Skip to content

Commit

Permalink
feat: systematic check on rights (#1560)
Browse files Browse the repository at this point in the history
* feat: update KPIs

* feat: systematically check agent rights

* feat: add comments
  • Loading branch information
XavierJp authored Jan 20, 2025
1 parent 0634e80 commit 2bf493a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 12 deletions.
4 changes: 2 additions & 2 deletions app/api/auth/agent-connect/callback/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { proConnectAuthenticate } from '#clients/authentication/pro-connect/stra
import { HttpForbiddenError } from '#clients/exceptions';
import { isServicePublic } from '#models/core/types';
import { getUniteLegaleFromSlug } from '#models/core/unite-legale';
import { getAgent, IAgentInfo } from '#models/user/agent';
import { createAgent, IAgentInfo } from '#models/user/agent';
import { extractSirenFromSiret } from '#utils/helpers';
import { logFatalErrorInSentry } from '#utils/sentry';
import { getBaseUrl } from '#utils/server-side-helper/app/get-base-url';
Expand All @@ -19,7 +19,7 @@ import {
export const GET = withSession(async function callbackRoute(req) {
try {
const userInfo = await proConnectAuthenticate(req);
const agent = await getAgent(userInfo);
const agent = await createAgent(userInfo);

await verifyAgentHabilitation(agent);

Expand Down
17 changes: 15 additions & 2 deletions app/api/data-fetching/[...slug]/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { UseCase } from '#models/user/agent';
import { hasRights } from '#models/user/rights';
import { getVerifiedAgent, UseCase } from '#models/user/agent';
import { ApplicationRights, hasRights } from '#models/user/rights';
import { setAgentSession } from '#utils/session';
import withSession, { IReqWithSession } from '#utils/session/with-session';
import { APIRoutesHandlers } from '../routes-handlers';
import { APIRoutesScopes } from '../routes-scopes';
Expand All @@ -20,13 +21,25 @@ async function getRoute(request: IReqWithSession, context: IContext) {
const handler = APIRoutesHandlers[route];
const scope = APIRoutesScopes[route];
const session = request.session;

/**
* This only updates rights on ajax api calls.
*
* Therefore it is very efficient to downgrade agent rights but less effective to upgrade rights as an agent with few rights will not event trigger ajax calls on some pages.
*/
if (hasRights(session, ApplicationRights.isAgent) && session?.user?.email) {
const updatedAgent = await getVerifiedAgent(session.user);
await setAgentSession(updatedAgent, session);
}

if (!hasRights(session, scope)) {
throw new APIRouteError(
'User does not have the required scope for this API route',
{ route, slug },
403
);
}

const searchParams = Object.fromEntries(new URL(request.url).searchParams);

const validatedParams = {
Expand Down
15 changes: 8 additions & 7 deletions app/api/data-fetching/routes-scopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import { ApplicationRights } from '#models/user/rights';
import { APIRoutesPaths } from './routes-paths';

export const APIRoutesScopes: Record<APIRoutesPaths, ApplicationRights> = {
// full open data & RNE
[APIRoutesPaths.RneDirigeants]: ApplicationRights.opendata,
[APIRoutesPaths.Observations]: ApplicationRights.opendata,
[APIRoutesPaths.Association]: ApplicationRights.opendata,
[APIRoutesPaths.VerifyTva]: ApplicationRights.opendata,
[APIRoutesPaths.EoriValidation]: ApplicationRights.opendata,
// documents RNE - Open data but restricted to agents only
[APIRoutesPaths.EspaceAgentRneDocuments]: ApplicationRights.documentsRne,
// person
[APIRoutesPaths.EspaceAgentBeneficiaires]: ApplicationRights.beneficiaires,
[APIRoutesPaths.EspaceAgentDirigeantsProtected]:
Expand All @@ -16,13 +24,6 @@ export const APIRoutesScopes: Record<APIRoutesPaths, ApplicationRights> = {
[APIRoutesPaths.EspaceAgentQualibat]: ApplicationRights.protectedCertificats,
[APIRoutesPaths.EspaceAgentQualifelec]:
ApplicationRights.protectedCertificats,
// pseudo open data & RNE
[APIRoutesPaths.RneDirigeants]: ApplicationRights.opendata,
[APIRoutesPaths.Observations]: ApplicationRights.opendata,
[APIRoutesPaths.Association]: ApplicationRights.opendata,
[APIRoutesPaths.VerifyTva]: ApplicationRights.opendata,
[APIRoutesPaths.EspaceAgentRneDocuments]: ApplicationRights.documentsRne,
[APIRoutesPaths.EoriValidation]: ApplicationRights.opendata,
// BTP
[APIRoutesPaths.EspaceAgentTravauxPublics]: ApplicationRights.travauxPublics,
// fiscal & social
Expand Down
19 changes: 18 additions & 1 deletion models/user/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,24 @@ const getSiretOrFallbackOnIdpId = (siret: string, idpId: string) => {
return getSiretFromIdpTemporary(idpId);
};

export const getAgent = async (
/**
* Return a verified agent with actual scopes, hasHabilitation and user type
* @param agent
* @returns
*/
export const getVerifiedAgent = async (agent: IAgentInfo) => {
const { scopes, userType, hasHabilitation } = await getAgentScopes(
agent.email
);
return {
...agent,
scopes,
userType,
hasHabilitation,
};
};

export const createAgent = async (
userInfo: IProConnectUserInfo
): Promise<IAgentInfo> => {
const { scopes, userType, hasHabilitation } = await getAgentScopes(
Expand Down

0 comments on commit 2bf493a

Please sign in to comment.