Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
package support
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/descrybe/descrybe-v2/apps/api/internal/auth"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
// ListAgents returns support_staff users and optionally full-admin staff.
|
||||
func (s *Service) ListAgents(ctx context.Context, includePlatformAdmins bool, limit, offset int) ([]SupportAgent, int64, error) {
|
||||
limit, offset = clampListBounds(limit, offset)
|
||||
where := `(staff_role = 'support_staff'`
|
||||
if includePlatformAdmins {
|
||||
where += ` OR staff_role IN ('admin','developer') OR (is_platform_admin = true AND (staff_role IS NULL OR staff_role = ''))`
|
||||
}
|
||||
where += `) AND is_active = true`
|
||||
|
||||
var total int64
|
||||
if err := s.Pool.QueryRow(ctx, `SELECT count(*) FROM users WHERE `+where).Scan(&total); err != nil {
|
||||
if isUndefinedColumn(err) {
|
||||
return []SupportAgent{}, 0, nil
|
||||
}
|
||||
return nil, 0, err
|
||||
}
|
||||
q := fmt.Sprintf(`
|
||||
SELECT id, email, COALESCE(name, ''), is_platform_admin, COALESCE(staff_role, ''), is_active
|
||||
FROM users
|
||||
WHERE %s
|
||||
ORDER BY email ASC
|
||||
LIMIT $1 OFFSET $2`, where)
|
||||
rows, err := s.Pool.Query(ctx, q, limit, offset)
|
||||
if err != nil {
|
||||
if isUndefinedColumn(err) {
|
||||
return []SupportAgent{}, 0, nil
|
||||
}
|
||||
return nil, 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
out := make([]SupportAgent, 0, limit)
|
||||
for rows.Next() {
|
||||
var a SupportAgent
|
||||
var role string
|
||||
if err := rows.Scan(&a.ID, &a.Email, &a.Name, &a.IsPlatformAdmin, &role, &a.IsActive); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
a.StaffRole = role
|
||||
access := auth.ResolveStaffAccess(a.IsPlatformAdmin, role)
|
||||
a.IsSupportAgent = access.SupportDesk
|
||||
a.IsPlatformAdmin = access.FullAdmin
|
||||
out = append(out, a)
|
||||
}
|
||||
return out, total, rows.Err()
|
||||
}
|
||||
|
||||
// SetSupportAgent grants or revokes staff_role=support_staff (does not grant full admin).
|
||||
func (s *Service) SetSupportAgent(ctx context.Context, userID uuid.UUID, enable bool) (SupportAgent, error) {
|
||||
var email, name string
|
||||
var isAdmin, isActive bool
|
||||
var staffRole *string
|
||||
err := s.Pool.QueryRow(ctx, `
|
||||
SELECT email, COALESCE(name, ''), is_platform_admin, staff_role, is_active
|
||||
FROM users WHERE id = $1`, userID,
|
||||
).Scan(&email, &name, &isAdmin, &staffRole, &isActive)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return SupportAgent{}, ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return SupportAgent{}, err
|
||||
}
|
||||
role := ""
|
||||
if staffRole != nil {
|
||||
role = *staffRole
|
||||
}
|
||||
access := auth.ResolveStaffAccess(isAdmin, role)
|
||||
if enable {
|
||||
if access.FullAdmin {
|
||||
// Already has desk via admin/developer — leave role unchanged.
|
||||
} else {
|
||||
_, err = s.Pool.Exec(ctx, `
|
||||
UPDATE users
|
||||
SET staff_role = $2, is_platform_admin = true, updated_at = now()
|
||||
WHERE id = $1`, userID, auth.StaffRoleSupportStaff)
|
||||
if err != nil {
|
||||
return SupportAgent{}, err
|
||||
}
|
||||
role = auth.StaffRoleSupportStaff
|
||||
isAdmin = true
|
||||
}
|
||||
} else {
|
||||
if role == auth.StaffRoleSupportStaff {
|
||||
_, err = s.Pool.Exec(ctx, `
|
||||
UPDATE users
|
||||
SET staff_role = NULL, is_platform_admin = false, updated_at = now()
|
||||
WHERE id = $1`, userID)
|
||||
if err != nil {
|
||||
return SupportAgent{}, err
|
||||
}
|
||||
role = ""
|
||||
isAdmin = false
|
||||
}
|
||||
// Do not demote admin/developer via this endpoint.
|
||||
}
|
||||
access = auth.ResolveStaffAccess(isAdmin, role)
|
||||
return SupportAgent{
|
||||
ID: userID,
|
||||
Email: email,
|
||||
Name: name,
|
||||
IsSupportAgent: access.SupportDesk,
|
||||
IsPlatformAdmin: access.FullAdmin,
|
||||
StaffRole: role,
|
||||
IsActive: isActive,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func isUndefinedColumn(err error) bool {
|
||||
var pgErr *pgconn.PgError
|
||||
if errors.As(err, &pgErr) {
|
||||
return pgErr.Code == "42703"
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user