Skip to main content

Exportação de permissões — API

Exporta, em CSV, quem tem cada permissão numa unidade e por qual papel — um relatório de auditoria de acesso pronto para download, sem paginação (a unidade inteira sai numa só resposta).

Funcionamento​

  1. Confirma que o ator autenticado tem permission:read naquela unidade (ResolveIdentityEffectivePermissionService.resolveAuthorizedUnit); sem isso, nega com IDENTITY_PERMISSION_EXPORT_FORBIDDEN — um errorCode de negócio próprio, não o 403 genérico do guard, porque o filtro de escopo (kind: 'unit') por si só permitiria a chamada; a rejeição final é decidida no serviço.
  2. Busca toda atribuição de papel ativa naquela unidade (direta na unidade ou tenant-wide que alcança a unidade), agrupada por usuário.
  3. Para cada usuário e cada permissão do catálogo atribuível (opcionalmente filtrada por permission), verifica se algum papel atribuído a ele concede aquele bit. Se sim, gera uma linha com o(s) nome(s) de papel que concedem, e a origem (TENANT_WIDE se algum papel veio de um grant de tenant, UNIT_SCOPED caso contrário).
  4. Usuários inativos e atribuições expiradas são excluídos antes de montar as linhas — não entram no CSV mesmo que o registro exista no banco.
  5. Nomes de usuário são neutralizados contra injeção de fórmula de planilha: um valor que começa com =, +, -, @, tab ou retorno de carro é escapado antes de entrar no CSV (proteção confirmada em teste: "neutralizes spreadsheet formulas in user names").

Endpoints​

MétodoRotaDescrição
GET/v1/units/:unitId/users/permissions-exportExporta as permissões efetivas da unidade em CSV

Versão: v1

Swagger: identityPermissionExportExport · Rota (Dev): http://localhost:3000/v1/units/{unitId}/users/permissions-export

Permissões​

RotaGuardsPermissão exigida (escopo unit)
GET .../permissions-exportIdentityOAuthAccessTokenGuard, AuthorizationGuardpermission:read, e confirmação adicional no serviço (resolveAuthorizedUnit)

Headers​

HeaderObrigatórioDescrição
AuthorizationSimBearer <access_token>
Content-Type (resposta)—text/csv; charset=utf-8
Content-Disposition (resposta)—attachment; filename="user-permissions.csv"

Path parameters​

NomeTipoObrigatórioDescrição
unitIduuidSimUnidade a exportar

Query parameters​

NomeTipoObrigatórioDescrição
permissionstringNãoFiltra a exportação a uma única permissão; formato recurso:ação (@Matches(/^\S+:\S+$/))

Body​

Nenhum (rota GET).

Response​

200 — corpo text/csv (IdentityPermissionExport, header real do CSV):

csv
user_id,user_name,roles,permission,source
0197...,Ana Souza,read_only,exam:read,UNIT_SCOPED
0198...,Carlos Lima,manager,exam:read,TENANT_WIDE

O exemplo do @ApiOkResponse no Swagger mostra apenas permission,unit_id — está desatualizado em relação ao schema real montado por IdentityPermissionExport (ver "Divergências" abaixo); o header e as colunas acima são os que o código de fato escreve (CSV_HEADER em identity-permission-export.ts).

Mapa de campos​

Coluna do CSVTipoValores possíveisDescrição
user_iduuid—Identificador do usuário
user_namestring—Nome de exibição do usuário; neutralizado contra fórmula de planilha
rolesstring—Nome(s) de exibição do(s) papel(éis) que concedem a permissão, unidos por ; , em ordem alfabética
permissionstringcatálogo atribuívelPermissão concedida (recurso:ação)
sourcestringTENANT_WIDE, UNIT_SCOPEDSe a concessão vem de um grant de tenant ou só da unidade

Erros​

Classe de erroerrorCodeStatusQuando ocorre
(validação de query/UUID)BAD_REQUEST / INVALID_UUID400unitId inválido, permission fora do formato recurso:ação
UnauthenticatedErrorIDENTITY_INVALID_OAUTH_ACCESS_TOKEN401access token ausente/inválido/expirado/inativo
ForbiddenActionIDENTITY_PERMISSION_EXPORT_FORBIDDEN403ator sem permission:read efetivo naquela unidade (checagem de negócio, além do guard)

Regras de negócio​

IDRegraComportamento esperado
RN-01Exportação restrita ao escopo do atorprecisa de permission:read efetivo na unidade exportada; ausência gera IDENTITY_PERMISSION_EXPORT_FORBIDDEN, não 404
RN-02Usuários inativos não aparecemmesmo com atribuição ativa no banco, um usuário inativo é excluído da exportação
RN-03Atribuições expiradas não aparecemuma atribuição com expiresAt no passado não gera linha
RN-04Revogação reflete na próxima exportaçãouma atribuição revogada é removida do CSV imediatamente (confirmado em teste)
RN-05CSV neutraliza fórmula de planilha no nome do usuáriovalores começando com =, +, -, @, tab ou retorno de carro são escapados — mitigação de CSV injection
RN-06permission filtra sem mudar a autorizaçãopassar um nome de permissão só restringe as linhas retornadas; não amplia nem reduz a permissão exigida para chamar a rota

Compliance​

Órgão / normaExigênciaComo a rota atende
LGPDMinimização e segurança no tratamento de dado exportadoescopo restrito à unidade autorizada; neutralização de fórmula evita execução de conteúdo malicioso ao abrir o CSV numa planilha
HIPAA / ANVISARelatório de acesso auditávela exportação em si é a ferramenta de auditoria (quem pode o quê, por qual papel); não há evento de auditoria adicional para o ato de exportar confirmado no código (ver NFR)

Variáveis de ambiente​

Nenhuma variável de ambiente é consumida diretamente por esta rota.

Tempo médio de resposta​

A confirmar — responsável: time de Identity; data: 24/09/2026. Sem medição publicada — o cálculo percorre todas as atribuições e todo o catálogo atribuível por usuário, então tende a crescer com o tamanho da unidade.

Requisitos não funcionais​

RequisitoDefinição
IdempotênciaSim (leitura pura)
PaginaçãoNão — a unidade inteira é exportada numa só resposta
Rate limitNão identificado
CacheNão identificado
AuditoriaNão identificado evento de auditoria específico para o ato de exportar, neste levantamento

Divergências e lacunas confirmadas​

  • O exemplo do Swagger (ApiOkResponse) mostra apenas permission,unit_id como colunas do CSV, mas o modelo real (IdentityPermissionExport, a partir das linhas montadas no serviço) inclui usuário, papéis e origem — o exemplo do Swagger está desatualizado em relação ao schema real; divergência de documentação, não de comportamento.

Relacionado​