package mail import ( "context" "github.com/ultisuite/ulti-backend/internal/api/query" "github.com/ultisuite/ulti-backend/internal/securityaudit" ) type UserLabelsList struct { Labels []map[string]any `json:"labels"` Pagination query.PaginationMeta `json:"pagination,omitempty"` } func (s *Service) ListUserLabels(ctx context.Context, externalID string, params query.ListParams) (UserLabelsList, error) { var total int64 err := s.db.QueryRow(ctx, ` SELECT COUNT(*) FROM mail_user_labels WHERE user_id = (SELECT id FROM users WHERE external_id = $1) `, externalID).Scan(&total) if err != nil { return UserLabelsList{}, err } rows, err := s.db.Query(ctx, ` SELECT id, name, color, created_at FROM mail_user_labels WHERE user_id = (SELECT id FROM users WHERE external_id = $1) ORDER BY name ASC LIMIT $2 OFFSET $3 `, externalID, params.Limit(), params.Offset()) if err != nil { return UserLabelsList{}, err } defer rows.Close() labels := make([]map[string]any, 0) for rows.Next() { var id, name, color string var createdAt any if err := rows.Scan(&id, &name, &color, &createdAt); err != nil { return UserLabelsList{}, err } labels = append(labels, map[string]any{ "id": id, "name": name, "color": color, "created_at": createdAt, }) } if err := rows.Err(); err != nil { return UserLabelsList{}, err } return UserLabelsList{ Labels: labels, Pagination: params.Meta(&total), }, nil } func (s *Service) CreateUserLabel(ctx context.Context, externalID string, req *createUserLabelRequest) (string, error) { var id string err := s.db.QueryRow(ctx, ` INSERT INTO mail_user_labels (user_id, name, color) VALUES ((SELECT id FROM users WHERE external_id = $1), $2, $3) RETURNING id `, externalID, req.Name, req.Color).Scan(&id) if err != nil { if isUniqueViolation(err) { return "", ErrDuplicateLabel } return "", err } return id, nil } func (s *Service) UpdateUserLabel(ctx context.Context, externalID, labelID string, req *updateUserLabelRequest) error { result, err := s.db.Exec(ctx, ` UPDATE mail_user_labels SET name = $1, color = $2 WHERE id = $3 AND user_id = (SELECT id FROM users WHERE external_id = $4) `, req.Name, req.Color, labelID, externalID) if err != nil { if isUniqueViolation(err) { return ErrDuplicateLabel } return err } if result.RowsAffected() == 0 { return ErrNotFound } return nil } func (s *Service) DeleteUserLabel(ctx context.Context, externalID, labelID string) error { result, err := s.db.Exec(ctx, ` DELETE FROM mail_user_labels WHERE id = $1 AND user_id = (SELECT id FROM users WHERE external_id = $2) `, labelID, externalID) if err != nil { return err } if result.RowsAffected() == 0 { return ErrNotFound } if s.audit != nil { s.audit.Log(ctx, externalID, securityaudit.ActionCriticalDeletion, map[string]any{ "target": "mail_user_label", "label_id": labelID, }) } return nil }