forked from nixcn/nixcn-cms
Impl magic login logic && checkin logic
Signed-off-by: Asai Neko <sugar@sne.moe>
This commit is contained in:
@@ -13,7 +13,8 @@ email:
|
|||||||
resend_api_key: abc
|
resend_api_key: abc
|
||||||
from:
|
from:
|
||||||
secrets:
|
secrets:
|
||||||
jwt: something
|
jwt_secret: something
|
||||||
turnstile: something
|
turnstile_secret: something
|
||||||
ttl:
|
ttl:
|
||||||
magic_link: 15000
|
magic_link_ttl: 15000
|
||||||
|
jwt_ttl: 86400000
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ type email struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type secrets struct {
|
type secrets struct {
|
||||||
jwt string `yaml:"jwt"`
|
jwt_secret string `yaml:"jwt_secret"`
|
||||||
turnstile string `yaml:"turnstile"`
|
turnstile_secret string `yaml:"turnstile_secret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ttl struct {
|
type ttl struct {
|
||||||
magic_token string `yaml:"magin_token"`
|
magic_link_ttl string `yaml:"magic_link_ttl"`
|
||||||
|
jwt_ttl string `yaml:"jwt_ttl"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ func (self *User) GetByUserId(userId string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *User) SetCheckinState(email string, state bool) error {
|
func (self *User) SetCheckinState(userId uuid.UUID, state bool) error {
|
||||||
if err := Database.Where("email = ?", email).First(&self).Error; err != nil {
|
if err := Database.Where("user_id = ?", userId).First(&self).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
self.Checkin = state
|
self.Checkin = state
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type Claims struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func JWTAuth() gin.HandlerFunc {
|
func JWTAuth() gin.HandlerFunc {
|
||||||
var JwtSecret = []byte(viper.GetString("secrets.jwt"))
|
var JwtSecret = []byte(viper.GetString("secrets.jwt_secret"))
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
auth := c.GetHeader("Authorization")
|
auth := c.GetHeader("Authorization")
|
||||||
if auth == "" {
|
if auth == "" {
|
||||||
@@ -66,7 +66,7 @@ func GenerateToken(userID uuid.UUID, application string) (string, error) {
|
|||||||
claims := Claims{
|
claims := Claims{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(viper.GetDuration("ttl.jwt_ttl"))),
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
Issuer: application,
|
Issuer: application,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Token struct {
|
type Token struct {
|
||||||
@@ -17,7 +19,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Generate magic token
|
// Generate magic token
|
||||||
func NewMagicToken(email string, ttl time.Duration) (string, error) {
|
func NewMagicToken(email string) (string, error) {
|
||||||
b := make([]byte, 32)
|
b := make([]byte, 32)
|
||||||
if _, err := rand.Read(b); err != nil {
|
if _, err := rand.Read(b); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -27,7 +29,7 @@ func NewMagicToken(email string, ttl time.Duration) (string, error) {
|
|||||||
|
|
||||||
store.Store(token, Token{
|
store.Store(token, Token{
|
||||||
Email: email,
|
Email: email,
|
||||||
ExpiresAt: time.Now().Add(ttl),
|
ExpiresAt: time.Now().Add(viper.GetDuration("ttl.magic_link_ttl")),
|
||||||
})
|
})
|
||||||
|
|
||||||
return token, nil
|
return token, nil
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
func VerifyTurnstile(token, ip string) (bool, error) {
|
func VerifyTurnstile(token, ip string) (bool, error) {
|
||||||
form := url.Values{}
|
form := url.Values{}
|
||||||
form.Set("secret", viper.GetString("secrets.turnstile"))
|
form.Set("secret", viper.GetString("secrets.turnstile_secret"))
|
||||||
form.Set("response", token)
|
form.Set("response", token)
|
||||||
form.Set("remoteip", ip)
|
form.Set("remoteip", ip)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"nixcn-cms/internal/crypto/jwt"
|
"nixcn-cms/internal/crypto/jwt"
|
||||||
"nixcn-cms/pkgs/magiclink"
|
"nixcn-cms/pkgs/magiclink"
|
||||||
"nixcn-cms/pkgs/turnstile"
|
"nixcn-cms/pkgs/turnstile"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -35,7 +34,7 @@ func RequestMagicLink(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate magic token
|
// Generate magic token
|
||||||
token, err := magiclink.NewMagicToken(req.Email, 15*time.Minute)
|
token, err := magiclink.NewMagicToken(req.Email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, gin.H{"error": "internal error"})
|
c.JSON(500, gin.H{"error": "internal error"})
|
||||||
return
|
return
|
||||||
|
|||||||
24
service/checkin/checkin.go
Normal file
24
service/checkin/checkin.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package checkin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"nixcn-cms/data"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Checkin(ctx *gin.Context) {
|
||||||
|
data := new(data.User)
|
||||||
|
userId, ok := ctx.Get("user_id")
|
||||||
|
if !ok {
|
||||||
|
ctx.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"status": "unauthorized",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.SetCheckinState(userId.(uuid.UUID), true)
|
||||||
|
ctx.JSON(http.StatusOK, gin.H{
|
||||||
|
"status": "success",
|
||||||
|
})
|
||||||
|
}
|
||||||
11
service/info/handler.go
Normal file
11
service/info/handler.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package info
|
||||||
|
|
||||||
|
import (
|
||||||
|
"nixcn-cms/internal/crypto/jwt"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Handler(r *gin.RouterGroup) {
|
||||||
|
r.Use(jwt.JWTAuth())
|
||||||
|
}
|
||||||
1
service/info/userinfo.go
Normal file
1
service/info/userinfo.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package info
|
||||||
Reference in New Issue
Block a user