Skip to content
Closed
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
82ca930
feat: Create a user API to synchronously return the user ID and simul…
bddiudiu Nov 20, 2025
47020e4
feat: Add group parameters when creating a user
bddiudiu Nov 21, 2025
542447a
chore(deps): bump golang.org/x/crypto from 0.42.0 to 0.45.0
dependabot[bot] Nov 20, 2025
f95cf0c
fix: claude cache price render
seefs001 Nov 19, 2025
ba1a158
feat: Fill thoughtSignature only for Gemini/Vertex channels using the…
seefs001 Nov 20, 2025
7cb6fc7
fix: When retrieving the model list with multiple keys, select the fi…
seefs001 Nov 20, 2025
f88e14b
feat: Add ContextKeyLocalCountTokens and update ResponseText2Usage to…
Calcium-Ion Nov 21, 2025
c1b8983
fix: 错误解析responses api中的input字段
jarvis-u Nov 14, 2025
2799c94
add Vietnamese language support
chokiproai Nov 21, 2025
2e42b73
fix: Update GET_MEDIA_TOKEN_NOT_STREAM default value to false
Calcium-Ion Nov 22, 2025
63c1af6
feat: Add CountToken configuration and update token counting logic
Calcium-Ion Nov 22, 2025
92c5b44
feat: 关联 discord 账号
StageDog Nov 22, 2025
305e069
feat: 针对 discord 登录配置使用新版设置方案
StageDog Nov 22, 2025
50ca4e3
fix: IsDiscordIdAlreadyTaken 应该检查软删除记录
StageDog Nov 22, 2025
817082d
refactor: Deprecate HARM_CATEGORY_CIVIC_INTEGRITY in safety settings
Calcium-Ion Nov 23, 2025
83c4924
feat: Set ContextKeyLocalCountTokens in NativeGeminiEmbeddingHandler …
Calcium-Ion Nov 23, 2025
ee96ca6
feat: gemini thinking_level && snake params
seefs001 Nov 22, 2025
4f94c3b
feat: embedding param override && internal params
seefs001 Nov 22, 2025
75902d2
feat: 二次确认添加重定向前模型
seefs001 Nov 22, 2025
e84a873
feat: 重定向后的模型视为已有的模型,附带特殊提示
seefs001 Nov 22, 2025
8837132
fix: release workflow show version
seefs001 Nov 22, 2025
d5259cf
Revert "fix: release workflow show version"
bddiudiu Nov 24, 2025
5864959
Revert "feat: 重定向后的模型视为已有的模型,附带特殊提示"
bddiudiu Nov 24, 2025
3bc3fe5
Revert "feat: 二次确认添加重定向前模型"
bddiudiu Nov 24, 2025
80a0f52
Revert "feat: embedding param override && internal params"
bddiudiu Nov 24, 2025
6bf3feb
Revert "feat: gemini thinking_level && snake params"
bddiudiu Nov 24, 2025
4e72998
Revert "feat: Set ContextKeyLocalCountTokens in NativeGeminiEmbedding…
bddiudiu Nov 24, 2025
a857f95
Revert "refactor: Deprecate HARM_CATEGORY_CIVIC_INTEGRITY in safety s…
bddiudiu Nov 24, 2025
35936e1
Revert "fix: IsDiscordIdAlreadyTaken 应该检查软删除记录"
bddiudiu Nov 24, 2025
1ae0070
Revert "feat: 针对 discord 登录配置使用新版设置方案"
bddiudiu Nov 24, 2025
38483b6
Revert "feat: 关联 discord 账号"
bddiudiu Nov 24, 2025
f501b90
Revert "feat: Add CountToken configuration and update token counting …
bddiudiu Nov 24, 2025
0f52a1a
Revert "fix: Update GET_MEDIA_TOKEN_NOT_STREAM default value to false"
bddiudiu Nov 24, 2025
15c9af6
Revert "add Vietnamese language support"
bddiudiu Nov 24, 2025
3e1f4ef
Revert "fix: 错误解析responses api中的input字段"
bddiudiu Nov 24, 2025
34d68c8
Revert "feat: Add ContextKeyLocalCountTokens and update ResponseText2…
bddiudiu Nov 24, 2025
5e7e68e
Revert "fix: When retrieving the model list with multiple keys, selec…
bddiudiu Nov 24, 2025
5e786f2
Revert "feat: Fill thoughtSignature only for Gemini/Vertex channels u…
bddiudiu Nov 24, 2025
cbe5463
Revert "fix: claude cache price render"
bddiudiu Nov 24, 2025
f8e4278
Revert "chore(deps): bump golang.org/x/crypto from 0.42.0 to 0.45.0"
bddiudiu Nov 24, 2025
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
37 changes: 37 additions & 0 deletions controller/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,16 +861,53 @@ func CreateUser(c *gin.Context) {
Username: user.Username,
Password: user.Password,
DisplayName: user.DisplayName,
Group: user.Group,
Role: user.Role, // 保持管理员设置的角色
}
if err := cleanUser.Insert(0); err != nil {
common.ApiError(c, err)
return
}

// 生成默认令牌
if constant.GenerateDefaultToken {
key, err := common.GenerateKey()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "生成默认令牌失败",
})
common.SysLog("failed to generate token key: " + err.Error())
return
}
// 生成默认令牌
token := model.Token{
UserId: cleanUser.Id, // 使用插入后的用户ID
Name: cleanUser.Username + "的初始令牌",
Key: key,
CreatedTime: common.GetTimestamp(),
AccessedTime: common.GetTimestamp(),
ExpiredTime: -1, // 永不过期
RemainQuota: 500000, // 示例额度
UnlimitedQuota: true,
ModelLimitsEnabled: false,
}
if setting.DefaultUseAutoGroup {
token.Group = "auto"
}
if err := token.Insert(); err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "创建默认令牌失败",
})
return
}
}
Comment on lines +872 to +905

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical inconsistency and multiple concerns with token generation logic.

Several issues identified:

  1. Inconsistency in ID retrieval: This code uses cleanUser.Id directly after Insert() (line 884), but the Register function (lines 226-233) queries the database to retrieve the inserted user's ID. This inconsistency suggests uncertainty about whether GORM populates the ID field after insertion.

  2. Contradictory quota settings: Setting both RemainQuota: 500000 and UnlimitedQuota: true is contradictory. If the quota is unlimited, why set a remain quota?

  3. Hard-coded values: The quota value (500000) and Chinese text ("的初始令牌") are hard-coded, reducing configurability and creating i18n issues.

  4. Code duplication: This token generation logic is nearly identical to lines 235-267 in the Register function, violating DRY principles.

  5. Partial failure without rollback: If token creation fails after user creation, the user exists without a token. Without a transaction wrapping both operations, this creates an inconsistent state.

Recommended actions:

  1. Verify whether cleanUser.Id is populated after Insert(). If not, fetch it from the database as done in Register.
  2. Remove the contradictory RemainQuota setting when UnlimitedQuota is true, or make quota configuration explicit.
  3. Extract token generation into a shared helper function to eliminate duplication.
  4. Use a database transaction to ensure atomicity of user+token creation.
  5. Make the token name configurable or at least support i18n.
// Example: Extract to helper function
func createDefaultToken(userId int, username string) error {
    if !constant.GenerateDefaultToken {
        return nil
    }
    
    key, err := common.GenerateKey()
    if err != nil {
        return fmt.Errorf("failed to generate token key: %w", err)
    }
    
    token := model.Token{
        UserId:             userId,
        Name:               fmt.Sprintf("%s - Initial Token", username), // or use i18n
        Key:                key,
        CreatedTime:        common.GetTimestamp(),
        AccessedTime:       common.GetTimestamp(),
        ExpiredTime:        -1,
        UnlimitedQuota:     true,
        ModelLimitsEnabled: false,
    }
    
    if setting.DefaultUseAutoGroup {
        token.Group = "auto"
    }
    
    return token.Insert()
}

Then wrap both operations in a transaction:

err := model.DB.Transaction(func(tx *gorm.DB) error {
    if err := cleanUser.Insert(0); err != nil {
        return err
    }
    return createDefaultToken(cleanUser.Id, cleanUser.Username)
})
if err != nil {
    common.ApiError(c, err)
    return
}


c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"userId": cleanUser.Id,
})
return
}
Expand Down