@tmlmobilidade/controllers 20260706.931.16 → 20260706.1756.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,27 @@
1
1
  import { type FastifyReply, type FastifyRequest } from '@tmlmobilidade/fastify';
2
- import { type Agency } from '@tmlmobilidade/types';
2
+ import { type ActionsOf, type Agency, type Permission } from '@tmlmobilidade/types';
3
+ interface GetAllAgenciesQuery {
4
+ actions?: string | string[];
5
+ scope?: Permission['scope'];
6
+ }
3
7
  export declare class AgenciesSharedController {
4
8
  /**
5
9
  * Returns all Agencies sorted by ID.
6
10
  * @param request The request object
7
11
  * @param reply The reply object
8
12
  */
9
- static getAll(request: FastifyRequest, reply: FastifyReply<Agency[]>): Promise<void>;
13
+ static getAll(request: FastifyRequest<{
14
+ Querystring: GetAllAgenciesQuery;
15
+ }>, reply: FastifyReply<Agency[]>): Promise<never>;
10
16
  /**
11
17
  * Returns an Agency by ID.
12
18
  * @param request The request object
13
19
  * @param reply The reply object
14
20
  */
15
- static getById(request: FastifyRequest<{
21
+ static getById<S extends Permission['scope']>(request: FastifyRequest<{
16
22
  Params: {
17
23
  id: string;
18
24
  };
19
- }>, reply: FastifyReply<Agency>): Promise<void>;
25
+ }>, reply: FastifyReply<Agency>, scope: S, action: ActionsOf<S>): Promise<never>;
20
26
  }
27
+ export {};
@@ -2,6 +2,10 @@
2
2
  import { HTTP_STATUS, HttpException } from '@tmlmobilidade/consts';
3
3
  import { agencies } from '@tmlmobilidade/interfaces';
4
4
  import { Logger } from '@tmlmobilidade/logger';
5
+ import { PermissionCatalog } from '@tmlmobilidade/types';
6
+ function getAgencyIdsFromPermission(permission) {
7
+ return permission?.resources?.agency_ids ?? [];
8
+ }
5
9
  /* * */
6
10
  export class AgenciesSharedController {
7
11
  //
@@ -11,7 +15,32 @@ export class AgenciesSharedController {
11
15
  * @param reply The reply object
12
16
  */
13
17
  static async getAll(request, reply) {
14
- const allAgencies = await agencies.findMany({}, { sort: { _id: 1 } });
18
+ //
19
+ // A. Setup variables
20
+ const scope = request.query.scope;
21
+ const actions = (Array.isArray(request.query.actions) ? request.query.actions : request.query.actions?.split(','))?.filter(Boolean);
22
+ if (!scope || !actions?.length) {
23
+ throw new HttpException(HTTP_STATUS.BAD_REQUEST, 'Missing scope or actions query parameters');
24
+ }
25
+ //
26
+ // Detect which agency_ids the user has access to,
27
+ // based on their permissions. If none, return an empty array.
28
+ const permittedAgencyIds = actions.flatMap(action => getAgencyIdsFromPermission(PermissionCatalog.get(request.permissions, scope, action)));
29
+ if (!permittedAgencyIds.length) {
30
+ Logger.issue({
31
+ context: {
32
+ action: 'getAll',
33
+ feature: 'agencies',
34
+ request,
35
+ },
36
+ level: 'info',
37
+ messageOrError: 'No agency_ids found in permissions',
38
+ });
39
+ return reply.send({ data: [], error: null, statusCode: HTTP_STATUS.OK });
40
+ }
41
+ const allowAllAgencies = permittedAgencyIds.includes(PermissionCatalog.ALLOW_ALL_FLAG);
42
+ const queryFilters = allowAllAgencies ? {} : { _id: { $in: permittedAgencyIds } };
43
+ const allAgencies = await agencies.findMany(queryFilters, { sort: { _id: 1 } });
15
44
  reply.send({ data: allAgencies, error: null, statusCode: HTTP_STATUS.OK });
16
45
  }
17
46
  /**
@@ -19,8 +48,28 @@ export class AgenciesSharedController {
19
48
  * @param request The request object
20
49
  * @param reply The reply object
21
50
  */
22
- static async getById(request, reply) {
23
- const agencyData = await agencies.findById(request.params.id);
51
+ static async getById(request, reply, scope, action) {
52
+ //
53
+ // Detect which agency_ids the user has access to,
54
+ // based on their permissions. If none, return an empty array.
55
+ const agenciesPermission = PermissionCatalog.get(request.permissions, scope, action);
56
+ const permittedAgencyIds = getAgencyIdsFromPermission(agenciesPermission);
57
+ if (!permittedAgencyIds.length) {
58
+ Logger.issue({
59
+ context: {
60
+ action: 'getById',
61
+ feature: 'agencies',
62
+ request,
63
+ value: request.params.id,
64
+ },
65
+ level: 'info',
66
+ messageOrError: 'No agency_ids found in permissions',
67
+ });
68
+ return reply.send({ data: null, error: null, statusCode: HTTP_STATUS.OK });
69
+ }
70
+ const allowAllAgencies = permittedAgencyIds.includes(PermissionCatalog.ALLOW_ALL_FLAG);
71
+ const queryFilters = allowAllAgencies ? { _id: request.params.id } : { _id: { $eq: request.params.id, $in: permittedAgencyIds } };
72
+ const agencyData = await agencies.findOne(queryFilters);
24
73
  if (!agencyData) {
25
74
  const error = new HttpException(HTTP_STATUS.NOT_FOUND, 'Agency not found');
26
75
  Logger.issue({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/controllers",
3
- "version": "20260706.931.16",
3
+ "version": "20260706.1756.42",
4
4
  "author": {
5
5
  "email": "iso@tmlmobilidade.pt",
6
6
  "name": "TML-ISO"