✨ 新增几大中心功能
This commit is contained in:
37
server/api/v1/app/app_auth.go
Normal file
37
server/api/v1/app/app_auth.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
appModel "git.echol.cn/loser/Go-Web-Template/server/model/app"
|
||||
"git.echol.cn/loser/Go-Web-Template/server/model/common/response"
|
||||
"git.echol.cn/loser/Go-Web-Template/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type AppAuthApi struct{}
|
||||
|
||||
func (a *AppAuthApi) Me(c *gin.Context) {
|
||||
uid := utils.GetUserID(c)
|
||||
if uid == 0 {
|
||||
response.NoAuth("未登录或非法访问,请登录", c)
|
||||
return
|
||||
}
|
||||
var user appModel.AppUser
|
||||
if err := global.GVA_DB.First(&user, uid).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
response.NoAuth("用户不存在", c)
|
||||
return
|
||||
}
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(gin.H{
|
||||
"id": user.ID,
|
||||
"uuid": user.UUID,
|
||||
"username": user.Username,
|
||||
"enable": user.Enable,
|
||||
}, c)
|
||||
}
|
||||
7
server/api/v1/app/enter.go
Normal file
7
server/api/v1/app/enter.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package app
|
||||
|
||||
type ApiGroup struct {
|
||||
PublicAuthApi
|
||||
AppAuthApi
|
||||
InviteCodeApi
|
||||
}
|
||||
50
server/api/v1/app/invite_code.go
Normal file
50
server/api/v1/app/invite_code.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.echol.cn/loser/Go-Web-Template/server/model/common/response"
|
||||
appSvc "git.echol.cn/loser/Go-Web-Template/server/service/app"
|
||||
"git.echol.cn/loser/Go-Web-Template/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type InviteCodeApi struct{}
|
||||
|
||||
type inviteCodeCurrentResponse struct {
|
||||
HasUnused bool `json:"hasUnused"`
|
||||
Record interface{} `json:"record,omitempty"`
|
||||
}
|
||||
|
||||
// GenerateInviteCode 玩家生成邀请码(返回明文)
|
||||
func (a *InviteCodeApi) GenerateInviteCode(c *gin.Context) {
|
||||
uid := utils.GetUserID(c)
|
||||
res, err := appSvc.AppInviteCodeServiceApp.Generate(uid)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
response.OkWithData(res, c)
|
||||
}
|
||||
|
||||
// CurrentInviteCode 获取当前未使用邀请码(不返回明文)
|
||||
func (a *InviteCodeApi) CurrentInviteCode(c *gin.Context) {
|
||||
uid := utils.GetUserID(c)
|
||||
rec, err := appSvc.AppInviteCodeServiceApp.GetCurrentUnused(uid)
|
||||
if err != nil {
|
||||
response.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
if rec == nil {
|
||||
response.OkWithData(inviteCodeCurrentResponse{HasUnused: false}, c)
|
||||
return
|
||||
}
|
||||
payload := map[string]interface{}{
|
||||
"id": rec.ID,
|
||||
"codeLast4": rec.CodeLast4,
|
||||
"status": rec.Status,
|
||||
"expiresAt": rec.ExpiresAt,
|
||||
"createdAt": rec.CreatedAt.Format(time.RFC3339),
|
||||
}
|
||||
response.OkWithData(inviteCodeCurrentResponse{HasUnused: true, Record: payload}, c)
|
||||
}
|
||||
122
server/api/v1/app/public_auth.go
Normal file
122
server/api/v1/app/public_auth.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
appModel "git.echol.cn/loser/Go-Web-Template/server/model/app"
|
||||
appReq "git.echol.cn/loser/Go-Web-Template/server/model/app/request"
|
||||
appRes "git.echol.cn/loser/Go-Web-Template/server/model/app/response"
|
||||
commonResp "git.echol.cn/loser/Go-Web-Template/server/model/common/response"
|
||||
systemReq "git.echol.cn/loser/Go-Web-Template/server/model/system/request"
|
||||
appSvc "git.echol.cn/loser/Go-Web-Template/server/service/app"
|
||||
"git.echol.cn/loser/Go-Web-Template/server/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/mojocn/base64Captcha"
|
||||
)
|
||||
|
||||
type PublicAuthApi struct{}
|
||||
|
||||
func (a *PublicAuthApi) RegisterStatus(c *gin.Context) {
|
||||
mode := appRes.RegisterMode(appSvc.GetRegisterMode())
|
||||
requireCaptcha := appSvc.GetRegisterRequireCaptcha()
|
||||
expireHours := appSvc.GetInviteExpireHours()
|
||||
payload := appRes.RegisterStatusResponse{
|
||||
Mode: mode,
|
||||
RequireCaptcha: requireCaptcha,
|
||||
InviteExpireHours: expireHours,
|
||||
}
|
||||
if mode == appRes.RegisterModeClosed {
|
||||
payload.Message = "暂不开放注册"
|
||||
}
|
||||
commonResp.OkWithData(payload, c)
|
||||
}
|
||||
|
||||
func (a *PublicAuthApi) Register(c *gin.Context) {
|
||||
var req appReq.PublicRegister
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
commonResp.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
mode := appSvc.GetRegisterMode()
|
||||
if mode == appSvc.RegisterModeClosed {
|
||||
commonResp.FailWithMessage("注册未开放", c)
|
||||
return
|
||||
}
|
||||
|
||||
// 可选验证码(复用 base64Captcha 默认内存 store)
|
||||
if appSvc.GetRegisterRequireCaptcha() {
|
||||
if req.Captcha == "" || req.CaptchaId == "" || !base64Captcha.DefaultMemStore.Verify(req.CaptchaId, req.Captcha, true) {
|
||||
commonResp.FailWithMessage("验证码错误", c)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
req.Username = strings.TrimSpace(req.Username)
|
||||
req.WelcomePhrase = strings.TrimSpace(req.WelcomePhrase)
|
||||
|
||||
if err := appSvc.AppRegisterServiceApp.Register(req, mode); err != nil {
|
||||
commonResp.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
commonResp.OkWithMessage("注册成功", c)
|
||||
}
|
||||
|
||||
func (a *PublicAuthApi) Login(c *gin.Context) {
|
||||
var req appReq.Login
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
commonResp.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
req.Username = strings.TrimSpace(req.Username)
|
||||
|
||||
user, err := appSvc.AppAuthServiceApp.Login(req.Username, req.Password)
|
||||
if err != nil {
|
||||
// 记录失败登录日志(不阻断业务返回)
|
||||
_ = global.GVA_DB.Create(&appModel.AppLoginLog{
|
||||
AppUserID: 0,
|
||||
Username: req.Username,
|
||||
IP: c.ClientIP(),
|
||||
Referer: c.GetHeader("Referer"),
|
||||
UserAgent: c.GetHeader("User-Agent"),
|
||||
Status: false,
|
||||
ErrorMessage: err.Error(),
|
||||
}).Error
|
||||
commonResp.FailWithMessage(err.Error(), c)
|
||||
return
|
||||
}
|
||||
|
||||
// 记录最后登录与活跃
|
||||
_ = appSvc.AppActivityServiceApp.RecordLogin(user.ID, c.ClientIP())
|
||||
// 记录成功登录日志(不阻断业务返回)
|
||||
_ = global.GVA_DB.Create(&appModel.AppLoginLog{
|
||||
AppUserID: user.ID,
|
||||
Username: user.Username,
|
||||
IP: c.ClientIP(),
|
||||
Referer: c.GetHeader("Referer"),
|
||||
UserAgent: c.GetHeader("User-Agent"),
|
||||
Status: true,
|
||||
}).Error
|
||||
|
||||
j := utils.NewJWT()
|
||||
claims := j.CreateAppClaims(utilsBaseClaimsFromAppUser(user))
|
||||
token, err := j.CreateToken(claims)
|
||||
if err != nil {
|
||||
commonResp.FailWithMessage("获取token失败", c)
|
||||
return
|
||||
}
|
||||
commonResp.OkWithData(gin.H{
|
||||
"token": token,
|
||||
}, c)
|
||||
}
|
||||
|
||||
func utilsBaseClaimsFromAppUser(user *appModel.AppUser) systemReq.BaseClaims {
|
||||
return systemReq.BaseClaims{
|
||||
UUID: user.UUID,
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
NickName: user.Username,
|
||||
AuthorityId: 0,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user