mirror of https://github.com/Xhofe/alist
refactor(convert_role): Improve role conversion logic for legacy formats (#9219)
- Add new imports: `database/sql`, `encoding/json`, and `conf` package in `convert_role.go`. - Simplify permission entry initialization by removing redundant struct formatting. - Update error logging messages for better clarity. - Replace `op.GetUsers` with direct database access for fetching user roles. - Implement role update logic using `rawDb` and handle legacy int role conversion. - Count the number of users whose roles are updated and log completion. - Introduce `IsLegacyRoleDetected` function to check for legacy role formats. - Modify `cmd/common.go` to invoke role conversion if legacy format is detected.pull/9228/head v3.46.1
parent
00120cba27
commit
f61d13d433
|
@ -1,6 +1,7 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/alist-org/alist/v3/internal/bootstrap/patch/v3_46_0"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -16,6 +17,12 @@ func Init() {
|
|||
bootstrap.InitConfig()
|
||||
bootstrap.Log()
|
||||
bootstrap.InitDB()
|
||||
|
||||
if v3_46_0.IsLegacyRoleDetected() {
|
||||
utils.Log.Warnf("Detected legacy role format, executing ConvertLegacyRoles patch early...")
|
||||
v3_46_0.ConvertLegacyRoles()
|
||||
}
|
||||
|
||||
data.InitData()
|
||||
bootstrap.InitStreamLimit()
|
||||
bootstrap.InitIndex()
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package v3_46_0
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/alist-org/alist/v3/internal/conf"
|
||||
"github.com/alist-org/alist/v3/internal/db"
|
||||
"github.com/alist-org/alist/v3/internal/model"
|
||||
"github.com/alist-org/alist/v3/internal/op"
|
||||
|
@ -83,47 +86,101 @@ func ConvertLegacyRoles() {
|
|||
}
|
||||
}
|
||||
|
||||
users, _, err := op.GetUsers(1, -1)
|
||||
rawDb := db.GetDb()
|
||||
table := conf.Conf.Database.TablePrefix + "users"
|
||||
rows, err := rawDb.Table(table).Select("id, username, role").Rows()
|
||||
if err != nil {
|
||||
utils.Log.Errorf("[convert roles] failed to get users: %v", err)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for i := range users {
|
||||
user := users[i]
|
||||
if user.Role == nil {
|
||||
var updatedCount int
|
||||
for rows.Next() {
|
||||
var id uint
|
||||
var username string
|
||||
var rawRole []byte
|
||||
|
||||
if err := rows.Scan(&id, &username, &rawRole); err != nil {
|
||||
utils.Log.Warnf("[convert roles] skip user scan err: %v", err)
|
||||
continue
|
||||
}
|
||||
changed := false
|
||||
var roles model.Roles
|
||||
for _, r := range user.Role {
|
||||
|
||||
utils.Log.Debugf("[convert roles] user: %s raw role: %s", username, string(rawRole))
|
||||
|
||||
if len(rawRole) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var oldRoles []int
|
||||
wasSingleInt := false
|
||||
if err := json.Unmarshal(rawRole, &oldRoles); err != nil {
|
||||
var single int
|
||||
if err := json.Unmarshal(rawRole, &single); err != nil {
|
||||
utils.Log.Warnf("[convert roles] user %s has invalid role: %s", username, string(rawRole))
|
||||
continue
|
||||
}
|
||||
oldRoles = []int{single}
|
||||
wasSingleInt = true
|
||||
}
|
||||
|
||||
var newRoles model.Roles
|
||||
for _, r := range oldRoles {
|
||||
switch r {
|
||||
case model.ADMIN:
|
||||
roles = append(roles, int(adminRole.ID))
|
||||
if int(adminRole.ID) != r {
|
||||
changed = true
|
||||
}
|
||||
newRoles = append(newRoles, int(adminRole.ID))
|
||||
case model.GUEST:
|
||||
roles = append(roles, int(guestRole.ID))
|
||||
if int(guestRole.ID) != r {
|
||||
changed = true
|
||||
}
|
||||
newRoles = append(newRoles, int(guestRole.ID))
|
||||
case model.GENERAL:
|
||||
roles = append(roles, int(generalRole.ID))
|
||||
if int(generalRole.ID) != r {
|
||||
changed = true
|
||||
}
|
||||
newRoles = append(newRoles, int(generalRole.ID))
|
||||
default:
|
||||
roles = append(roles, r)
|
||||
newRoles = append(newRoles, r)
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
user.Role = roles
|
||||
if err := db.UpdateUser(&user); err != nil {
|
||||
utils.Log.Errorf("[convert roles] failed to update user %s: %v", user.Username, err)
|
||||
|
||||
if wasSingleInt {
|
||||
err := rawDb.Table(table).Where("id = ?", id).Update("role", newRoles).Error
|
||||
if err != nil {
|
||||
utils.Log.Errorf("[convert roles] failed to update user %s: %v", username, err)
|
||||
} else {
|
||||
updatedCount++
|
||||
utils.Log.Infof("[convert roles] updated user %s: %v → %v", username, oldRoles, newRoles)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.Log.Infof("[convert roles] completed role conversion for %d users", len(users))
|
||||
utils.Log.Infof("[convert roles] completed role conversion for %d users", updatedCount)
|
||||
}
|
||||
|
||||
func IsLegacyRoleDetected() bool {
|
||||
rawDb := db.GetDb()
|
||||
table := conf.Conf.Database.TablePrefix + "users"
|
||||
rows, err := rawDb.Table(table).Select("role").Rows()
|
||||
if err != nil {
|
||||
utils.Log.Errorf("[role check] failed to scan user roles: %v", err)
|
||||
return false
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var raw sql.RawBytes
|
||||
if err := rows.Scan(&raw); err != nil {
|
||||
continue
|
||||
}
|
||||
if len(raw) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var roles []int
|
||||
if err := json.Unmarshal(raw, &roles); err == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var single int
|
||||
if err := json.Unmarshal(raw, &single); err == nil {
|
||||
utils.Log.Infof("[role check] detected legacy int role: %d", single)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue