Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions controller/custom_oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/i18n"
"github.com/QuantumNous/new-api/model"
"github.com/QuantumNous/new-api/oauth"
"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -469,7 +470,7 @@ func buildUserOAuthBindingsResponse(userId int) ([]UserOAuthBindingResponse, err
func GetUserOAuthBindings(c *gin.Context) {
userId := c.GetInt("id")
if userId == 0 {
common.ApiErrorMsg(c, "未登录")
common.ApiErrorI18n(c, i18n.MsgUnauthorized)
return
}

Expand Down Expand Up @@ -523,14 +524,14 @@ func GetUserOAuthBindingsByAdmin(c *gin.Context) {
func UnbindCustomOAuth(c *gin.Context) {
userId := c.GetInt("id")
if userId == 0 {
common.ApiErrorMsg(c, "未登录")
common.ApiErrorI18n(c, i18n.MsgUnauthorized)
return
}

providerIdStr := c.Param("provider_id")
providerId, err := strconv.Atoi(providerIdStr)
if err != nil {
common.ApiErrorMsg(c, "无效的提供商 ID")
common.ApiErrorI18n(c, i18n.MsgInvalidId)
return
}

Expand All @@ -541,7 +542,7 @@ func UnbindCustomOAuth(c *gin.Context) {

c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "解绑成功",
"message": i18n.T(c, i18n.MsgCustomOAuthUnbindSuccess),
})
}

Expand Down
82 changes: 33 additions & 49 deletions controller/wechat.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package controller

import (
"encoding/json"
"errors"
"fmt"
"net/http"
Expand All @@ -10,12 +9,18 @@ import (
"time"

"github.com/QuantumNous/new-api/common"
"github.com/QuantumNous/new-api/i18n"
"github.com/QuantumNous/new-api/model"

"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
)

var (
errWeChatInvalidCode = errors.New("wechat code is empty")
errWeChatVerificationFailed = errors.New("wechat verification failed")
)

type wechatLoginResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Expand All @@ -24,7 +29,7 @@ type wechatLoginResponse struct {

func getWeChatIdByCode(code string) (string, error) {
if code == "" {
return "", errors.New("无效的参数")
return "", errWeChatInvalidCode
}
req, err := http.NewRequest("GET", fmt.Sprintf("%s/api/wechat/user?code=%s", common.WeChatServerAddress, url.QueryEscape(code)), nil)
if err != nil {
Expand All @@ -40,34 +45,40 @@ func getWeChatIdByCode(code string) (string, error) {
}
defer httpResponse.Body.Close()
var res wechatLoginResponse
err = json.NewDecoder(httpResponse.Body).Decode(&res)
err = common.DecodeJson(httpResponse.Body, &res)
if err != nil {
return "", err
}
if !res.Success {
return "", errors.New(res.Message)
return "", errWeChatVerificationFailed
}
if res.Data == "" {
return "", errors.New("验证码错误或已过期")
return "", errWeChatVerificationFailed
}
return res.Data, nil
}

func apiWeChatError(c *gin.Context, err error) {
switch {
case errors.Is(err, errWeChatInvalidCode):
common.ApiErrorI18n(c, i18n.MsgInvalidParams)
case errors.Is(err, errWeChatVerificationFailed):
common.ApiErrorI18n(c, i18n.MsgUserVerificationCodeError)
default:
common.SysError("wechat auth failed: " + err.Error())
common.ApiErrorI18n(c, i18n.MsgOAuthConnectFailed, map[string]any{"Provider": "WeChat"})
}
}

func WeChatAuth(c *gin.Context) {
if !common.WeChatAuthEnabled {
c.JSON(http.StatusOK, gin.H{
"message": "管理员未开启通过微信登录以及注册",
"success": false,
})
common.ApiErrorI18n(c, i18n.MsgWeChatNotEnabled)
return
}
code := c.Query("code")
wechatId, err := getWeChatIdByCode(code)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"message": err.Error(),
"success": false,
})
apiWeChatError(c, err)
return
}
user := model.User{
Expand All @@ -76,17 +87,11 @@ 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(),
})
common.ApiError(c, err)
return
}
if user.Id == 0 {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "用户已注销",
})
common.ApiErrorI18n(c, i18n.MsgOAuthUserDeleted)
return
}
} else {
Expand All @@ -97,26 +102,17 @@ func WeChatAuth(c *gin.Context) {
user.Status = common.UserStatusEnabled

if err := user.Insert(0); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
common.ApiError(c, err)
return
}
} else {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "管理员关闭了新用户注册",
})
common.ApiErrorI18n(c, i18n.MsgUserRegisterDisabled)
return
}
}

if user.Status != common.UserStatusEnabled {
c.JSON(http.StatusOK, gin.H{
"message": "用户已被封禁",
"success": false,
})
common.ApiErrorI18n(c, i18n.MsgUserDisabled)
return
}
setupLogin(&user, c)
Expand All @@ -128,34 +124,22 @@ type wechatBindRequest struct {

func WeChatBind(c *gin.Context) {
if !common.WeChatAuthEnabled {
c.JSON(http.StatusOK, gin.H{
"message": "管理员未开启通过微信登录以及注册",
"success": false,
})
common.ApiErrorI18n(c, i18n.MsgWeChatNotEnabled)
return
}
var req wechatBindRequest
if err := common.DecodeJson(c.Request.Body, &req); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "无效的请求",
})
common.ApiErrorI18n(c, i18n.MsgInvalidParams)
return
}
code := req.Code
wechatId, err := getWeChatIdByCode(code)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"message": err.Error(),
"success": false,
})
apiWeChatError(c, err)
return
}
if model.IsWeChatIdAlreadyTaken(wechatId) {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "该微信账号已被绑定",
})
common.ApiErrorI18n(c, i18n.MsgWeChatAccountUsed)
return
}
session := sessions.Default(c)
Expand Down
7 changes: 7 additions & 0 deletions i18n/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,4 +329,11 @@ const (
MsgCustomOAuthHasBindings = "custom_oauth.has_bindings"
MsgCustomOAuthBindingNotFound = "custom_oauth.binding_not_found"
MsgCustomOAuthProviderIdInvalid = "custom_oauth.provider_id_field_invalid"
MsgCustomOAuthUnbindSuccess = "custom_oauth.unbind_success"
)

// WeChat auth related messages
const (
MsgWeChatNotEnabled = "wechat.not_enabled"
MsgWeChatAccountUsed = "wechat.account_used"
)
5 changes: 5 additions & 0 deletions i18n/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,8 @@ custom_oauth.name_empty: "Provider name cannot be empty"
custom_oauth.has_bindings: "Cannot delete provider with existing user bindings"
custom_oauth.binding_not_found: "OAuth binding not found"
custom_oauth.provider_id_field_invalid: "Could not extract user ID from provider response"
custom_oauth.unbind_success: "OAuth account unbound successfully"

# WeChat auth messages
wechat.not_enabled: "WeChat login and registration are not enabled"
wechat.account_used: "This WeChat account has already been bound"
5 changes: 5 additions & 0 deletions i18n/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,8 @@ custom_oauth.name_empty: "提供商名称不能为空"
custom_oauth.has_bindings: "无法删除已有用户绑定的提供商"
custom_oauth.binding_not_found: "OAuth 绑定不存在"
custom_oauth.provider_id_field_invalid: "无法从提供商响应中提取用户 ID"
custom_oauth.unbind_success: "OAuth 账户解绑成功"

# WeChat auth messages
wechat.not_enabled: "管理员未开启通过微信登录以及注册"
wechat.account_used: "该微信账户已被绑定"
5 changes: 5 additions & 0 deletions i18n/locales/zh-TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,8 @@ custom_oauth.name_empty: "供應者名稱不能為空"
custom_oauth.has_bindings: "無法刪除已有使用者綁定的供應者"
custom_oauth.binding_not_found: "OAuth 綁定不存在"
custom_oauth.provider_id_field_invalid: "無法從供應者響應中提取使用者 ID"
custom_oauth.unbind_success: "OAuth 帳號解除綁定成功"

# WeChat auth messages
wechat.not_enabled: "管理員未開啟透過微信登入以及註冊"
wechat.account_used: "該微信帳號已被綁定"