mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-04 09:27:15 +00:00
fix(cli): stop -getApiToken accumulating admin tokens (#6175)
* fix(cli): stop -getApiToken accumulating admin tokens `x-ui setting -getApiToken` reads like a getter, but when tokens already exist it minted a brand-new one named `cli-fallback-<unix>` on every invocation. The plaintext is printed once and the row stays enabled forever, so an operator who runs the command a few times while debugging silently leaves several admin-equivalent credentials behind that nobody can tell apart or revoke knowingly. Keep the convenience the fallback was added for, but rotate a single `cli-fallback` token instead: RecreateByName drops any existing row with that name before issuing a new one, so at most one CLI-issued token exists at a time and the previous plaintext stops working. * fix(api-token): preserve token on failed replacement --------- Co-authored-by: n0ctal <293235942+n0ctal@users.noreply.github.com>
This commit is contained in:
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/database"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/database/model"
|
||||
"github.com/mhsanaei/3x-ui/v3/internal/util/common"
|
||||
@@ -86,6 +88,28 @@ func (s *ApiTokenService) Create(name string) (*ApiTokenView, error) {
|
||||
return view, nil
|
||||
}
|
||||
|
||||
// RecreateByName replaces any token with this name, keeping exactly one so a
|
||||
// repeatedly-run caller cannot accumulate credentials it can never revoke.
|
||||
func (s *ApiTokenService) RecreateByName(name string) (*ApiTokenView, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, common.NewError("token name is required")
|
||||
}
|
||||
plaintext := random.Seq(apiTokenLength)
|
||||
row := &model.ApiToken{Name: name, Token: crypto.HashTokenSHA256(plaintext), Enabled: true}
|
||||
if err := database.GetDB().Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("name = ?", name).Delete(model.ApiToken{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Create(row).Error
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
view := toView(row)
|
||||
view.Token = plaintext
|
||||
return view, nil
|
||||
}
|
||||
|
||||
func (s *ApiTokenService) Delete(id int) error {
|
||||
if id <= 0 {
|
||||
return common.NewError("invalid token id")
|
||||
|
||||
Reference in New Issue
Block a user