package services import ( "context" "ms-auth/internal/lib" "ms-auth/internal/models" ) type UserStorage interface { CreateUser(ctx context.Context, user *models.User) (int32, error) ReadUserByEmail(ctx context.Context, email string) (*models.User, error) ReadUserByUsername(ctx context.Context, username string) (*models.User, error) ReadUserById(ctx context.Context, id int32) (*models.User, error) UpdateUser(ctx context.Context, user *models.User) error DeleteUser(ctx context.Context, id int32) error } type UserService struct { userProvider UserStorage sessionProvider SessionProvider cfg lib.Config } func NewUserService( userProvider UserStorage, sessionProvider SessionProvider, cfg lib.Config, ) *UserService { return &UserService{ userProvider: userProvider, sessionProvider: sessionProvider, cfg: cfg, } } func (u *UserService) CreateUser(ctx context.Context, user *models.User) (int32, error) { me := ctx.Value("user").(*models.User) switch *me.Role { case models.RoleAdmin: break case models.RoleModerator: if !user.Role.AtMost(models.RoleParticipant) { return 0, lib.ErrNoPermission } default: return 0, lib.ErrNoPermission } return u.userProvider.CreateUser(ctx, user) } func (u *UserService) ReadUserBySessionToken(ctx context.Context, token string) (*models.User, error) { session, err := u.sessionProvider.ReadSessionByToken(ctx, token) if err != nil { return nil, err } return u.userProvider.ReadUserById(ctx, *session.UserId) } func (u *UserService) ReadUser(ctx context.Context, id int32) (*models.User, error) { return u.userProvider.ReadUserById(ctx, id) } func (u *UserService) ReadUserByEmail(ctx context.Context, email string) (*models.User, error) { return u.userProvider.ReadUserByEmail(ctx, email) } func (u *UserService) ReadUserByUsername(ctx context.Context, username string) (*models.User, error) { return u.userProvider.ReadUserByUsername(ctx, username) } func (u *UserService) UpdateUser(ctx context.Context, modifiedUser *models.User) error { me := ctx.Value("user").(*models.User) user, err := u.userProvider.ReadUserById(ctx, *modifiedUser.Id) if err != nil { return err } hasAccess := func() bool { if me.Role.IsAdmin() { return true } if me.Role.IsModerator() { if !user.Role.AtMost(models.RoleParticipant) { return false } return true } if me.Role.IsParticipant() { if me.Id != user.Id { return false } if modifiedUser.Username != nil { return false } if modifiedUser.Email != nil { return false } if modifiedUser.ExpiresAt != nil { return false } if modifiedUser.Role != nil { return false } return true } if me.Role.IsSpectator() { return false } return false }() if !hasAccess { return lib.ErrNoPermission } return u.userProvider.UpdateUser(ctx, user) } func (u *UserService) DeleteUser(ctx context.Context, id int32) error { me := ctx.Value("user").(*models.User) if *me.Id == id || !me.Role.IsAdmin() { return lib.ErrNoPermission } return u.userProvider.DeleteUser(ctx, id) }