mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
[management] Refactor users to use store methods (#2917)
* Refactor setup key handling to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add lock to get account groups Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add check for regular user Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * get only required groups for auto-group validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add account lock and return auto groups map on validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * refactor account peers update Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor groups to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * refactor GetGroupByID and add NewGroupNotFoundError Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add AddPeer and RemovePeer methods to Group struct Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Preserve store engine in SqlStore transactions Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Run groups ops in transaction Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix missing group removed from setup key activity Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor posture checks to remove get and save account Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix refactor Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix sonar Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Change setup key log level to debug for missing group Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Retrieve modified peers once for group events Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor policy get and save account to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Retrieve policy groups and posture checks once for validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix typo Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add policy tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor anyGroupHasPeers to retrieve all groups once Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor dns settings to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add account locking and merge group deletion methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor name server groups to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add peer store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor ephemeral peers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add lock for peer store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor peer handlers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor peer to use store methods Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix typo Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add locks and remove log Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * run peer ops in transaction Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * remove duplicate store method Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix peer fields updated after save Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use update strength and simplify check Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * prevent changing ruleID when not empty Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * prevent duplicate rules during updates Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix lint Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor auth middleware Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor account methods and mock Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor user and PAT handling Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Remove db query context and fix get user by id Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix database transaction locking issue Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use UTC time in test Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add account locks Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix prevent users from creating PATs for other users Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add store locks and prevent fetching setup keys peers when retrieving user peers with empty userID Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add missing tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor test names and remove duplicate TestPostgresql_SavePeerStatus Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add account locks and remove redundant ephemeral check Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Retrieve all groups for peers and restrict groups for regular users Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix store tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * use account object to get validated peers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Improve peer performance Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Get account direct from store without buffer Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Add get peer groups tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Adjust benchmarks Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Adjust benchmarks Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * [management] Update benchmark workflow (#3181) * update local benchmark expectations * update cloud expectations * Add status error for generic result error Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use integrated validator direct Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations * update expectations * update expectations * Refactor peer scheduler to retry every 3 seconds on errors Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations * fix validator * fix validator * fix validator * update timeouts * Refactor ToGroupsInfo to process slices of groups Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations * update expectations * update expectations * Bump integrations version Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor GetValidatedPeers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * go mod tidy Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Use peers and groups map for peers validation Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * remove mysql from api benchmark tests * Fix merge Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix blocked db calls on user auto groups update Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Skip user check for system initiated peer deletion Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Remove context in db calls Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * update expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * [management] Improve group peer/resource counting (#3192) * Fix sonar Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Adjust bench expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Rename GetAccountInfoFromPAT to GetTokenInfo Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Remove global account lock for ListUsers Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * build userinfo after updating users in db Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * [management] Optimize user bulk deletion (#3315) * refactor building user infos Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * fix tests Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * remove unused code Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Refactor GetUsersFromAccount to return a map of UserInfo instead of a slice Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Export BuildUserInfosForAccount to account manager Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Fetch account user info once for bulk users save Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Update user deletion expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Set max open conns for activity store Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> * Update bench expectations Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> --------- Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> --------- Signed-off-by: bcmmbaga <bethuelmbaga12@gmail.com> Co-authored-by: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Co-authored-by: Pascal Fischer <pascal@netbird.io> Co-authored-by: Pedro Costa <550684+pnmcosta@users.noreply.github.com>
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/netbirdio/netbird/management/server/util"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/driver/postgres"
|
||||
@@ -414,24 +415,16 @@ func (s *SqlStore) SavePeerLocation(ctx context.Context, lockStrength LockingStr
|
||||
}
|
||||
|
||||
// SaveUsers saves the given list of users to the database.
|
||||
// It updates existing users if a conflict occurs.
|
||||
func (s *SqlStore) SaveUsers(accountID string, users map[string]*types.User) error {
|
||||
usersToSave := make([]types.User, 0, len(users))
|
||||
for _, user := range users {
|
||||
user.AccountID = accountID
|
||||
for id, pat := range user.PATs {
|
||||
pat.ID = id
|
||||
user.PATsG = append(user.PATsG, *pat)
|
||||
}
|
||||
usersToSave = append(usersToSave, *user)
|
||||
}
|
||||
err := s.db.Session(&gorm.Session{FullSaveAssociations: true}).
|
||||
Clauses(clause.OnConflict{UpdateAll: true}).
|
||||
Create(&usersToSave).Error
|
||||
if err != nil {
|
||||
return status.Errorf(status.Internal, "failed to save users to store: %v", err)
|
||||
func (s *SqlStore) SaveUsers(ctx context.Context, lockStrength LockingStrength, users []*types.User) error {
|
||||
if len(users) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Save(&users)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to save users to store: %s", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to save users to store")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -439,7 +432,8 @@ func (s *SqlStore) SaveUsers(accountID string, users map[string]*types.User) err
|
||||
func (s *SqlStore) SaveUser(ctx context.Context, lockStrength LockingStrength, user *types.User) error {
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Save(user)
|
||||
if result.Error != nil {
|
||||
return status.Errorf(status.Internal, "failed to save user to store: %v", result.Error)
|
||||
log.WithContext(ctx).Errorf("failed to save user to store: %s", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to save user to store")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -526,30 +520,17 @@ func (s *SqlStore) GetTokenIDByHashedToken(ctx context.Context, hashedToken stri
|
||||
return token.ID, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetUserByTokenID(ctx context.Context, tokenID string) (*types.User, error) {
|
||||
var token types.PersonalAccessToken
|
||||
result := s.db.First(&token, idQueryCondition, tokenID)
|
||||
func (s *SqlStore) GetUserByPATID(ctx context.Context, lockStrength LockingStrength, patID string) (*types.User, error) {
|
||||
var user types.User
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Joins("JOIN personal_access_tokens ON personal_access_tokens.user_id = users.id").
|
||||
Where("personal_access_tokens.id = ?", patID).First(&user)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.Errorf(status.NotFound, "account not found: index lookup failed")
|
||||
return nil, status.NewPATNotFoundError(patID)
|
||||
}
|
||||
log.WithContext(ctx).Errorf("error when getting token from the store: %s", result.Error)
|
||||
return nil, status.NewGetAccountFromStoreError(result.Error)
|
||||
}
|
||||
|
||||
if token.UserID == "" {
|
||||
return nil, status.Errorf(status.NotFound, "account not found: index lookup failed")
|
||||
}
|
||||
|
||||
var user types.User
|
||||
result = s.db.Preload("PATsG").First(&user, idQueryCondition, token.UserID)
|
||||
if result.Error != nil {
|
||||
return nil, status.Errorf(status.NotFound, "account not found: index lookup failed")
|
||||
}
|
||||
|
||||
user.PATs = make(map[string]*types.PersonalAccessToken, len(user.PATsG))
|
||||
for _, pat := range user.PATsG {
|
||||
user.PATs[pat.ID] = pat.Copy()
|
||||
log.WithContext(ctx).Errorf("failed to get token user from the store: %s", result.Error)
|
||||
return nil, status.NewGetUserFromStoreError()
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
@@ -557,8 +538,7 @@ func (s *SqlStore) GetUserByTokenID(ctx context.Context, tokenID string) (*types
|
||||
|
||||
func (s *SqlStore) GetUserByUserID(ctx context.Context, lockStrength LockingStrength, userID string) (*types.User, error) {
|
||||
var user types.User
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Preload(clause.Associations).First(&user, idQueryCondition, userID)
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).First(&user, idQueryCondition, userID)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.NewUserNotFoundError(userID)
|
||||
@@ -569,6 +549,25 @@ func (s *SqlStore) GetUserByUserID(ctx context.Context, lockStrength LockingStre
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) DeleteUser(ctx context.Context, lockStrength LockingStrength, accountID, userID string) error {
|
||||
err := s.db.Transaction(func(tx *gorm.DB) error {
|
||||
result := tx.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Delete(&types.PersonalAccessToken{}, "user_id = ?", userID)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
|
||||
return tx.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Delete(&types.User{}, accountAndIDQueryCondition, accountID, userID).Error
|
||||
})
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Errorf("failed to delete user from the store: %s", err)
|
||||
return status.Errorf(status.Internal, "failed to delete user from store")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetAccountUsers(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*types.User, error) {
|
||||
var users []*types.User
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Find(&users, accountIDCondition, accountID)
|
||||
@@ -899,6 +898,20 @@ func (s *SqlStore) GetAccountSettings(ctx context.Context, lockStrength LockingS
|
||||
return accountSettings.Settings, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) GetAccountCreatedBy(ctx context.Context, lockStrength LockingStrength, accountID string) (string, error) {
|
||||
var createdBy string
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Model(&types.Account{}).
|
||||
Select("created_by").First(&createdBy, idQueryCondition, accountID)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return "", status.NewAccountNotFoundError(accountID)
|
||||
}
|
||||
return "", status.NewGetAccountFromStoreError(result.Error)
|
||||
}
|
||||
|
||||
return createdBy, nil
|
||||
}
|
||||
|
||||
// SaveUserLastLogin stores the last login time for a user in DB.
|
||||
func (s *SqlStore) SaveUserLastLogin(ctx context.Context, accountID, userID string, lastLogin time.Time) error {
|
||||
var user types.User
|
||||
@@ -2053,3 +2066,94 @@ func (s *SqlStore) DeleteNetworkResource(ctx context.Context, lockStrength Locki
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPATByHashedToken returns a PersonalAccessToken by its hashed token.
|
||||
func (s *SqlStore) GetPATByHashedToken(ctx context.Context, lockStrength LockingStrength, hashedToken string) (*types.PersonalAccessToken, error) {
|
||||
var pat types.PersonalAccessToken
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).First(&pat, "hashed_token = ?", hashedToken)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.NewPATNotFoundError(hashedToken)
|
||||
}
|
||||
log.WithContext(ctx).Errorf("failed to get pat by hash from the store: %s", result.Error)
|
||||
return nil, status.Errorf(status.Internal, "failed to get pat by hash from store")
|
||||
}
|
||||
|
||||
return &pat, nil
|
||||
}
|
||||
|
||||
// GetPATByID retrieves a personal access token by its ID and user ID.
|
||||
func (s *SqlStore) GetPATByID(ctx context.Context, lockStrength LockingStrength, userID string, patID string) (*types.PersonalAccessToken, error) {
|
||||
var pat types.PersonalAccessToken
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
First(&pat, "id = ? AND user_id = ?", patID, userID)
|
||||
if err := result.Error; err != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return nil, status.NewPATNotFoundError(patID)
|
||||
}
|
||||
log.WithContext(ctx).Errorf("failed to get pat from the store: %s", err)
|
||||
return nil, status.Errorf(status.Internal, "failed to get pat from store")
|
||||
}
|
||||
|
||||
return &pat, nil
|
||||
}
|
||||
|
||||
// GetUserPATs retrieves personal access tokens for a user.
|
||||
func (s *SqlStore) GetUserPATs(ctx context.Context, lockStrength LockingStrength, userID string) ([]*types.PersonalAccessToken, error) {
|
||||
var pats []*types.PersonalAccessToken
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Find(&pats, "user_id = ?", userID)
|
||||
if err := result.Error; err != nil {
|
||||
log.WithContext(ctx).Errorf("failed to get user pat's from the store: %s", err)
|
||||
return nil, status.Errorf(status.Internal, "failed to get user pat's from store")
|
||||
}
|
||||
|
||||
return pats, nil
|
||||
}
|
||||
|
||||
// MarkPATUsed marks a personal access token as used.
|
||||
func (s *SqlStore) MarkPATUsed(ctx context.Context, lockStrength LockingStrength, patID string) error {
|
||||
patCopy := types.PersonalAccessToken{
|
||||
LastUsed: util.ToPtr(time.Now().UTC()),
|
||||
}
|
||||
|
||||
fieldsToUpdate := []string{"last_used"}
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Select(fieldsToUpdate).
|
||||
Where(idQueryCondition, patID).Updates(&patCopy)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to mark pat as used: %s", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to mark pat as used")
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return status.NewPATNotFoundError(patID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SavePAT saves a personal access token to the database.
|
||||
func (s *SqlStore) SavePAT(ctx context.Context, lockStrength LockingStrength, pat *types.PersonalAccessToken) error {
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).Save(pat)
|
||||
if err := result.Error; err != nil {
|
||||
log.WithContext(ctx).Errorf("failed to save pat to the store: %s", err)
|
||||
return status.Errorf(status.Internal, "failed to save pat to store")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeletePAT deletes a personal access token from the database.
|
||||
func (s *SqlStore) DeletePAT(ctx context.Context, lockStrength LockingStrength, userID, patID string) error {
|
||||
result := s.db.Clauses(clause.Locking{Strength: string(lockStrength)}).
|
||||
Delete(&types.PersonalAccessToken{}, "user_id = ? AND id = ?", userID, patID)
|
||||
if err := result.Error; err != nil {
|
||||
log.WithContext(ctx).Errorf("failed to delete pat from the store: %s", err)
|
||||
return status.Errorf(status.Internal, "failed to delete pat from store")
|
||||
}
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return status.NewPATNotFoundError(patID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user