implement graphQL and init postgres

This commit is contained in:
Fran Jurmanović
2025-07-06 19:19:36 +02:00
parent 016728532c
commit 26a0d33592
25 changed files with 1713 additions and 314 deletions

View File

@@ -8,6 +8,7 @@ import (
"omega-server/local/utl/jwt"
"omega-server/local/utl/logging"
"os"
"strings"
"github.com/google/uuid"
)
@@ -38,8 +39,8 @@ func (s *MembershipService) SetCacheInvalidator(invalidator CacheInvalidator) {
}
// Login authenticates a user and returns a JWT.
func (s *MembershipService) Login(ctx context.Context, username, password string) (string, error) {
user, err := s.repo.FindUserByUsername(ctx, username)
func (s *MembershipService) Login(ctx context.Context, email, password string) (string, error) {
user, err := s.repo.FindUserByEmail(ctx, email)
if err != nil {
return "", errors.New("invalid credentials")
}
@@ -55,38 +56,42 @@ func (s *MembershipService) Login(ctx context.Context, username, password string
roleNames[i] = role.Name
}
return jwt.GenerateToken(user.ID, user.Email, user.Username, roleNames)
return jwt.GenerateToken(user.ID, user.Email, user.FullName, roleNames)
}
// CreateUser creates a new user.
func (s *MembershipService) CreateUser(ctx context.Context, username, password, roleName string) (*model.User, error) {
role, err := s.repo.FindRoleByName(ctx, roleName)
if err != nil {
logging.Error("Failed to find role by name: %v", err)
return nil, errors.New("role not found")
}
user := &model.User{
Username: username,
Email: username + "@example.com", // You may want to accept email as parameter
Name: username,
}
// Set password using the model's SetPassword method
if err := user.SetPassword(password); err != nil {
func (s *MembershipService) CreateUser(ctx context.Context, user *model.User, roleIDs []string) (*model.User, error) {
// Validate domain model
if err := user.Validate(); err != nil {
return nil, err
}
// Assign roles
user.Roles = []model.Role{*role}
// Handle roles
if len(roleIDs) > 0 {
roles := make([]model.Role, 0, len(roleIDs))
for _, roleID := range roleIDs {
role, err := s.repo.FindRoleByName(ctx, roleID)
if err != nil {
logging.Error("Failed to find role by name: %v", err)
return nil, errors.New("role not found: " + roleID)
}
roles = append(roles, *role)
}
user.Roles = roles
}
// Create user
if err := s.repo.CreateUser(ctx, user); err != nil {
logging.Error("Failed to create user: %v", err)
return nil, err
}
logging.InfoOperation("USER_CREATE", "Created user: "+user.Username+" (ID: "+user.ID+", Role: "+roleName+")")
// Log with role names
roleNames := make([]string, len(user.Roles))
for i, role := range user.Roles {
roleNames[i] = role.Name
}
logging.InfoOperation("USER_CREATE", "Created user: "+user.Email+" (ID: "+user.ID+", Roles: "+strings.Join(roleNames, ", ")+")")
return user, nil
}
@@ -105,13 +110,6 @@ func (s *MembershipService) GetUserWithPermissions(ctx context.Context, userID s
return s.repo.FindUserByIDWithPermissions(ctx, userID)
}
// UpdateUserRequest defines the request body for updating a user.
type UpdateUserRequest struct {
Username *string `json:"username"`
Password *string `json:"password"`
RoleID *string `json:"roleId"`
}
// DeleteUser deletes a user with validation to prevent Super Admin deletion.
func (s *MembershipService) DeleteUser(ctx context.Context, userID uuid.UUID) error {
// Get user with role information
@@ -142,34 +140,42 @@ func (s *MembershipService) DeleteUser(ctx context.Context, userID uuid.UUID) er
}
// UpdateUser updates a user's details.
func (s *MembershipService) UpdateUser(ctx context.Context, userID uuid.UUID, req UpdateUserRequest) (*model.User, error) {
func (s *MembershipService) UpdateUser(ctx context.Context, userID uuid.UUID, req *model.UserUpdateRequest) (*model.User, error) {
// Validate request
if err := req.Validate(); err != nil {
return nil, err
}
user, err := s.repo.FindUserByID(ctx, userID)
if err != nil {
return nil, errors.New("user not found")
}
if req.Username != nil {
user.Username = *req.Username
// Apply update request to user
if err := req.ApplyToUser(user); err != nil {
return nil, err
}
if req.Password != nil && *req.Password != "" {
// Use the model's SetPassword method to hash the password
if err := user.SetPassword(*req.Password); err != nil {
return nil, err
// Handle roles if provided
if len(req.RoleIDs) > 0 {
roles := make([]model.Role, 0, len(req.RoleIDs))
for _, roleID := range req.RoleIDs {
roleUUID, err := uuid.Parse(roleID)
if err != nil {
return nil, errors.New("invalid role ID format: " + roleID)
}
role, err := s.repo.FindRoleByID(ctx, roleUUID)
if err != nil {
return nil, errors.New("role not found: " + roleID)
}
roles = append(roles, *role)
}
user.Roles = roles
}
if req.RoleID != nil {
// Check if role exists
roleUUID, err := uuid.Parse(*req.RoleID)
if err != nil {
return nil, errors.New("invalid role ID format")
}
role, err := s.repo.FindRoleByID(ctx, roleUUID)
if err != nil {
return nil, errors.New("role not found")
}
user.Roles = []model.Role{*role}
// Validate updated user
if err := user.Validate(); err != nil {
return nil, err
}
if err := s.repo.UpdateUser(ctx, user); err != nil {
@@ -177,11 +183,11 @@ func (s *MembershipService) UpdateUser(ctx context.Context, userID uuid.UUID, re
}
// Invalidate cache if role was changed
if req.RoleID != nil && s.cacheInvalidator != nil {
if len(req.RoleIDs) > 0 && s.cacheInvalidator != nil {
s.cacheInvalidator.InvalidateUserPermissions(userID.String())
}
logging.InfoOperation("USER_UPDATE", "Updated user: "+user.Username+" (ID: "+user.ID+")")
logging.InfoOperation("USER_UPDATE", "Updated user: "+user.Email+" (ID: "+user.ID+")")
return user, nil
}
@@ -289,10 +295,17 @@ func (s *MembershipService) SetupInitialData(ctx context.Context) error {
}
// Create a default admin user if one doesn't exist
_, err = s.repo.FindUserByUsername(ctx, "admin")
_, err = s.repo.FindUserByEmail(ctx, "admin@example.com")
if err != nil {
logging.Debug("Creating default admin user")
_, err = s.CreateUser(ctx, "admin", os.Getenv("PASSWORD"), "Super Admin") // Default password, should be changed
adminUser := &model.User{
Email: "admin@example.com",
FullName: "System Administrator",
}
if err := adminUser.SetPassword(os.Getenv("PASSWORD")); err != nil {
return err
}
_, err = s.CreateUser(ctx, adminUser, []string{"Super Admin"})
if err != nil {
return err
}