mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-05 07:26:36 +08:00
oauth
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/linux-do/credit/internal/apps/oauth"
|
||||
"github.com/linux-do/credit/internal/common"
|
||||
"github.com/linux-do/credit/internal/common/bind"
|
||||
"github.com/linux-do/credit/internal/common/response"
|
||||
"github.com/linux-do/credit/internal/db"
|
||||
"github.com/linux-do/credit/internal/model"
|
||||
"github.com/linux-do/credit/internal/util"
|
||||
)
|
||||
|
||||
type loginRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type registerRequest struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Nickname string `json:"nickname"`
|
||||
DisplayName string `json:"display_name"`
|
||||
}
|
||||
|
||||
func isPasswordLoginEnabled() bool {
|
||||
enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyPasswordLoginEnabled)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func isPasswordRegisterEnabled() bool {
|
||||
enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyPasswordRegisterEnabled)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func isRegistrationEnabled() bool {
|
||||
enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyRegistrationEnabled)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return enabled
|
||||
}
|
||||
|
||||
func setLoginSession(c *gin.Context, user *model.User) error {
|
||||
session := sessions.Default(c)
|
||||
session.Set(oauth.UserIDKey, user.ID)
|
||||
session.Set(oauth.UserNameKey, user.Username)
|
||||
if err := session.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Login 用户密码登录
|
||||
// @Summary 用户密码登录
|
||||
// @Description 使用用户名和密码登录,登录成功后建立 Session。若管理员已关闭密码登录功能则返回错误。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.loginRequest true "登录请求参数"
|
||||
// @Success 200 {object} util.ResponseAny{data=oauth.BasicUserInfo} "登录成功,返回用户信息"
|
||||
// @Failure 400 {object} util.ResponseAny "用户名或密码错误、帐号已禁用等"
|
||||
// @Failure 500 {object} util.ResponseAny "服务内部错误"
|
||||
// @Router /api/v1/user/login [post]
|
||||
func Login(c *gin.Context) {
|
||||
if !isPasswordLoginEnabled() {
|
||||
response.RespondFailure(c, "管理员关闭了密码登录")
|
||||
return
|
||||
}
|
||||
var req loginRequest
|
||||
if !bind.JSON(c, &req) {
|
||||
return
|
||||
}
|
||||
req.Username = strings.TrimSpace(req.Username)
|
||||
if req.Username == "" || req.Password == "" {
|
||||
response.RespondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
|
||||
var user model.User
|
||||
ctx := c.Request.Context()
|
||||
if err := db.DB(ctx).Where("username = ?", req.Username).First(&user).Error; err != nil {
|
||||
response.RespondFailure(c, "用户名或密码错误")
|
||||
return
|
||||
}
|
||||
if !user.IsActive {
|
||||
response.RespondFailure(c, common.BannedAccount)
|
||||
return
|
||||
}
|
||||
if !user.CheckPassword(req.Password) {
|
||||
response.RespondFailure(c, "用户名或密码错误")
|
||||
return
|
||||
}
|
||||
|
||||
user.LastLoginAt = time.Now()
|
||||
if err := db.DB(ctx).Model(&user).Update("last_login_at", user.LastLoginAt).Error; err != nil {
|
||||
response.RespondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err := setLoginSession(c, &user); err != nil {
|
||||
response.RespondFailure(c, "无法保存会话信息,请重试")
|
||||
return
|
||||
}
|
||||
|
||||
response.RespondSuccess(c, oauth.BuildBasicUserInfo(&user))
|
||||
}
|
||||
|
||||
// Register 用户注册
|
||||
// @Summary 用户注册
|
||||
// @Description 使用用户名和密码注册新账号,注册成功后自动登录并建立 Session。密码长度不能少于 8 位。
|
||||
// @Tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body user.registerRequest true "注册请求参数"
|
||||
// @Success 200 {object} util.ResponseAny{data=oauth.BasicUserInfo} "注册并登录成功,返回用户信息"
|
||||
// @Failure 400 {object} util.ResponseAny "参数错误、用户名已存在或注册已关闭"
|
||||
// @Failure 500 {object} util.ResponseAny "服务内部错误"
|
||||
// @Router /api/v1/user/register [post]
|
||||
func Register(c *gin.Context) {
|
||||
if !isRegistrationEnabled() || !isPasswordRegisterEnabled() {
|
||||
response.RespondFailure(c, "管理员关闭了注册")
|
||||
return
|
||||
}
|
||||
|
||||
var req registerRequest
|
||||
if !bind.JSON(c, &req) {
|
||||
return
|
||||
}
|
||||
|
||||
req.Username = strings.TrimSpace(req.Username)
|
||||
req.Password = strings.TrimSpace(req.Password)
|
||||
req.Nickname = strings.TrimSpace(req.Nickname)
|
||||
req.DisplayName = strings.TrimSpace(req.DisplayName)
|
||||
|
||||
if req.Username == "" || req.Password == "" {
|
||||
response.RespondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
if len(req.Password) < 8 {
|
||||
response.RespondFailure(c, "密码长度不能少于 8 位")
|
||||
return
|
||||
}
|
||||
|
||||
ctx := c.Request.Context()
|
||||
var count int64
|
||||
if err := db.DB(ctx).Model(&model.User{}).Where("username = ?", req.Username).Count(&count).Error; err != nil {
|
||||
response.RespondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if count > 0 {
|
||||
response.RespondFailure(c, "用户名已存在")
|
||||
return
|
||||
}
|
||||
|
||||
user := model.User{
|
||||
Username: req.Username,
|
||||
Nickname: req.Nickname,
|
||||
AvatarUrl: "",
|
||||
TrustLevel: model.TrustLevelNewUser,
|
||||
PayScore: 0,
|
||||
SignKey: util.GenerateUniqueIDSimple(),
|
||||
IsActive: true,
|
||||
IsAdmin: false,
|
||||
LastLoginAt: time.Now(),
|
||||
}
|
||||
if user.Nickname == "" {
|
||||
user.Nickname = req.DisplayName
|
||||
}
|
||||
if user.Nickname == "" {
|
||||
user.Nickname = req.Username
|
||||
}
|
||||
if err := user.SetPassword(req.Password); err != nil {
|
||||
response.RespondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := db.DB(ctx).Create(&user).Error; err != nil {
|
||||
response.RespondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if err := setLoginSession(c, &user); err != nil {
|
||||
response.RespondFailure(c, "无法保存会话信息,请重试")
|
||||
return
|
||||
}
|
||||
|
||||
response.RespondSuccess(c, oauth.BuildBasicUserInfo(&user))
|
||||
}
|
||||
|
||||
// Logout 用户退出登录
|
||||
// @Summary 用户退出登录
|
||||
// @Description 清除用户登录 Session,完成退出
|
||||
// @Tags user
|
||||
// @Produce json
|
||||
// @Security SessionCookie
|
||||
// @Success 200 {object} util.ResponseAny{data=string} "退出成功"
|
||||
// @Failure 500 {object} util.ResponseAny "Session 清除失败"
|
||||
// @Router /api/v1/user/logout [get]
|
||||
func Logout(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
session.Options(util.GetSessionOptions(-1))
|
||||
session.Clear()
|
||||
if err := session.Save(); err != nil {
|
||||
response.RespondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
response.RespondSuccessMessage(c, "")
|
||||
}
|
||||
Reference in New Issue
Block a user