package repository import ( "context" "errors" "github.com/Tencent/WeKnora/internal/types" "github.com/Tencent/WeKnora/internal/types/interfaces" "gorm.io/gorm" ) var ( ErrUserNotFound = errors.New("user not found") ErrUserAlreadyExists = errors.New("user already exists") ErrTokenNotFound = errors.New("token not found") ) // userRepository implements user repository interface type userRepository struct { db *gorm.DB } // NewUserRepository creates a new user repository func NewUserRepository(db *gorm.DB) interfaces.UserRepository { return &userRepository{db: db} } // CreateUser creates a user func (r *userRepository) CreateUser(ctx context.Context, user *types.User) error { return r.db.WithContext(ctx).Create(user).Error } // GetUserByID gets a user by ID func (r *userRepository) GetUserByID(ctx context.Context, id string) (*types.User, error) { var user types.User if err := r.db.WithContext(ctx).Where("id = ?", id).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrUserNotFound } return nil, err } return &user, nil } // GetUserByEmail gets a user by email func (r *userRepository) GetUserByEmail(ctx context.Context, email string) (*types.User, error) { var user types.User if err := r.db.WithContext(ctx).Where("email = ?", email).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrUserNotFound } return nil, err } return &user, nil } // GetUserByUsername gets a user by username func (r *userRepository) GetUserByUsername(ctx context.Context, username string) (*types.User, error) { var user types.User if err := r.db.WithContext(ctx).Where("username = ?", username).First(&user).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrUserNotFound } return nil, err } return &user, nil } // UpdateUser updates a user func (r *userRepository) UpdateUser(ctx context.Context, user *types.User) error { return r.db.WithContext(ctx).Save(user).Error } // DeleteUser deletes a user func (r *userRepository) DeleteUser(ctx context.Context, id string) error { return r.db.WithContext(ctx).Where("id = ?", id).Delete(&types.User{}).Error } // ListUsers lists users with pagination func (r *userRepository) ListUsers(ctx context.Context, offset, limit int) ([]*types.User, error) { var users []*types.User query := r.db.WithContext(ctx).Order("created_at DESC") if limit > 0 { query = query.Limit(limit) } if offset > 0 { query = query.Offset(offset) } if err := query.Find(&users).Error; err != nil { return nil, err } return users, nil } // authTokenRepository implements auth token repository interface type authTokenRepository struct { db *gorm.DB } // NewAuthTokenRepository creates a new auth token repository func NewAuthTokenRepository(db *gorm.DB) interfaces.AuthTokenRepository { return &authTokenRepository{db: db} } // CreateToken creates an auth token func (r *authTokenRepository) CreateToken(ctx context.Context, token *types.AuthToken) error { return r.db.WithContext(ctx).Create(token).Error } // GetTokenByValue gets a token by its value func (r *authTokenRepository) GetTokenByValue(ctx context.Context, tokenValue string) (*types.AuthToken, error) { var token types.AuthToken if err := r.db.WithContext(ctx).Where("token = ?", tokenValue).First(&token).Error; err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrTokenNotFound } return nil, err } return &token, nil } // GetTokensByUserID gets all tokens for a user func (r *authTokenRepository) GetTokensByUserID(ctx context.Context, userID string) ([]*types.AuthToken, error) { var tokens []*types.AuthToken if err := r.db.WithContext(ctx).Where("user_id = ?", userID).Find(&tokens).Error; err != nil { return nil, err } return tokens, nil } // UpdateToken updates a token func (r *authTokenRepository) UpdateToken(ctx context.Context, token *types.AuthToken) error { return r.db.WithContext(ctx).Save(token).Error } // DeleteToken deletes a token func (r *authTokenRepository) DeleteToken(ctx context.Context, id string) error { return r.db.WithContext(ctx).Where("id = ?", id).Delete(&types.AuthToken{}).Error } // DeleteExpiredTokens deletes all expired tokens func (r *authTokenRepository) DeleteExpiredTokens(ctx context.Context) error { return r.db.WithContext(ctx).Where("expires_at < NOW()").Delete(&types.AuthToken{}).Error } // RevokeTokensByUserID revokes all tokens for a user func (r *authTokenRepository) RevokeTokensByUserID(ctx context.Context, userID string) error { return r.db.WithContext(ctx).Model(&types.AuthToken{}).Where("user_id = ?", userID).Update("is_revoked", true).Error }