|
@@ -13,6 +13,7 @@ import (
|
|
|
|
|
|
|
|
"gogs.dmsc.dev/arp/auth"
|
|
"gogs.dmsc.dev/arp/auth"
|
|
|
"gogs.dmsc.dev/arp/graph/model"
|
|
"gogs.dmsc.dev/arp/graph/model"
|
|
|
|
|
+ "gogs.dmsc.dev/arp/logging"
|
|
|
"gogs.dmsc.dev/arp/models"
|
|
"gogs.dmsc.dev/arp/models"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
@@ -41,6 +42,11 @@ func (r *mutationResolver) Login(ctx context.Context, email string, password str
|
|
|
|
|
|
|
|
// CreateUser is the resolver for the createUser field.
|
|
// CreateUser is the resolver for the createUser field.
|
|
|
func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) {
|
|
func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser) (*model.User, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
roles := make([]models.Role, len(input.Roles))
|
|
roles := make([]models.Role, len(input.Roles))
|
|
|
for i, roleIDStr := range input.Roles {
|
|
for i, roleIDStr := range input.Roles {
|
|
|
roleID, err := toID(roleIDStr)
|
|
roleID, err := toID(roleIDStr)
|
|
@@ -70,12 +76,16 @@ func (r *mutationResolver) CreateUser(ctx context.Context, input model.NewUser)
|
|
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "USER", user.Email)
|
|
|
return convertUser(user), nil
|
|
return convertUser(user), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateUser is the resolver for the updateUser field.
|
|
// UpdateUser is the resolver for the updateUser field.
|
|
|
func (r *mutationResolver) UpdateUser(ctx context.Context, id string, input model.UpdateUserInput) (*model.User, error) {
|
|
func (r *mutationResolver) UpdateUser(ctx context.Context, id string, input model.UpdateUserInput) (*model.User, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "user:update") {
|
|
if !auth.HasPermission(ctx, "user:update") {
|
|
|
return nil, errors.New("unauthorized: missing user:update permission")
|
|
return nil, errors.New("unauthorized: missing user:update permission")
|
|
|
}
|
|
}
|
|
@@ -121,12 +131,16 @@ func (r *mutationResolver) UpdateUser(ctx context.Context, id string, input mode
|
|
|
return nil, fmt.Errorf("failed to update user: %w", err)
|
|
return nil, fmt.Errorf("failed to update user: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "USER", existing.Email)
|
|
|
return convertUser(existing), nil
|
|
return convertUser(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteUser is the resolver for the deleteUser field.
|
|
// DeleteUser is the resolver for the deleteUser field.
|
|
|
func (r *mutationResolver) DeleteUser(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteUser(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "user:delete") {
|
|
if !auth.HasPermission(ctx, "user:delete") {
|
|
|
return false, errors.New("unauthorized: missing user:delete permission")
|
|
return false, errors.New("unauthorized: missing user:delete permission")
|
|
|
}
|
|
}
|
|
@@ -141,11 +155,17 @@ func (r *mutationResolver) DeleteUser(ctx context.Context, id string) (bool, err
|
|
|
return false, fmt.Errorf("failed to delete user: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete user: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "USER", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateNote is the resolver for the createNote field.
|
|
// CreateNote is the resolver for the createNote field.
|
|
|
func (r *mutationResolver) CreateNote(ctx context.Context, input model.NewNote) (*model.Note, error) {
|
|
func (r *mutationResolver) CreateNote(ctx context.Context, input model.NewNote) (*model.Note, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
userID, err := toID(input.UserID)
|
|
userID, err := toID(input.UserID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid user ID: %w", err)
|
|
return nil, fmt.Errorf("invalid user ID: %w", err)
|
|
@@ -167,12 +187,16 @@ func (r *mutationResolver) CreateNote(ctx context.Context, input model.NewNote)
|
|
|
return nil, fmt.Errorf("failed to create note: %w", err)
|
|
return nil, fmt.Errorf("failed to create note: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "NOTE", note.Title)
|
|
|
return convertNote(note), nil
|
|
return convertNote(note), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateNote is the resolver for the updateNote field.
|
|
// UpdateNote is the resolver for the updateNote field.
|
|
|
func (r *mutationResolver) UpdateNote(ctx context.Context, id string, input model.UpdateNoteInput) (*model.Note, error) {
|
|
func (r *mutationResolver) UpdateNote(ctx context.Context, id string, input model.UpdateNoteInput) (*model.Note, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "note:update") {
|
|
if !auth.HasPermission(ctx, "note:update") {
|
|
|
return nil, errors.New("unauthorized: missing note:update permission")
|
|
return nil, errors.New("unauthorized: missing note:update permission")
|
|
|
}
|
|
}
|
|
@@ -212,12 +236,16 @@ func (r *mutationResolver) UpdateNote(ctx context.Context, id string, input mode
|
|
|
return nil, fmt.Errorf("failed to update note: %w", err)
|
|
return nil, fmt.Errorf("failed to update note: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "NOTE", existing.Title)
|
|
|
return convertNote(existing), nil
|
|
return convertNote(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteNote is the resolver for the deleteNote field.
|
|
// DeleteNote is the resolver for the deleteNote field.
|
|
|
func (r *mutationResolver) DeleteNote(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteNote(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "note:delete") {
|
|
if !auth.HasPermission(ctx, "note:delete") {
|
|
|
return false, errors.New("unauthorized: missing note:delete permission")
|
|
return false, errors.New("unauthorized: missing note:delete permission")
|
|
|
}
|
|
}
|
|
@@ -232,11 +260,17 @@ func (r *mutationResolver) DeleteNote(ctx context.Context, id string) (bool, err
|
|
|
return false, fmt.Errorf("failed to delete note: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete note: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "NOTE", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateRole is the resolver for the createRole field.
|
|
// CreateRole is the resolver for the createRole field.
|
|
|
func (r *mutationResolver) CreateRole(ctx context.Context, input model.NewRole) (*model.Role, error) {
|
|
func (r *mutationResolver) CreateRole(ctx context.Context, input model.NewRole) (*model.Role, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
permissions := make([]models.Permission, len(input.Permissions))
|
|
permissions := make([]models.Permission, len(input.Permissions))
|
|
|
for i, permIDStr := range input.Permissions {
|
|
for i, permIDStr := range input.Permissions {
|
|
|
permID, err := toID(permIDStr)
|
|
permID, err := toID(permIDStr)
|
|
@@ -260,12 +294,16 @@ func (r *mutationResolver) CreateRole(ctx context.Context, input model.NewRole)
|
|
|
return nil, fmt.Errorf("failed to create role: %w", err)
|
|
return nil, fmt.Errorf("failed to create role: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "ROLE", role.Name)
|
|
|
return convertRole(role), nil
|
|
return convertRole(role), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateRole is the resolver for the updateRole field.
|
|
// UpdateRole is the resolver for the updateRole field.
|
|
|
func (r *mutationResolver) UpdateRole(ctx context.Context, id string, input model.UpdateRoleInput) (*model.Role, error) {
|
|
func (r *mutationResolver) UpdateRole(ctx context.Context, id string, input model.UpdateRoleInput) (*model.Role, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "role:update") {
|
|
if !auth.HasPermission(ctx, "role:update") {
|
|
|
return nil, errors.New("unauthorized: missing role:update permission")
|
|
return nil, errors.New("unauthorized: missing role:update permission")
|
|
|
}
|
|
}
|
|
@@ -306,12 +344,16 @@ func (r *mutationResolver) UpdateRole(ctx context.Context, id string, input mode
|
|
|
return nil, fmt.Errorf("failed to update role: %w", err)
|
|
return nil, fmt.Errorf("failed to update role: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "ROLE", existing.Name)
|
|
|
return convertRole(existing), nil
|
|
return convertRole(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteRole is the resolver for the deleteRole field.
|
|
// DeleteRole is the resolver for the deleteRole field.
|
|
|
func (r *mutationResolver) DeleteRole(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteRole(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "role:delete") {
|
|
if !auth.HasPermission(ctx, "role:delete") {
|
|
|
return false, errors.New("unauthorized: missing role:delete permission")
|
|
return false, errors.New("unauthorized: missing role:delete permission")
|
|
|
}
|
|
}
|
|
@@ -326,11 +368,17 @@ func (r *mutationResolver) DeleteRole(ctx context.Context, id string) (bool, err
|
|
|
return false, fmt.Errorf("failed to delete role: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete role: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "ROLE", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreatePermission is the resolver for the createPermission field.
|
|
// CreatePermission is the resolver for the createPermission field.
|
|
|
func (r *mutationResolver) CreatePermission(ctx context.Context, input model.NewPermission) (*model.Permission, error) {
|
|
func (r *mutationResolver) CreatePermission(ctx context.Context, input model.NewPermission) (*model.Permission, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
permission := models.Permission{
|
|
permission := models.Permission{
|
|
|
Code: input.Code,
|
|
Code: input.Code,
|
|
|
Description: input.Description,
|
|
Description: input.Description,
|
|
@@ -340,12 +388,16 @@ func (r *mutationResolver) CreatePermission(ctx context.Context, input model.New
|
|
|
return nil, fmt.Errorf("failed to create permission: %w", err)
|
|
return nil, fmt.Errorf("failed to create permission: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "PERMISSION", permission.Code)
|
|
|
return convertPermission(permission), nil
|
|
return convertPermission(permission), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdatePermission is the resolver for the updatePermission field.
|
|
// UpdatePermission is the resolver for the updatePermission field.
|
|
|
func (r *mutationResolver) UpdatePermission(ctx context.Context, id string, input model.UpdatePermissionInput) (*model.Permission, error) {
|
|
func (r *mutationResolver) UpdatePermission(ctx context.Context, id string, input model.UpdatePermissionInput) (*model.Permission, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "permission:update") {
|
|
if !auth.HasPermission(ctx, "permission:update") {
|
|
|
return nil, errors.New("unauthorized: missing permission:update permission")
|
|
return nil, errors.New("unauthorized: missing permission:update permission")
|
|
|
}
|
|
}
|
|
@@ -371,12 +423,16 @@ func (r *mutationResolver) UpdatePermission(ctx context.Context, id string, inpu
|
|
|
return nil, fmt.Errorf("failed to update permission: %w", err)
|
|
return nil, fmt.Errorf("failed to update permission: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "PERMISSION", existing.Code)
|
|
|
return convertPermission(existing), nil
|
|
return convertPermission(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeletePermission is the resolver for the deletePermission field.
|
|
// DeletePermission is the resolver for the deletePermission field.
|
|
|
func (r *mutationResolver) DeletePermission(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeletePermission(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "permission:delete") {
|
|
if !auth.HasPermission(ctx, "permission:delete") {
|
|
|
return false, errors.New("unauthorized: missing permission:delete permission")
|
|
return false, errors.New("unauthorized: missing permission:delete permission")
|
|
|
}
|
|
}
|
|
@@ -391,11 +447,17 @@ func (r *mutationResolver) DeletePermission(ctx context.Context, id string) (boo
|
|
|
return false, fmt.Errorf("failed to delete permission: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete permission: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "PERMISSION", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateService is the resolver for the createService field.
|
|
// CreateService is the resolver for the createService field.
|
|
|
func (r *mutationResolver) CreateService(ctx context.Context, input model.NewService) (*model.Service, error) {
|
|
func (r *mutationResolver) CreateService(ctx context.Context, input model.NewService) (*model.Service, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
createdByID, err := toID(input.CreatedByID)
|
|
createdByID, err := toID(input.CreatedByID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid created by ID: %w", err)
|
|
return nil, fmt.Errorf("invalid created by ID: %w", err)
|
|
@@ -429,12 +491,16 @@ func (r *mutationResolver) CreateService(ctx context.Context, input model.NewSer
|
|
|
// Reload with associations
|
|
// Reload with associations
|
|
|
r.DB.Preload("Participants").Preload("Tasks").First(&service, service.ID)
|
|
r.DB.Preload("Participants").Preload("Tasks").First(&service, service.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "SERVICE", service.Name)
|
|
|
return convertService(service), nil
|
|
return convertService(service), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateService is the resolver for the updateService field.
|
|
// UpdateService is the resolver for the updateService field.
|
|
|
func (r *mutationResolver) UpdateService(ctx context.Context, id string, input model.UpdateServiceInput) (*model.Service, error) {
|
|
func (r *mutationResolver) UpdateService(ctx context.Context, id string, input model.UpdateServiceInput) (*model.Service, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "service:update") {
|
|
if !auth.HasPermission(ctx, "service:update") {
|
|
|
return nil, errors.New("unauthorized: missing service:update permission")
|
|
return nil, errors.New("unauthorized: missing service:update permission")
|
|
|
}
|
|
}
|
|
@@ -478,12 +544,16 @@ func (r *mutationResolver) UpdateService(ctx context.Context, id string, input m
|
|
|
// Reload with associations for response
|
|
// Reload with associations for response
|
|
|
r.DB.Preload("Participants").Preload("Tasks").First(&existing, existing.ID)
|
|
r.DB.Preload("Participants").Preload("Tasks").First(&existing, existing.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "SERVICE", existing.Name)
|
|
|
return convertService(existing), nil
|
|
return convertService(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteService is the resolver for the deleteService field.
|
|
// DeleteService is the resolver for the deleteService field.
|
|
|
func (r *mutationResolver) DeleteService(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteService(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "service:delete") {
|
|
if !auth.HasPermission(ctx, "service:delete") {
|
|
|
return false, errors.New("unauthorized: missing service:delete permission")
|
|
return false, errors.New("unauthorized: missing service:delete permission")
|
|
|
}
|
|
}
|
|
@@ -498,11 +568,17 @@ func (r *mutationResolver) DeleteService(ctx context.Context, id string) (bool,
|
|
|
return false, fmt.Errorf("failed to delete service: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete service: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "SERVICE", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateTask is the resolver for the createTask field.
|
|
// CreateTask is the resolver for the createTask field.
|
|
|
func (r *mutationResolver) CreateTask(ctx context.Context, input model.NewTask) (*model.Task, error) {
|
|
func (r *mutationResolver) CreateTask(ctx context.Context, input model.NewTask) (*model.Task, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
createdByID, err := toID(input.CreatedByID)
|
|
createdByID, err := toID(input.CreatedByID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid created by ID: %w", err)
|
|
return nil, fmt.Errorf("invalid created by ID: %w", err)
|
|
@@ -543,12 +619,16 @@ func (r *mutationResolver) CreateTask(ctx context.Context, input model.NewTask)
|
|
|
// Reload with associations
|
|
// Reload with associations
|
|
|
r.DB.Preload("CreatedBy").Preload("Assignee").Preload("Status").First(&task, task.ID)
|
|
r.DB.Preload("CreatedBy").Preload("Assignee").Preload("Status").First(&task, task.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "TASK", task.Title)
|
|
|
return convertTask(task), nil
|
|
return convertTask(task), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateTask is the resolver for the updateTask field.
|
|
// UpdateTask is the resolver for the updateTask field.
|
|
|
func (r *mutationResolver) UpdateTask(ctx context.Context, id string, input model.UpdateTaskInput) (*model.Task, error) {
|
|
func (r *mutationResolver) UpdateTask(ctx context.Context, id string, input model.UpdateTaskInput) (*model.Task, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "task:update") {
|
|
if !auth.HasPermission(ctx, "task:update") {
|
|
|
return nil, errors.New("unauthorized: missing task:update permission")
|
|
return nil, errors.New("unauthorized: missing task:update permission")
|
|
|
}
|
|
}
|
|
@@ -613,12 +693,16 @@ func (r *mutationResolver) UpdateTask(ctx context.Context, id string, input mode
|
|
|
// Reload with associations for response
|
|
// Reload with associations for response
|
|
|
r.DB.Preload("CreatedBy").Preload("Assignee").Preload("Status").First(&existing, existing.ID)
|
|
r.DB.Preload("CreatedBy").Preload("Assignee").Preload("Status").First(&existing, existing.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "TASK", existing.Title)
|
|
|
return convertTask(existing), nil
|
|
return convertTask(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteTask is the resolver for the deleteTask field.
|
|
// DeleteTask is the resolver for the deleteTask field.
|
|
|
func (r *mutationResolver) DeleteTask(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteTask(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "task:delete") {
|
|
if !auth.HasPermission(ctx, "task:delete") {
|
|
|
return false, errors.New("unauthorized: missing task:delete permission")
|
|
return false, errors.New("unauthorized: missing task:delete permission")
|
|
|
}
|
|
}
|
|
@@ -633,11 +717,17 @@ func (r *mutationResolver) DeleteTask(ctx context.Context, id string) (bool, err
|
|
|
return false, fmt.Errorf("failed to delete task: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete task: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "TASK", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateTaskStatus is the resolver for the createTaskStatus field.
|
|
// CreateTaskStatus is the resolver for the createTaskStatus field.
|
|
|
func (r *mutationResolver) CreateTaskStatus(ctx context.Context, input model.NewTaskStatus) (*model.TaskStatus, error) {
|
|
func (r *mutationResolver) CreateTaskStatus(ctx context.Context, input model.NewTaskStatus) (*model.TaskStatus, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
taskStatus := models.TaskStatus{
|
|
taskStatus := models.TaskStatus{
|
|
|
Code: input.Code,
|
|
Code: input.Code,
|
|
|
Label: input.Label,
|
|
Label: input.Label,
|
|
@@ -647,12 +737,16 @@ func (r *mutationResolver) CreateTaskStatus(ctx context.Context, input model.New
|
|
|
return nil, fmt.Errorf("failed to create task status: %w", err)
|
|
return nil, fmt.Errorf("failed to create task status: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "TASKSTATUS", taskStatus.Code)
|
|
|
return convertTaskStatus(taskStatus), nil
|
|
return convertTaskStatus(taskStatus), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateTaskStatus is the resolver for the updateTaskStatus field.
|
|
// UpdateTaskStatus is the resolver for the updateTaskStatus field.
|
|
|
func (r *mutationResolver) UpdateTaskStatus(ctx context.Context, id string, input model.UpdateTaskStatusInput) (*model.TaskStatus, error) {
|
|
func (r *mutationResolver) UpdateTaskStatus(ctx context.Context, id string, input model.UpdateTaskStatusInput) (*model.TaskStatus, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "taskstatus:update") {
|
|
if !auth.HasPermission(ctx, "taskstatus:update") {
|
|
|
return nil, errors.New("unauthorized: missing taskstatus:update permission")
|
|
return nil, errors.New("unauthorized: missing taskstatus:update permission")
|
|
|
}
|
|
}
|
|
@@ -681,12 +775,16 @@ func (r *mutationResolver) UpdateTaskStatus(ctx context.Context, id string, inpu
|
|
|
// Reload with tasks for response
|
|
// Reload with tasks for response
|
|
|
r.DB.Preload("Tasks").First(&existing, existing.ID)
|
|
r.DB.Preload("Tasks").First(&existing, existing.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "TASKSTATUS", existing.Code)
|
|
|
return convertTaskStatus(existing), nil
|
|
return convertTaskStatus(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteTaskStatus is the resolver for the deleteTaskStatus field.
|
|
// DeleteTaskStatus is the resolver for the deleteTaskStatus field.
|
|
|
func (r *mutationResolver) DeleteTaskStatus(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteTaskStatus(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "taskstatus:delete") {
|
|
if !auth.HasPermission(ctx, "taskstatus:delete") {
|
|
|
return false, errors.New("unauthorized: missing taskstatus:delete permission")
|
|
return false, errors.New("unauthorized: missing taskstatus:delete permission")
|
|
|
}
|
|
}
|
|
@@ -701,11 +799,17 @@ func (r *mutationResolver) DeleteTaskStatus(ctx context.Context, id string) (boo
|
|
|
return false, fmt.Errorf("failed to delete task status: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete task status: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "TASKSTATUS", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateChannel is the resolver for the createChannel field.
|
|
// CreateChannel is the resolver for the createChannel field.
|
|
|
func (r *mutationResolver) CreateChannel(ctx context.Context, input model.NewChannel) (*model.Channel, error) {
|
|
func (r *mutationResolver) CreateChannel(ctx context.Context, input model.NewChannel) (*model.Channel, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
channel := models.Channel{}
|
|
channel := models.Channel{}
|
|
|
|
|
|
|
|
for _, participantIDStr := range input.Participants {
|
|
for _, participantIDStr := range input.Participants {
|
|
@@ -727,12 +831,16 @@ func (r *mutationResolver) CreateChannel(ctx context.Context, input model.NewCha
|
|
|
// Reload with participants
|
|
// Reload with participants
|
|
|
r.DB.Preload("Participants").First(&channel, channel.ID)
|
|
r.DB.Preload("Participants").First(&channel, channel.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "CHANNEL", fmt.Sprintf("id=%d", channel.ID))
|
|
|
return convertChannel(channel), nil
|
|
return convertChannel(channel), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateChannel is the resolver for the updateChannel field.
|
|
// UpdateChannel is the resolver for the updateChannel field.
|
|
|
func (r *mutationResolver) UpdateChannel(ctx context.Context, id string, input model.UpdateChannelInput) (*model.Channel, error) {
|
|
func (r *mutationResolver) UpdateChannel(ctx context.Context, id string, input model.UpdateChannelInput) (*model.Channel, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "channel:update") {
|
|
if !auth.HasPermission(ctx, "channel:update") {
|
|
|
return nil, errors.New("unauthorized: missing channel:update permission")
|
|
return nil, errors.New("unauthorized: missing channel:update permission")
|
|
|
}
|
|
}
|
|
@@ -765,12 +873,16 @@ func (r *mutationResolver) UpdateChannel(ctx context.Context, id string, input m
|
|
|
return nil, fmt.Errorf("failed to update channel: %w", err)
|
|
return nil, fmt.Errorf("failed to update channel: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "CHANNEL", id)
|
|
|
return convertChannel(existing), nil
|
|
return convertChannel(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteChannel is the resolver for the deleteChannel field.
|
|
// DeleteChannel is the resolver for the deleteChannel field.
|
|
|
func (r *mutationResolver) DeleteChannel(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteChannel(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "channel:delete") {
|
|
if !auth.HasPermission(ctx, "channel:delete") {
|
|
|
return false, errors.New("unauthorized: missing channel:delete permission")
|
|
return false, errors.New("unauthorized: missing channel:delete permission")
|
|
|
}
|
|
}
|
|
@@ -785,11 +897,17 @@ func (r *mutationResolver) DeleteChannel(ctx context.Context, id string) (bool,
|
|
|
return false, fmt.Errorf("failed to delete channel: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete channel: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "CHANNEL", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// CreateMessage is the resolver for the createMessage field.
|
|
// CreateMessage is the resolver for the createMessage field.
|
|
|
func (r *mutationResolver) CreateMessage(ctx context.Context, input model.NewMessage) (*model.Message, error) {
|
|
func (r *mutationResolver) CreateMessage(ctx context.Context, input model.NewMessage) (*model.Message, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
conversationID, err := toID(input.ConversationID)
|
|
conversationID, err := toID(input.ConversationID)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid conversation ID: %w", err)
|
|
return nil, fmt.Errorf("invalid conversation ID: %w", err)
|
|
@@ -812,12 +930,16 @@ func (r *mutationResolver) CreateMessage(ctx context.Context, input model.NewMes
|
|
|
// Reload with associations
|
|
// Reload with associations
|
|
|
r.DB.Preload("Sender").First(&message, message.ID)
|
|
r.DB.Preload("Sender").First(&message, message.ID)
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "CREATE", "MESSAGE", fmt.Sprintf("id=%d", message.ID))
|
|
|
return convertMessage(message), nil
|
|
return convertMessage(message), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// UpdateMessage is the resolver for the updateMessage field.
|
|
// UpdateMessage is the resolver for the updateMessage field.
|
|
|
func (r *mutationResolver) UpdateMessage(ctx context.Context, id string, input model.UpdateMessageInput) (*model.Message, error) {
|
|
func (r *mutationResolver) UpdateMessage(ctx context.Context, id string, input model.UpdateMessageInput) (*model.Message, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "message:update") {
|
|
if !auth.HasPermission(ctx, "message:update") {
|
|
|
return nil, errors.New("unauthorized: missing message:update permission")
|
|
return nil, errors.New("unauthorized: missing message:update permission")
|
|
|
}
|
|
}
|
|
@@ -854,12 +976,16 @@ func (r *mutationResolver) UpdateMessage(ctx context.Context, id string, input m
|
|
|
return nil, fmt.Errorf("failed to update message: %w", err)
|
|
return nil, fmt.Errorf("failed to update message: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "UPDATE", "MESSAGE", id)
|
|
|
return convertMessage(existing), nil
|
|
return convertMessage(existing), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// DeleteMessage is the resolver for the deleteMessage field.
|
|
// DeleteMessage is the resolver for the deleteMessage field.
|
|
|
func (r *mutationResolver) DeleteMessage(ctx context.Context, id string) (bool, error) {
|
|
func (r *mutationResolver) DeleteMessage(ctx context.Context, id string) (bool, error) {
|
|
|
// Auth check
|
|
// Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return false, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
if !auth.HasPermission(ctx, "message:delete") {
|
|
if !auth.HasPermission(ctx, "message:delete") {
|
|
|
return false, errors.New("unauthorized: missing message:delete permission")
|
|
return false, errors.New("unauthorized: missing message:delete permission")
|
|
|
}
|
|
}
|
|
@@ -874,20 +1000,32 @@ func (r *mutationResolver) DeleteMessage(ctx context.Context, id string) (bool,
|
|
|
return false, fmt.Errorf("failed to delete message: %w", result.Error)
|
|
return false, fmt.Errorf("failed to delete message: %w", result.Error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogMutation(ctx, "DELETE", "MESSAGE", id)
|
|
|
return result.RowsAffected > 0, nil
|
|
return result.RowsAffected > 0, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Users is the resolver for the users field.
|
|
// Users is the resolver for the users field.
|
|
|
func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
|
|
func (r *queryResolver) Users(ctx context.Context) ([]*model.User, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var users []models.User
|
|
var users []models.User
|
|
|
if err := r.DB.Find(&users).Error; err != nil {
|
|
if err := r.DB.Find(&users).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch users: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch users: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "USERS", "all")
|
|
|
return convertUsers(users), nil
|
|
return convertUsers(users), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// User is the resolver for the user field.
|
|
// User is the resolver for the user field.
|
|
|
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
|
|
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
userID, err := toID(id)
|
|
userID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid user ID: %w", err)
|
|
return nil, fmt.Errorf("invalid user ID: %w", err)
|
|
@@ -898,20 +1036,32 @@ func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error
|
|
|
return nil, fmt.Errorf("user not found: %w", err)
|
|
return nil, fmt.Errorf("user not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "USER", id)
|
|
|
return convertUser(user), nil
|
|
return convertUser(user), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Notes is the resolver for the notes field.
|
|
// Notes is the resolver for the notes field.
|
|
|
func (r *queryResolver) Notes(ctx context.Context) ([]*model.Note, error) {
|
|
func (r *queryResolver) Notes(ctx context.Context) ([]*model.Note, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var notes []models.Note
|
|
var notes []models.Note
|
|
|
if err := r.DB.Preload("User").Preload("Service").Find(¬es).Error; err != nil {
|
|
if err := r.DB.Preload("User").Preload("Service").Find(¬es).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch notes: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch notes: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "NOTES", "all")
|
|
|
return convertNotes(notes), nil
|
|
return convertNotes(notes), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Note is the resolver for the note field.
|
|
// Note is the resolver for the note field.
|
|
|
func (r *queryResolver) Note(ctx context.Context, id string) (*model.Note, error) {
|
|
func (r *queryResolver) Note(ctx context.Context, id string) (*model.Note, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
noteID, err := toID(id)
|
|
noteID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid note ID: %w", err)
|
|
return nil, fmt.Errorf("invalid note ID: %w", err)
|
|
@@ -922,20 +1072,32 @@ func (r *queryResolver) Note(ctx context.Context, id string) (*model.Note, error
|
|
|
return nil, fmt.Errorf("note not found: %w", err)
|
|
return nil, fmt.Errorf("note not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "NOTE", id)
|
|
|
return convertNote(note), nil
|
|
return convertNote(note), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Roles is the resolver for the roles field.
|
|
// Roles is the resolver for the roles field.
|
|
|
func (r *queryResolver) Roles(ctx context.Context) ([]*model.Role, error) {
|
|
func (r *queryResolver) Roles(ctx context.Context) ([]*model.Role, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var roles []models.Role
|
|
var roles []models.Role
|
|
|
if err := r.DB.Preload("Permissions").Find(&roles).Error; err != nil {
|
|
if err := r.DB.Preload("Permissions").Find(&roles).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch roles: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch roles: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "ROLES", "all")
|
|
|
return convertRoles(roles), nil
|
|
return convertRoles(roles), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Role is the resolver for the role field.
|
|
// Role is the resolver for the role field.
|
|
|
func (r *queryResolver) Role(ctx context.Context, id string) (*model.Role, error) {
|
|
func (r *queryResolver) Role(ctx context.Context, id string) (*model.Role, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
roleID, err := toID(id)
|
|
roleID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid role ID: %w", err)
|
|
return nil, fmt.Errorf("invalid role ID: %w", err)
|
|
@@ -946,20 +1108,32 @@ func (r *queryResolver) Role(ctx context.Context, id string) (*model.Role, error
|
|
|
return nil, fmt.Errorf("role not found: %w", err)
|
|
return nil, fmt.Errorf("role not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "ROLE", id)
|
|
|
return convertRole(role), nil
|
|
return convertRole(role), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Permissions is the resolver for the permissions field.
|
|
// Permissions is the resolver for the permissions field.
|
|
|
func (r *queryResolver) Permissions(ctx context.Context) ([]*model.Permission, error) {
|
|
func (r *queryResolver) Permissions(ctx context.Context) ([]*model.Permission, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var perms []models.Permission
|
|
var perms []models.Permission
|
|
|
if err := r.DB.Find(&perms).Error; err != nil {
|
|
if err := r.DB.Find(&perms).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch permissions: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch permissions: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "PERMISSIONS", "all")
|
|
|
return convertPermissions(perms), nil
|
|
return convertPermissions(perms), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Permission is the resolver for the permission field.
|
|
// Permission is the resolver for the permission field.
|
|
|
func (r *queryResolver) Permission(ctx context.Context, id string) (*model.Permission, error) {
|
|
func (r *queryResolver) Permission(ctx context.Context, id string) (*model.Permission, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
permID, err := toID(id)
|
|
permID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid permission ID: %w", err)
|
|
return nil, fmt.Errorf("invalid permission ID: %w", err)
|
|
@@ -970,20 +1144,32 @@ func (r *queryResolver) Permission(ctx context.Context, id string) (*model.Permi
|
|
|
return nil, fmt.Errorf("permission not found: %w", err)
|
|
return nil, fmt.Errorf("permission not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "PERMISSION", id)
|
|
|
return convertPermission(perm), nil
|
|
return convertPermission(perm), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Services is the resolver for the services field.
|
|
// Services is the resolver for the services field.
|
|
|
func (r *queryResolver) Services(ctx context.Context) ([]*model.Service, error) {
|
|
func (r *queryResolver) Services(ctx context.Context) ([]*model.Service, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var services []models.Service
|
|
var services []models.Service
|
|
|
if err := r.DB.Preload("CreatedBy").Preload("Participants").Preload("Tasks").Find(&services).Error; err != nil {
|
|
if err := r.DB.Preload("CreatedBy").Preload("Participants").Preload("Tasks").Find(&services).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch services: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch services: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "SERVICES", "all")
|
|
|
return convertServices(services), nil
|
|
return convertServices(services), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Service is the resolver for the service field.
|
|
// Service is the resolver for the service field.
|
|
|
func (r *queryResolver) Service(ctx context.Context, id string) (*model.Service, error) {
|
|
func (r *queryResolver) Service(ctx context.Context, id string) (*model.Service, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
serviceID, err := toID(id)
|
|
serviceID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid service ID: %w", err)
|
|
return nil, fmt.Errorf("invalid service ID: %w", err)
|
|
@@ -994,20 +1180,32 @@ func (r *queryResolver) Service(ctx context.Context, id string) (*model.Service,
|
|
|
return nil, fmt.Errorf("service not found: %w", err)
|
|
return nil, fmt.Errorf("service not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "SERVICE", id)
|
|
|
return convertService(service), nil
|
|
return convertService(service), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Tasks is the resolver for the tasks field.
|
|
// Tasks is the resolver for the tasks field.
|
|
|
func (r *queryResolver) Tasks(ctx context.Context) ([]*model.Task, error) {
|
|
func (r *queryResolver) Tasks(ctx context.Context) ([]*model.Task, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var tasks []models.Task
|
|
var tasks []models.Task
|
|
|
if err := r.DB.Preload("CreatedBy").Preload("Assignee").Preload("Status").Find(&tasks).Error; err != nil {
|
|
if err := r.DB.Preload("CreatedBy").Preload("Assignee").Preload("Status").Find(&tasks).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch tasks: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch tasks: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "TASKS", "all")
|
|
|
return convertTasks(tasks), nil
|
|
return convertTasks(tasks), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Task is the resolver for the task field.
|
|
// Task is the resolver for the task field.
|
|
|
func (r *queryResolver) Task(ctx context.Context, id string) (*model.Task, error) {
|
|
func (r *queryResolver) Task(ctx context.Context, id string) (*model.Task, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
taskID, err := toID(id)
|
|
taskID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid task ID: %w", err)
|
|
return nil, fmt.Errorf("invalid task ID: %w", err)
|
|
@@ -1018,20 +1216,32 @@ func (r *queryResolver) Task(ctx context.Context, id string) (*model.Task, error
|
|
|
return nil, fmt.Errorf("task not found: %w", err)
|
|
return nil, fmt.Errorf("task not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "TASK", id)
|
|
|
return convertTask(task), nil
|
|
return convertTask(task), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// TaskStatuses is the resolver for the taskStatuses field.
|
|
// TaskStatuses is the resolver for the taskStatuses field.
|
|
|
func (r *queryResolver) TaskStatuses(ctx context.Context) ([]*model.TaskStatus, error) {
|
|
func (r *queryResolver) TaskStatuses(ctx context.Context) ([]*model.TaskStatus, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var statuses []models.TaskStatus
|
|
var statuses []models.TaskStatus
|
|
|
if err := r.DB.Preload("Tasks").Find(&statuses).Error; err != nil {
|
|
if err := r.DB.Preload("Tasks").Find(&statuses).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch task statuses: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch task statuses: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "TASKSTATUSES", "all")
|
|
|
return convertTaskStatuses(statuses), nil
|
|
return convertTaskStatuses(statuses), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// TaskStatus is the resolver for the taskStatus field.
|
|
|
|
|
|
|
+// TaskStatus
|
|
|
func (r *queryResolver) TaskStatus(ctx context.Context, id string) (*model.TaskStatus, error) {
|
|
func (r *queryResolver) TaskStatus(ctx context.Context, id string) (*model.TaskStatus, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
statusID, err := toID(id)
|
|
statusID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid task status ID: %w", err)
|
|
return nil, fmt.Errorf("invalid task status ID: %w", err)
|
|
@@ -1042,20 +1252,32 @@ func (r *queryResolver) TaskStatus(ctx context.Context, id string) (*model.TaskS
|
|
|
return nil, fmt.Errorf("task status not found: %w", err)
|
|
return nil, fmt.Errorf("task status not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "TASKSTATUS", id)
|
|
|
return convertTaskStatus(status), nil
|
|
return convertTaskStatus(status), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Channels is the resolver for the channels field.
|
|
// Channels is the resolver for the channels field.
|
|
|
func (r *queryResolver) Channels(ctx context.Context) ([]*model.Channel, error) {
|
|
func (r *queryResolver) Channels(ctx context.Context) ([]*model.Channel, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var channels []models.Channel
|
|
var channels []models.Channel
|
|
|
if err := r.DB.Preload("Participants").Find(&channels).Error; err != nil {
|
|
if err := r.DB.Preload("Participants").Find(&channels).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch channels: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch channels: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "CHANNELS", "all")
|
|
|
return convertChannels(channels), nil
|
|
return convertChannels(channels), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Channel is the resolver for the channel field.
|
|
// Channel is the resolver for the channel field.
|
|
|
func (r *queryResolver) Channel(ctx context.Context, id string) (*model.Channel, error) {
|
|
func (r *queryResolver) Channel(ctx context.Context, id string) (*model.Channel, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
channelID, err := toID(id)
|
|
channelID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid channel ID: %w", err)
|
|
return nil, fmt.Errorf("invalid channel ID: %w", err)
|
|
@@ -1066,20 +1288,32 @@ func (r *queryResolver) Channel(ctx context.Context, id string) (*model.Channel,
|
|
|
return nil, fmt.Errorf("channel not found: %w", err)
|
|
return nil, fmt.Errorf("channel not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "CHANNEL", id)
|
|
|
return convertChannel(channel), nil
|
|
return convertChannel(channel), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Messages is the resolver for the messages field.
|
|
// Messages is the resolver for the messages field.
|
|
|
func (r *queryResolver) Messages(ctx context.Context) ([]*model.Message, error) {
|
|
func (r *queryResolver) Messages(ctx context.Context) ([]*model.Message, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
var messages []models.Message
|
|
var messages []models.Message
|
|
|
if err := r.DB.Preload("Sender").Find(&messages).Error; err != nil {
|
|
if err := r.DB.Preload("Sender").Find(&messages).Error; err != nil {
|
|
|
return nil, fmt.Errorf("failed to fetch messages: %w", err)
|
|
return nil, fmt.Errorf("failed to fetch messages: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
+ logging.LogQuery(ctx, "MESSAGES", "all")
|
|
|
return convertMessages(messages), nil
|
|
return convertMessages(messages), nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Message is the resolver for the message field.
|
|
// Message is the resolver for the message field.
|
|
|
func (r *queryResolver) Message(ctx context.Context, id string) (*model.Message, error) {
|
|
func (r *queryResolver) Message(ctx context.Context, id string) (*model.Message, error) {
|
|
|
|
|
+ // Auth check
|
|
|
|
|
+ if !auth.IsAuthenticated(ctx) {
|
|
|
|
|
+ return nil, errors.New("unauthorized: authentication required")
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
messageID, err := toID(id)
|
|
messageID, err := toID(id)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("invalid message ID: %w", err)
|
|
return nil, fmt.Errorf("invalid message ID: %w", err)
|
|
@@ -1090,6 +1324,7 @@ func (r *queryResolver) Message(ctx context.Context, id string) (*model.Message,
|
|
|
return nil, fmt.Errorf("message not found: %w", err)
|
|
return nil, fmt.Errorf("message not found: %w", err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ logging.LogQuery(ctx, "MESSAGE", id)
|
|
|
return convertMessage(message), nil
|
|
return convertMessage(message), nil
|
|
|
}
|
|
}
|
|
|
|
|
|