mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 14:06:36 +08:00
[优化] 代码优化
This commit is contained in:
@@ -26,7 +26,7 @@ var OptionMapRWMutex sync.RWMutex
|
||||
var ItemsPerPage = 10
|
||||
|
||||
var PasswordLoginEnabled = true
|
||||
var PasswordRegisterEnabled = true
|
||||
var PasswordRegisterEnabled = false
|
||||
var EmailVerificationEnabled = false
|
||||
var GitHubOAuthEnabled = false
|
||||
var WeChatAuthEnabled = false
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
"openflare/service"
|
||||
@@ -25,65 +23,43 @@ func GetStatus(c *gin.Context) {
|
||||
if err != nil {
|
||||
authSources = []service.PublicAuthSource{}
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": gin.H{
|
||||
"version": common.Version,
|
||||
"start_time": common.StartTime,
|
||||
"email_verification": common.EmailVerificationEnabled,
|
||||
"github_oauth": common.GitHubOAuthEnabled,
|
||||
"github_client_id": common.GitHubClientId,
|
||||
"system_name": common.SystemName,
|
||||
"home_page_link": common.HomePageLink,
|
||||
"footer_html": common.Footer,
|
||||
"wechat_qrcode": common.WeChatAccountQRCodeImageURL,
|
||||
"wechat_login": common.WeChatAuthEnabled,
|
||||
"server_address": common.ServerAddress,
|
||||
"register_enabled": common.RegisterEnabled,
|
||||
"password_register_enabled": common.PasswordRegisterEnabled,
|
||||
"auth_sources": authSources,
|
||||
},
|
||||
respondSuccess(c, gin.H{
|
||||
"version": common.Version,
|
||||
"start_time": common.StartTime,
|
||||
"email_verification": common.EmailVerificationEnabled,
|
||||
"github_oauth": common.GitHubOAuthEnabled,
|
||||
"github_client_id": common.GitHubClientId,
|
||||
"system_name": common.SystemName,
|
||||
"home_page_link": common.HomePageLink,
|
||||
"footer_html": common.Footer,
|
||||
"wechat_qrcode": common.WeChatAccountQRCodeImageURL,
|
||||
"wechat_login": common.WeChatAuthEnabled,
|
||||
"server_address": common.ServerAddress,
|
||||
"password_register_enabled": common.PasswordRegisterEnabled,
|
||||
"auth_sources": authSources,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func GetNotice(c *gin.Context) {
|
||||
common.OptionMapRWMutex.RLock()
|
||||
defer common.OptionMapRWMutex.RUnlock()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": common.OptionMap["Notice"],
|
||||
})
|
||||
return
|
||||
respondSuccess(c, common.OptionMap["Notice"])
|
||||
}
|
||||
|
||||
func GetAbout(c *gin.Context) {
|
||||
common.OptionMapRWMutex.RLock()
|
||||
defer common.OptionMapRWMutex.RUnlock()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": common.OptionMap["About"],
|
||||
})
|
||||
return
|
||||
respondSuccess(c, common.OptionMap["About"])
|
||||
}
|
||||
|
||||
func SendEmailVerification(c *gin.Context) {
|
||||
email := c.Query("email")
|
||||
if err := validation.Validate.Var(email, "required,email"); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
respondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
if model.IsEmailAlreadyTaken(email) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "邮箱地址已被占用",
|
||||
})
|
||||
respondFailure(c, "邮箱地址已被占用")
|
||||
return
|
||||
}
|
||||
code := security.GenerateVerificationCode(6)
|
||||
@@ -101,33 +77,20 @@ func SendEmailVerification(c *gin.Context) {
|
||||
}
|
||||
err := mail.SendEmail(cfg, subject, email, content)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func SendPasswordResetEmail(c *gin.Context) {
|
||||
email := c.Query("email")
|
||||
if err := validation.Validate.Var(email, "required,email"); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
respondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
if !model.IsEmailAlreadyTaken(email) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "该邮箱地址未注册",
|
||||
})
|
||||
respondFailure(c, "该邮箱地址未注册")
|
||||
return
|
||||
}
|
||||
code := security.GenerateVerificationCode(0)
|
||||
@@ -146,17 +109,10 @@ func SendPasswordResetEmail(c *gin.Context) {
|
||||
}
|
||||
err := mail.SendEmail(cfg, subject, email, content)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
type PasswordResetRequest struct {
|
||||
@@ -166,35 +122,23 @@ type PasswordResetRequest struct {
|
||||
|
||||
func ResetPassword(c *gin.Context) {
|
||||
var req PasswordResetRequest
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&req)
|
||||
if !bindJSON(c, &req) {
|
||||
return
|
||||
}
|
||||
if req.Email == "" || req.Token == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
respondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
if !security.VerifyCodeWithKey(req.Email, req.Token, security.PasswordResetPurpose) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "重置链接非法或已过期",
|
||||
})
|
||||
respondFailure(c, "重置链接非法或已过期")
|
||||
return
|
||||
}
|
||||
password := security.GenerateVerificationCode(12)
|
||||
err = model.ResetUserPasswordByEmail(req.Email, password)
|
||||
err := model.ResetUserPasswordByEmail(req.Email, password)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
security.DeleteKey(req.Email, security.PasswordResetPurpose)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": password,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, password)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
"openflare/service"
|
||||
@@ -231,11 +229,11 @@ func validateOptionWithState(option model.Option, state map[string]string) error
|
||||
switch option.Key {
|
||||
case "GitHubOAuthEnabled":
|
||||
if option.Value == "true" && strings.TrimSpace(state["GitHubClientId"]) == "" {
|
||||
return fmt.Errorf("鏃犳硶鍚敤 GitHub OAuth锛岃鍏堝~鍏?GitHub Client ID 浠ュ強 GitHub Client Secret锛?")
|
||||
return fmt.Errorf("无法启用 GitHub OAuth,请先填入 GitHub Client ID 以及 GitHub Client Secret!")
|
||||
}
|
||||
case "WeChatAuthEnabled":
|
||||
if option.Value == "true" && strings.TrimSpace(state["WeChatServerAddress"]) == "" {
|
||||
return fmt.Errorf("鏃犳硶鍚敤寰俊鐧诲綍锛岃鍏堝~鍏ュ井淇$櫥褰曠浉鍏抽厤缃俊鎭紒")
|
||||
return fmt.Errorf("无法启用微信登录,请先填入微信登录相关配置信息!")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -260,13 +258,13 @@ func validateOptionWithState(option model.Option, state map[string]string) error
|
||||
|
||||
func updateOptions(options []model.Option) error {
|
||||
if len(options) == 0 {
|
||||
return fmt.Errorf("鏃犳晥鐨勫弬鏁?")
|
||||
return fmt.Errorf("无效的参数")
|
||||
}
|
||||
|
||||
state := buildOptionValidationState(options)
|
||||
for _, option := range options {
|
||||
if strings.TrimSpace(option.Key) == "" {
|
||||
return fmt.Errorf("鏃犳晥鐨勫弬鏁?")
|
||||
return fmt.Errorf("无效的参数")
|
||||
}
|
||||
if err := validateOptionWithState(option, state); err != nil {
|
||||
return err
|
||||
@@ -295,12 +293,7 @@ func GetOptions(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
common.OptionMapRWMutex.Unlock()
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": options,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, options)
|
||||
}
|
||||
|
||||
// UpdateOption godoc
|
||||
@@ -314,80 +307,47 @@ func GetOptions(c *gin.Context) {
|
||||
// @Router /api/option/update [post]
|
||||
func UpdateOption(c *gin.Context) {
|
||||
var option model.Option
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&option)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
if !bindJSON(c, &option) {
|
||||
return
|
||||
}
|
||||
switch option.Key {
|
||||
case "GitHubOAuthEnabled":
|
||||
if option.Value == "true" && common.GitHubClientId == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法启用 GitHub OAuth,请先填入 GitHub Client ID 以及 GitHub Client Secret!",
|
||||
})
|
||||
respondFailure(c, "无法启用 GitHub OAuth,请先填入 GitHub Client ID 以及 GitHub Client Secret!")
|
||||
return
|
||||
}
|
||||
case "WeChatAuthEnabled":
|
||||
if option.Value == "true" && common.WeChatServerAddress == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法启用微信登录,请先填入微信登录相关配置信息!",
|
||||
})
|
||||
respondFailure(c, "无法启用微信登录,请先填入微信登录相关配置信息!")
|
||||
return
|
||||
}
|
||||
}
|
||||
if err = validateRateLimitOption(option.Key, option.Value); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
if err := validateRateLimitOption(option.Key, option.Value); err != nil {
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err = validateOpenRestyOption(option.Key, option.Value); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
if err := validateOpenRestyOption(option.Key, option.Value); err != nil {
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err = validateGeoIPOption(option.Key, option.Value); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
if err := validateGeoIPOption(option.Key, option.Value); err != nil {
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err = validateDatabaseCleanupOption(option.Key, option.Value); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
if err := validateDatabaseCleanupOption(option.Key, option.Value); err != nil {
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if err = validateAgentOption(option.Key, option.Value); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
if err := validateAgentOption(option.Key, option.Value); err != nil {
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
err = model.UpdateOption(option.Key, option.Value)
|
||||
err := model.UpdateOption(option.Key, option.Value)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
// UpdateOptionsBatch godoc
|
||||
@@ -401,24 +361,18 @@ func UpdateOption(c *gin.Context) {
|
||||
// @Router /api/option/update-batch [post]
|
||||
func UpdateOptionsBatch(c *gin.Context) {
|
||||
var payload optionBatchPayload
|
||||
if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil || len(payload.Options) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"success": false,
|
||||
"message": "鏃犳晥鐨勫弬鏁?",
|
||||
})
|
||||
if !bindJSON(c, &payload) {
|
||||
return
|
||||
}
|
||||
if len(payload.Options) == 0 {
|
||||
respondBadRequest(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
|
||||
if err := updateOptions(payload.Options); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"openflare/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func GetOrigins(c *gin.Context) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"openflare/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetProxyRoutes godoc
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"openflare/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetTLSCertificates godoc
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
"openflare/utils/security"
|
||||
@@ -22,40 +20,26 @@ type LoginRequest struct {
|
||||
|
||||
func Login(c *gin.Context) {
|
||||
if !common.PasswordLoginEnabled {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "管理员关闭了密码登录",
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, "管理员关闭了密码登录")
|
||||
return
|
||||
}
|
||||
var loginRequest LoginRequest
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&loginRequest)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "无效的参数",
|
||||
"success": false,
|
||||
})
|
||||
if !bindJSON(c, &loginRequest) {
|
||||
return
|
||||
}
|
||||
username := loginRequest.Username
|
||||
password := loginRequest.Password
|
||||
if username == "" || password == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "无效的参数",
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
user := model.User{
|
||||
Username: username,
|
||||
Password: password,
|
||||
}
|
||||
err = user.ValidateAndFill()
|
||||
err := user.ValidateAndFill()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": err.Error(),
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
setupLogin(&user, c)
|
||||
@@ -96,24 +80,14 @@ func Logout(c *gin.Context) {
|
||||
session.Clear()
|
||||
err := session.Save()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": err.Error(),
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "",
|
||||
"success": true,
|
||||
})
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func Register(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "非法请求",
|
||||
"success": false,
|
||||
})
|
||||
return
|
||||
respondFailure(c, "非法请求")
|
||||
}
|
||||
|
||||
func GetAllUsers(c *gin.Context) {
|
||||
@@ -123,167 +97,101 @@ func GetAllUsers(c *gin.Context) {
|
||||
}
|
||||
users, err := model.GetAllUsers(p*common.ItemsPerPage, common.ItemsPerPage)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": users,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, users)
|
||||
}
|
||||
|
||||
func SearchUsers(c *gin.Context) {
|
||||
keyword := c.Query("keyword")
|
||||
users, err := model.SearchUsers(keyword)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": users,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, users)
|
||||
}
|
||||
|
||||
func GetUser(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
id, ok := parseIDParam(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
user, err := model.GetUserById(id, false)
|
||||
user, err := model.GetUserById(int(id), false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
myRole := c.GetInt("role")
|
||||
if myRole <= user.Role {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无权获取同级或更高等级用户的信息",
|
||||
})
|
||||
respondFailure(c, "无权获取同级或更高等级用户的信息")
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": user,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, user)
|
||||
}
|
||||
|
||||
func GenerateToken(c *gin.Context) {
|
||||
id := c.GetInt("id")
|
||||
user, err := model.GetUserById(id, true)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
user.Token = uuid.New().String()
|
||||
user.Token = strings.Replace(user.Token, "-", "", -1)
|
||||
|
||||
if model.DB.Where("token = ?", user.Token).First(user).RowsAffected != 0 {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "请重试,系统生成的 UUID 竟然重复了!",
|
||||
})
|
||||
respondFailure(c, "请重试,系统生成的 UUID 竟然重复了!")
|
||||
return
|
||||
}
|
||||
|
||||
if err := user.Update(false); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": user.Token,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, user.Token)
|
||||
}
|
||||
|
||||
func GetSelf(c *gin.Context) {
|
||||
id := c.GetInt("id")
|
||||
user, err := model.GetUserById(id, false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": user,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, user)
|
||||
}
|
||||
|
||||
func UpdateUser(c *gin.Context) {
|
||||
var updatedUser model.User
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&updatedUser)
|
||||
if err != nil || updatedUser.Id == 0 {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
if !bindJSON(c, &updatedUser) {
|
||||
return
|
||||
}
|
||||
if updatedUser.Id == 0 {
|
||||
respondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
if updatedUser.Password == "" {
|
||||
updatedUser.Password = "$I_LOVE_U" // make Validator happy :)
|
||||
}
|
||||
if err := validation.Validate.Struct(&updatedUser); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "输入不合法 " + err.Error(),
|
||||
})
|
||||
respondFailure(c, "输入不合法 "+err.Error())
|
||||
return
|
||||
}
|
||||
originUser, err := model.GetUserById(updatedUser.Id, false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
myRole := c.GetInt("role")
|
||||
if myRole <= originUser.Role {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无权更新同权限等级或更高权限等级的用户信息",
|
||||
})
|
||||
respondFailure(c, "无权更新同权限等级或更高权限等级的用户信息")
|
||||
return
|
||||
}
|
||||
if myRole <= updatedUser.Role {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无权将其他用户权限等级提升到大于等于自己的权限等级",
|
||||
})
|
||||
respondFailure(c, "无权将其他用户权限等级提升到大于等于自己的权限等级")
|
||||
return
|
||||
}
|
||||
if updatedUser.Password == "$I_LOVE_U" {
|
||||
@@ -291,37 +199,22 @@ func UpdateUser(c *gin.Context) {
|
||||
}
|
||||
updatePassword := updatedUser.Password != ""
|
||||
if err := updatedUser.Update(updatePassword); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func UpdateSelf(c *gin.Context) {
|
||||
var user model.User
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&user)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
if !bindJSON(c, &user) {
|
||||
return
|
||||
}
|
||||
if user.Password == "" {
|
||||
user.Password = "$I_LOVE_U" // make Validator happy :)
|
||||
}
|
||||
if err := validation.Validate.Struct(&user); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "输入不合法 " + err.Error(),
|
||||
})
|
||||
respondFailure(c, "输入不合法 "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -337,80 +230,53 @@ func UpdateSelf(c *gin.Context) {
|
||||
}
|
||||
updatePassword := user.Password != ""
|
||||
if err := cleanUser.Update(updatePassword); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func DeleteUser(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
id, ok := parseIDParam(c)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
originUser, err := model.GetUserById(id, false)
|
||||
originUser, err := model.GetUserById(int(id), false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
myRole := c.GetInt("role")
|
||||
if myRole <= originUser.Role {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无权删除同权限等级或更高权限等级的用户",
|
||||
})
|
||||
respondFailure(c, "无权删除同权限等级或更高权限等级的用户")
|
||||
return
|
||||
}
|
||||
err = model.DeleteUserById(id)
|
||||
err = model.DeleteUserById(int(id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func DeleteSelf(c *gin.Context) {
|
||||
id := c.GetInt("id")
|
||||
err := model.DeleteUserById(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func CreateUser(c *gin.Context) {
|
||||
var user model.User
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&user)
|
||||
if err != nil || user.Username == "" || user.Password == "" {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
if !bindJSON(c, &user) {
|
||||
return
|
||||
}
|
||||
if user.Username == "" || user.Password == "" {
|
||||
respondFailure(c, "无效的参数")
|
||||
return
|
||||
}
|
||||
if user.DisplayName == "" {
|
||||
@@ -418,10 +284,7 @@ func CreateUser(c *gin.Context) {
|
||||
}
|
||||
myRole := c.GetInt("role")
|
||||
if user.Role >= myRole {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法创建权限大于等于自己的用户",
|
||||
})
|
||||
respondFailure(c, "无法创建权限大于等于自己的用户")
|
||||
return
|
||||
}
|
||||
// Even for admin users, we cannot fully trust them!
|
||||
@@ -431,18 +294,11 @@ func CreateUser(c *gin.Context) {
|
||||
DisplayName: user.DisplayName,
|
||||
}
|
||||
if err := cleanUser.Insert(); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
type ManageRequest struct {
|
||||
@@ -453,13 +309,7 @@ type ManageRequest struct {
|
||||
// ManageUser Only admin user can do this
|
||||
func ManageUser(c *gin.Context) {
|
||||
var req ManageRequest
|
||||
err := json.NewDecoder(c.Request.Body).Decode(&req)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无效的参数",
|
||||
})
|
||||
if !bindJSON(c, &req) {
|
||||
return
|
||||
}
|
||||
user := model.User{
|
||||
@@ -468,108 +318,70 @@ func ManageUser(c *gin.Context) {
|
||||
// Fill attributes
|
||||
model.DB.Where(&user).First(&user)
|
||||
if user.Id == 0 {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "用户不存在",
|
||||
})
|
||||
respondFailure(c, "用户不存在")
|
||||
return
|
||||
}
|
||||
myRole := c.GetInt("role")
|
||||
if myRole <= user.Role && myRole != common.RoleRootUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无权更新同权限等级或更高权限等级的用户信息",
|
||||
})
|
||||
respondFailure(c, "无权更新同权限等级或更高权限等级的用户信息")
|
||||
return
|
||||
}
|
||||
switch req.Action {
|
||||
case "disable":
|
||||
user.Status = common.UserStatusDisabled
|
||||
if user.Role == common.RoleRootUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法禁用超级管理员用户",
|
||||
})
|
||||
respondFailure(c, "无法禁用超级管理员用户")
|
||||
return
|
||||
}
|
||||
case "enable":
|
||||
user.Status = common.UserStatusEnabled
|
||||
case "delete":
|
||||
if user.Role == common.RoleRootUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法删除超级管理员用户",
|
||||
})
|
||||
respondFailure(c, "无法删除超级管理员用户")
|
||||
return
|
||||
}
|
||||
if err := user.Delete(); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
case "promote":
|
||||
if myRole != common.RoleRootUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "普通管理员用户无法提升其他用户为管理员",
|
||||
})
|
||||
respondFailure(c, "普通管理员用户无法提升其他用户为管理员")
|
||||
return
|
||||
}
|
||||
if user.Role >= common.RoleAdminUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "该用户已经是管理员",
|
||||
})
|
||||
respondFailure(c, "该用户已经是管理员")
|
||||
return
|
||||
}
|
||||
user.Role = common.RoleAdminUser
|
||||
case "demote":
|
||||
if user.Role == common.RoleRootUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无法降级超级管理员用户",
|
||||
})
|
||||
respondFailure(c, "无法降级超级管理员用户")
|
||||
return
|
||||
}
|
||||
if user.Role == common.RoleCommonUser {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "该用户已经是普通用户",
|
||||
})
|
||||
respondFailure(c, "该用户已经是普通用户")
|
||||
return
|
||||
}
|
||||
user.Role = common.RoleCommonUser
|
||||
}
|
||||
|
||||
if err := user.Update(false); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
clearUser := model.User{
|
||||
Role: user.Role,
|
||||
Status: user.Status,
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
"data": clearUser,
|
||||
})
|
||||
return
|
||||
respondSuccess(c, clearUser)
|
||||
}
|
||||
|
||||
func EmailBind(c *gin.Context) {
|
||||
email := c.Query("email")
|
||||
code := c.Query("code")
|
||||
if !security.VerifyCodeWithKey(email, code, security.EmailVerificationPurpose) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "验证码错误或已过期",
|
||||
})
|
||||
respondFailure(c, "验证码错误或已过期")
|
||||
return
|
||||
}
|
||||
id := c.GetInt("id")
|
||||
@@ -578,25 +390,15 @@ func EmailBind(c *gin.Context) {
|
||||
}
|
||||
err := user.FillUserById()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
user.Email = email
|
||||
// no need to check if this email already taken, because we have used verification code to check it
|
||||
err = user.Update(false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
return
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"openflare/service"
|
||||
"strconv"
|
||||
|
||||
@@ -16,10 +14,10 @@ type wafIDsRequest struct {
|
||||
func ListWAFRuleGroups(c *gin.Context) {
|
||||
groups, err := service.ListWAFRuleGroups()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": groups})
|
||||
respondSuccess(c, groups)
|
||||
}
|
||||
|
||||
func GetWAFRuleGroup(c *gin.Context) {
|
||||
@@ -29,24 +27,23 @@ func GetWAFRuleGroup(c *gin.Context) {
|
||||
}
|
||||
group, err := service.GetWAFRuleGroup(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": group})
|
||||
respondSuccess(c, group)
|
||||
}
|
||||
|
||||
func CreateWAFRuleGroup(c *gin.Context) {
|
||||
var input service.WAFRuleGroupInput
|
||||
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "invalid payload"})
|
||||
if !bindJSON(c, &input) {
|
||||
return
|
||||
}
|
||||
group, err := service.CreateWAFRuleGroup(input)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": group})
|
||||
respondSuccess(c, group)
|
||||
}
|
||||
|
||||
func UpdateWAFRuleGroup(c *gin.Context) {
|
||||
@@ -55,16 +52,15 @@ func UpdateWAFRuleGroup(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
var input service.WAFRuleGroupInput
|
||||
if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "invalid payload"})
|
||||
if !bindJSON(c, &input) {
|
||||
return
|
||||
}
|
||||
group, err := service.UpdateWAFRuleGroup(id, input)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": group})
|
||||
respondSuccess(c, group)
|
||||
}
|
||||
|
||||
func DeleteWAFRuleGroup(c *gin.Context) {
|
||||
@@ -73,10 +69,10 @@ func DeleteWAFRuleGroup(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
if err := service.DeleteWAFRuleGroup(id); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": ""})
|
||||
respondSuccessMessage(c, "")
|
||||
}
|
||||
|
||||
func ReplaceWAFRuleGroupSites(c *gin.Context) {
|
||||
@@ -85,16 +81,15 @@ func ReplaceWAFRuleGroupSites(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
var request wafIDsRequest
|
||||
if err := json.NewDecoder(c.Request.Body).Decode(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "invalid payload"})
|
||||
if !bindJSON(c, &request) {
|
||||
return
|
||||
}
|
||||
group, err := service.ReplaceWAFRuleGroupSites(id, request.IDs)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": group})
|
||||
respondSuccess(c, group)
|
||||
}
|
||||
|
||||
func GetWAFSiteRuleGroups(c *gin.Context) {
|
||||
@@ -104,10 +99,10 @@ func GetWAFSiteRuleGroups(c *gin.Context) {
|
||||
}
|
||||
view, err := service.GetWAFSiteRuleGroups(routeID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": view})
|
||||
respondSuccess(c, view)
|
||||
}
|
||||
|
||||
func ReplaceWAFSiteRuleGroups(c *gin.Context) {
|
||||
@@ -116,22 +111,21 @@ func ReplaceWAFSiteRuleGroups(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
var request wafIDsRequest
|
||||
if err := json.NewDecoder(c.Request.Body).Decode(&request); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "invalid payload"})
|
||||
if !bindJSON(c, &request) {
|
||||
return
|
||||
}
|
||||
view, err := service.ReplaceWAFSiteRuleGroups(routeID, request.IDs)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "message": err.Error()})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "", "data": view})
|
||||
respondSuccess(c, view)
|
||||
}
|
||||
|
||||
func parseUintPathParam(c *gin.Context, name string) (uint, bool) {
|
||||
id, err := strconv.ParseUint(c.Param(name), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "message": "invalid id"})
|
||||
respondBadRequest(c, "invalid id")
|
||||
return 0, false
|
||||
}
|
||||
return uint(id), true
|
||||
|
||||
@@ -4,12 +4,14 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type wechatLoginResponse struct {
|
||||
@@ -34,7 +36,12 @@ func getWeChatIdByCode(code string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer httpResponse.Body.Close()
|
||||
defer func(Body io.ReadCloser) {
|
||||
err := Body.Close()
|
||||
if err != nil {
|
||||
slog.Error("Failed to close response body", "error", err)
|
||||
}
|
||||
}(httpResponse.Body)
|
||||
var res wechatLoginResponse
|
||||
err = json.NewDecoder(httpResponse.Body).Decode(&res)
|
||||
if err != nil {
|
||||
@@ -51,19 +58,13 @@ func getWeChatIdByCode(code string) (string, error) {
|
||||
|
||||
func WeChatAuth(c *gin.Context) {
|
||||
if !common.WeChatAuthEnabled {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "管理员未开启通过微信登录以及注册",
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, "管理员未开启通过微信登录以及注册")
|
||||
return
|
||||
}
|
||||
code := c.Query("code")
|
||||
wechatId, err := getWeChatIdByCode(code)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": err.Error(),
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
user := model.User{
|
||||
@@ -72,40 +73,16 @@ func WeChatAuth(c *gin.Context) {
|
||||
if model.IsWeChatIdAlreadyTaken(wechatId) {
|
||||
err := user.FillUserByWeChatId()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if common.RegisterEnabled {
|
||||
user.Username = "wechat_" + strconv.Itoa(model.GetMaxUserId()+1)
|
||||
user.DisplayName = "WeChat User"
|
||||
user.Role = common.RoleCommonUser
|
||||
user.Status = common.UserStatusEnabled
|
||||
|
||||
if err := user.Insert(); err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "管理员关闭了新用户注册",
|
||||
})
|
||||
return
|
||||
}
|
||||
respondFailure(c, "管理员关闭了新用户注册")
|
||||
return
|
||||
}
|
||||
|
||||
if user.Status != common.UserStatusEnabled {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "用户已被封禁",
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, "用户已被封禁")
|
||||
return
|
||||
}
|
||||
setupLogin(&user, c)
|
||||
@@ -113,26 +90,17 @@ func WeChatAuth(c *gin.Context) {
|
||||
|
||||
func WeChatBind(c *gin.Context) {
|
||||
if !common.WeChatAuthEnabled {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "管理员未开启通过微信登录以及注册",
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, "管理员未开启通过微信登录以及注册")
|
||||
return
|
||||
}
|
||||
code := c.Query("code")
|
||||
wechatId, err := getWeChatIdByCode(code)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": err.Error(),
|
||||
"success": false,
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
if model.IsWeChatIdAlreadyTaken(wechatId) {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "该微信账号已被绑定",
|
||||
})
|
||||
respondFailure(c, "该微信账号已被绑定")
|
||||
return
|
||||
}
|
||||
id := c.GetInt("id")
|
||||
@@ -141,24 +109,15 @@ func WeChatBind(c *gin.Context) {
|
||||
}
|
||||
err = user.FillUserById()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
user.WeChatId = wechatId
|
||||
err = user.Update(false)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": err.Error(),
|
||||
})
|
||||
respondFailure(c, err.Error())
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"message": "",
|
||||
})
|
||||
respondSuccessMessage(c, "")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"github.com/robfig/cron/v3"
|
||||
"log/slog"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
var cronRunner *cron.Cron
|
||||
|
||||
@@ -2,12 +2,13 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gin-gonic/gin"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"openflare/common"
|
||||
"openflare/utils/ratelimit"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var timeFormat = "2006-01-02T15:04:05.000Z"
|
||||
@@ -52,11 +53,11 @@ func redisRateLimiter(c *gin.Context, maxRequestNum int, duration int64, mark st
|
||||
c.Status(http.StatusTooManyRequests)
|
||||
c.Abort()
|
||||
return
|
||||
} else {
|
||||
rdb.LPush(ctx, key, time.Now().Format(timeFormat))
|
||||
rdb.LTrim(ctx, key, 0, int64(maxRequestNum-1))
|
||||
rdb.Expire(ctx, key, common.RateLimitKeyExpirationDuration)
|
||||
}
|
||||
|
||||
rdb.LPush(ctx, key, time.Now().Format(timeFormat))
|
||||
rdb.LTrim(ctx, key, 0, int64(maxRequestNum-1))
|
||||
rdb.Expire(ctx, key, common.RateLimitKeyExpirationDuration)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,12 +75,12 @@ func rateLimitFactory(maxRequestNum int, duration int64, mark string) func(c *gi
|
||||
return func(c *gin.Context) {
|
||||
redisRateLimiter(c, maxRequestNum, duration, mark)
|
||||
}
|
||||
} else {
|
||||
// It's safe to call multi times.
|
||||
inMemoryRateLimiter.Init(common.RateLimitKeyExpirationDuration)
|
||||
return func(c *gin.Context) {
|
||||
memoryRateLimiter(c, maxRequestNum, duration, mark)
|
||||
}
|
||||
}
|
||||
|
||||
// It's safe to call multi times.
|
||||
inMemoryRateLimiter.Init(common.RateLimitKeyExpirationDuration)
|
||||
return func(c *gin.Context) {
|
||||
memoryRateLimiter(c, maxRequestNum, duration, mark)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,11 +95,3 @@ func GlobalAPIRateLimit() func(c *gin.Context) {
|
||||
func CriticalRateLimit() func(c *gin.Context) {
|
||||
return rateLimitFactory(common.CriticalRateLimitNum, common.CriticalRateLimitDuration, "CT")
|
||||
}
|
||||
|
||||
func DownloadRateLimit() func(c *gin.Context) {
|
||||
return rateLimitFactory(common.DownloadRateLimitNum, common.DownloadRateLimitDuration, "DW")
|
||||
}
|
||||
|
||||
func UploadRateLimit() func(c *gin.Context) {
|
||||
return rateLimitFactory(common.UploadRateLimitNum, common.UploadRateLimitDuration, "UP")
|
||||
}
|
||||
|
||||
@@ -50,12 +50,6 @@ func CountApplyLogs(nodeID string) (total int64, err error) {
|
||||
return total, err
|
||||
}
|
||||
|
||||
func GetLatestApplyLog(nodeID string) (*ApplyLog, error) {
|
||||
log := &ApplyLog{}
|
||||
err := DB.Where("node_id = ?", nodeID).Order("id desc").First(log).Error
|
||||
return log, err
|
||||
}
|
||||
|
||||
func GetLatestApplyLogsByNodeIDs(nodeIDs []string) (map[string]*ApplyLog, error) {
|
||||
result := make(map[string]*ApplyLog)
|
||||
if len(nodeIDs) == 0 {
|
||||
|
||||
@@ -19,7 +19,6 @@ export interface PublicStatus {
|
||||
wechat_qrcode: string;
|
||||
wechat_login: boolean;
|
||||
server_address: string;
|
||||
register_enabled: boolean;
|
||||
password_register_enabled: boolean;
|
||||
auth_sources: PublicAuthSource[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user