mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-25 08:09:07 +02:00
140 lines
4.9 KiB
Go
140 lines
4.9 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
|
|
"github.com/netbirdio/netbird/management/server/types"
|
|
"github.com/netbirdio/netbird/shared/management/status"
|
|
)
|
|
|
|
// SaveUserInvite saves a user invite to the database
|
|
func (s *SqlStore) SaveUserInvite(ctx context.Context, invite *types.UserInviteRecord) error {
|
|
inviteCopy := invite.Copy()
|
|
if err := inviteCopy.EncryptSensitiveData(s.fieldEncrypt); err != nil {
|
|
return fmt.Errorf("encrypt invite: %w", err)
|
|
}
|
|
|
|
result := s.db.Save(inviteCopy)
|
|
if result.Error != nil {
|
|
log.WithContext(ctx).Errorf("failed to save user invite to store: %s", result.Error)
|
|
return status.Errorf(status.Internal, "failed to save user invite to store")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetUserInviteByID retrieves a user invite by its ID and account ID
|
|
func (s *SqlStore) GetUserInviteByID(ctx context.Context, lockStrength LockingStrength, accountID, inviteID string) (*types.UserInviteRecord, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var invite types.UserInviteRecord
|
|
result := tx.Where("account_id = ?", accountID).Take(&invite, idQueryCondition, inviteID)
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
return nil, status.Errorf(status.NotFound, "user invite not found")
|
|
}
|
|
log.WithContext(ctx).Errorf("failed to get user invite from store: %s", result.Error)
|
|
return nil, status.Errorf(status.Internal, "failed to get user invite from store")
|
|
}
|
|
|
|
if err := invite.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
|
return nil, fmt.Errorf("decrypt invite: %w", err)
|
|
}
|
|
|
|
return &invite, nil
|
|
}
|
|
|
|
// GetUserInviteByHashedToken retrieves a user invite by its hashed token
|
|
func (s *SqlStore) GetUserInviteByHashedToken(ctx context.Context, lockStrength LockingStrength, hashedToken string) (*types.UserInviteRecord, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var invite types.UserInviteRecord
|
|
result := tx.Take(&invite, "hashed_token = ?", hashedToken)
|
|
if result.Error != nil {
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
|
return nil, status.Errorf(status.NotFound, "user invite not found")
|
|
}
|
|
log.WithContext(ctx).Errorf("failed to get user invite from store: %s", result.Error)
|
|
return nil, status.Errorf(status.Internal, "failed to get user invite from store")
|
|
}
|
|
|
|
if err := invite.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
|
return nil, fmt.Errorf("decrypt invite: %w", err)
|
|
}
|
|
|
|
return &invite, nil
|
|
}
|
|
|
|
// GetUserInviteByEmail retrieves a user invite by account ID and email.
|
|
// Since email is encrypted with random IVs, we fetch all invites for the account
|
|
// and compare emails in memory after decryption.
|
|
func (s *SqlStore) GetUserInviteByEmail(ctx context.Context, lockStrength LockingStrength, accountID, email string) (*types.UserInviteRecord, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var invites []*types.UserInviteRecord
|
|
result := tx.Find(&invites, "account_id = ?", accountID)
|
|
if result.Error != nil {
|
|
log.WithContext(ctx).Errorf("failed to get user invites from store: %s", result.Error)
|
|
return nil, status.Errorf(status.Internal, "failed to get user invites from store")
|
|
}
|
|
|
|
for _, invite := range invites {
|
|
if err := invite.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
|
return nil, fmt.Errorf("decrypt invite: %w", err)
|
|
}
|
|
if strings.EqualFold(invite.Email, email) {
|
|
return invite, nil
|
|
}
|
|
}
|
|
|
|
return nil, status.Errorf(status.NotFound, "user invite not found for email")
|
|
}
|
|
|
|
// GetAccountUserInvites retrieves all user invites for an account
|
|
func (s *SqlStore) GetAccountUserInvites(ctx context.Context, lockStrength LockingStrength, accountID string) ([]*types.UserInviteRecord, error) {
|
|
tx := s.db
|
|
if lockStrength != LockingStrengthNone {
|
|
tx = tx.Clauses(clause.Locking{Strength: string(lockStrength)})
|
|
}
|
|
|
|
var invites []*types.UserInviteRecord
|
|
result := tx.Find(&invites, "account_id = ?", accountID)
|
|
if result.Error != nil {
|
|
log.WithContext(ctx).Errorf("failed to get user invites from store: %s", result.Error)
|
|
return nil, status.Errorf(status.Internal, "failed to get user invites from store")
|
|
}
|
|
|
|
for _, invite := range invites {
|
|
if err := invite.DecryptSensitiveData(s.fieldEncrypt); err != nil {
|
|
return nil, fmt.Errorf("decrypt invite: %w", err)
|
|
}
|
|
}
|
|
|
|
return invites, nil
|
|
}
|
|
|
|
// DeleteUserInvite deletes a user invite by its ID
|
|
func (s *SqlStore) DeleteUserInvite(ctx context.Context, inviteID string) error {
|
|
result := s.db.Delete(&types.UserInviteRecord{}, idQueryCondition, inviteID)
|
|
if result.Error != nil {
|
|
log.WithContext(ctx).Errorf("failed to delete user invite from store: %s", result.Error)
|
|
return status.Errorf(status.Internal, "failed to delete user invite from store")
|
|
}
|
|
return nil
|
|
}
|