优化
This commit is contained in:
+25
-27
@@ -42,10 +42,16 @@ func (jwtBlacklistPO) TableName() string { return "jwt_blacklists" }
|
||||
func (r *apiTokenRepo) UserHasAuthority(ctx context.Context, userID, authorityID uint) (*biz.User, bool, error) {
|
||||
var po userPO
|
||||
if err := r.data.gormDB.WithContext(ctx).First(&po, userID).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, false, errors.New("用户不存在")
|
||||
}
|
||||
return nil, false, err
|
||||
}
|
||||
var count int64
|
||||
err := r.data.gormDB.WithContext(ctx).Model(&userAuthorityPO{}).Where("sys_user_id = ? AND sys_authority_authority_id = ?", userID, authorityID).Count(&count).Error
|
||||
err := r.data.gormDB.WithContext(ctx).Model(&userAuthorityPO{}).
|
||||
Joins("JOIN sys_authorities ON sys_authorities.authority_id = sys_user_authority.sys_authority_authority_id").
|
||||
Where("sys_user_authority.sys_user_id = ? AND sys_user_authority.sys_authority_authority_id = ? AND sys_authorities.deleted_at IS NULL", userID, authorityID).
|
||||
Count(&count).Error
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@@ -106,22 +112,20 @@ func (r *apiTokenRepo) DisableAPIToken(ctx context.Context, id uint) (string, er
|
||||
return po.Token, r.data.gormDB.WithContext(ctx).Model(&po).Update("status", false).Error
|
||||
}
|
||||
func (r *apiTokenRepo) DisableAndBlacklistAPIToken(ctx context.Context, id uint) error {
|
||||
return r.data.gormDB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var po apiTokenPO
|
||||
if err := tx.First(&po, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// Blacklist the token before disabling it while making both writes atomic.
|
||||
if err := tx.Create(&jwtBlacklistPO{JWT: po.Token}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Model(&po).Update("status", false).Error
|
||||
})
|
||||
// Persist the blacklist row first, then mark the
|
||||
// API-token record disabled. The two writes are intentionally separate in
|
||||
// the reference implementation, so a storage error has the same observable
|
||||
// result here.
|
||||
var po apiTokenPO
|
||||
if err := r.data.gormDB.WithContext(ctx).First(&po, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := r.BlacklistToken(ctx, po.Token); err != nil {
|
||||
return err
|
||||
}
|
||||
return r.data.gormDB.WithContext(ctx).Model(&po).Update("status", false).Error
|
||||
}
|
||||
func (r *apiTokenRepo) BlacklistToken(ctx context.Context, token string) error {
|
||||
if token == "" {
|
||||
return errors.New("token is empty")
|
||||
}
|
||||
return r.data.gormDB.WithContext(ctx).Create(&jwtBlacklistPO{JWT: token}).Error
|
||||
}
|
||||
func (r *apiTokenRepo) IsTokenDisabled(ctx context.Context, token string) (bool, error) {
|
||||
@@ -129,16 +133,10 @@ func (r *apiTokenRepo) IsTokenDisabled(ctx context.Context, token string) (bool,
|
||||
if err := r.data.gormDB.WithContext(ctx).Model(&jwtBlacklistPO{}).Where("jwt = ?", token).Count(&blacklistCount).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
if blacklistCount > 0 {
|
||||
return true, nil
|
||||
}
|
||||
var po apiTokenPO
|
||||
result := r.data.gormDB.WithContext(ctx).Where("token = ?", token).Limit(1).Find(&po)
|
||||
if result.Error != nil {
|
||||
return false, result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return false, nil
|
||||
}
|
||||
return !po.Status || time.Now().After(po.ExpiresAt), nil
|
||||
// The JWT middleware consults only jwt_blacklists and lets JWT parsing
|
||||
// report expiry. API-token deletion writes this row before changing the
|
||||
// token status, so consulting status/ExpiresAt here would produce a
|
||||
// different error message and would make manually-disabled tokens behave
|
||||
// unlike tokens issued through the regular login flow.
|
||||
return blacklistCount > 0, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user