@ftisindia/create-app 0.1.2 → 0.1.4

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.
Files changed (109) hide show
  1. package/README.md +65 -0
  2. package/package.json +1 -1
  3. package/template/README.md +65 -1
  4. package/template/_package.json +0 -2
  5. package/template/docs/API_REFERENCE.md +13 -0
  6. package/template/docs/OAUTH.md +7 -3
  7. package/template/scripts/gen-module.mjs +2 -0
  8. package/template/src/app.module.ts +16 -22
  9. package/template/src/common/dto/error-response.dto.ts +3 -3
  10. package/template/src/common/dto/membership-response.dto.ts +26 -14
  11. package/template/src/common/dto/mutation-response.dto.ts +1 -1
  12. package/template/src/common/dto/pagination-query.dto.ts +37 -0
  13. package/template/src/common/dto/role-summary.dto.ts +5 -5
  14. package/template/src/common/dto/user-summary.dto.ts +6 -6
  15. package/template/src/common/filters/http-exception.filter.ts +9 -19
  16. package/template/src/common/swagger/api-error-responses.ts +12 -12
  17. package/template/src/config/app.config.ts +3 -3
  18. package/template/src/config/auth.config.ts +3 -3
  19. package/template/src/config/database.config.ts +3 -3
  20. package/template/src/config/env.validation.ts +58 -40
  21. package/template/src/config/index.ts +5 -5
  22. package/template/src/config/rbac.config.ts +3 -3
  23. package/template/src/database/prisma/prisma-transaction.ts +1 -1
  24. package/template/src/database/prisma/prisma.module.ts +2 -2
  25. package/template/src/database/prisma/prisma.service.ts +3 -6
  26. package/template/src/main.ts +11 -11
  27. package/template/src/modules/access-control/access-control.module.ts +9 -9
  28. package/template/src/modules/access-control/application/role-permission-policy.ts +71 -0
  29. package/template/src/modules/access-control/application/route-registry.validator.ts +34 -63
  30. package/template/src/modules/access-control/application/services/ability.factory.ts +5 -9
  31. package/template/src/modules/access-control/application/services/access-control.service.ts +78 -85
  32. package/template/src/modules/access-control/application/services/permission.guard.ts +16 -21
  33. package/template/src/modules/access-control/application/services/rbac-cache.service.ts +7 -9
  34. package/template/src/modules/access-control/dto/access-control-response.dto.ts +32 -20
  35. package/template/src/modules/access-control/dto/create-role.dto.ts +6 -6
  36. package/template/src/modules/access-control/dto/update-role-permissions.dto.ts +3 -10
  37. package/template/src/modules/access-control/dto/update-role.dto.ts +6 -6
  38. package/template/src/modules/access-control/presentation/access-control.controller.ts +69 -74
  39. package/template/src/modules/access-control/presentation/permissions.decorator.ts +3 -3
  40. package/template/src/modules/access-control/presentation/public.decorator.ts +2 -2
  41. package/template/src/modules/access-control/types/permission-key.ts +19 -19
  42. package/template/src/modules/access-control/types/route-permission-registry.ts +76 -76
  43. package/template/src/modules/audit/application/services/audit.service.ts +7 -7
  44. package/template/src/modules/audit/audit.module.ts +4 -4
  45. package/template/src/modules/audit/dto/audit-response.dto.ts +18 -18
  46. package/template/src/modules/audit/dto/list-audit-logs-query.dto.ts +14 -14
  47. package/template/src/modules/audit/presentation/audit.controller.ts +17 -23
  48. package/template/src/modules/auth/application/services/auth.service.ts +147 -110
  49. package/template/src/modules/auth/application/services/password.service.ts +2 -2
  50. package/template/src/modules/auth/application/services/token.service.ts +20 -21
  51. package/template/src/modules/auth/auth.module.ts +20 -47
  52. package/template/src/modules/auth/dto/auth-response.dto.ts +9 -10
  53. package/template/src/modules/auth/dto/login.dto.ts +4 -4
  54. package/template/src/modules/auth/dto/logout.dto.ts +1 -1
  55. package/template/src/modules/auth/dto/oauth-exchange.dto.ts +4 -5
  56. package/template/src/modules/auth/dto/refresh-token.dto.ts +4 -5
  57. package/template/src/modules/auth/dto/signup.dto.ts +5 -11
  58. package/template/src/modules/auth/infrastructure/passport/google-auth.guard.ts +6 -14
  59. package/template/src/modules/auth/infrastructure/passport/google-oauth-state.store.ts +98 -0
  60. package/template/src/modules/auth/infrastructure/passport/google.strategy.ts +21 -30
  61. package/template/src/modules/auth/infrastructure/passport/jwt-auth.guard.ts +3 -3
  62. package/template/src/modules/auth/infrastructure/passport/jwt.strategy.ts +11 -11
  63. package/template/src/modules/auth/presentation/auth.controller.ts +45 -45
  64. package/template/src/modules/auth/presentation/current-user.decorator.ts +3 -5
  65. package/template/src/modules/auth/presentation/google-oauth-exception.filter.ts +5 -10
  66. package/template/src/modules/health/dto/health-response.dto.ts +5 -5
  67. package/template/src/modules/health/health.module.ts +2 -2
  68. package/template/src/modules/health/presentation/health.controller.ts +13 -13
  69. package/template/src/modules/invitations/application/services/invitations.service.ts +127 -176
  70. package/template/src/modules/invitations/dto/accept-invitation.dto.ts +6 -7
  71. package/template/src/modules/invitations/dto/create-invitation.dto.ts +14 -15
  72. package/template/src/modules/invitations/dto/invitation-response.dto.ts +37 -29
  73. package/template/src/modules/invitations/dto/invitation-token.dto.ts +4 -4
  74. package/template/src/modules/invitations/invitations.module.ts +5 -5
  75. package/template/src/modules/invitations/presentation/invitations.controller.ts +61 -63
  76. package/template/src/modules/memberships/application/services/memberships.service.ts +70 -84
  77. package/template/src/modules/memberships/dto/transfer-owner.dto.ts +4 -4
  78. package/template/src/modules/memberships/dto/update-billing-contact.dto.ts +2 -2
  79. package/template/src/modules/memberships/dto/update-membership-owner.dto.ts +2 -2
  80. package/template/src/modules/memberships/dto/update-membership-role.dto.ts +4 -4
  81. package/template/src/modules/memberships/dto/update-membership-status.dto.ts +3 -3
  82. package/template/src/modules/memberships/memberships.module.ts +4 -4
  83. package/template/src/modules/memberships/presentation/memberships.controller.ts +83 -99
  84. package/template/src/modules/organisations/application/services/organisations.service.ts +21 -23
  85. package/template/src/modules/organisations/dto/create-organisation.dto.ts +6 -13
  86. package/template/src/modules/organisations/dto/organisation-response.dto.ts +14 -14
  87. package/template/src/modules/organisations/infrastructure/repositories/organisations.repository.ts +4 -7
  88. package/template/src/modules/organisations/organisations.module.ts +5 -5
  89. package/template/src/modules/organisations/presentation/organisations.controller.ts +14 -23
  90. package/template/src/modules/organisations/types/default-organisation-data.ts +3 -9
  91. package/template/src/modules/request-context/application/services/request-context.service.ts +15 -7
  92. package/template/src/modules/request-context/presentation/org-scope.guard.ts +4 -9
  93. package/template/src/modules/request-context/presentation/request-context.interceptor.ts +4 -9
  94. package/template/src/modules/request-context/presentation/request-context.middleware.ts +7 -8
  95. package/template/src/modules/request-context/request-context.module.ts +7 -7
  96. package/template/src/modules/request-context/types/request-context.ts +2 -2
  97. package/template/src/modules/sample/application/services/sample.service.ts +10 -8
  98. package/template/src/modules/sample/dto/sample-echo.dto.ts +3 -3
  99. package/template/src/modules/sample/dto/sample-response.dto.ts +12 -12
  100. package/template/src/modules/sample/presentation/sample.controller.ts +25 -42
  101. package/template/src/modules/sample/sample.module.ts +4 -4
  102. package/template/src/modules/settings/application/services/settings.service.ts +15 -27
  103. package/template/src/modules/settings/dto/setting-response.dto.ts +9 -9
  104. package/template/src/modules/settings/dto/update-setting.dto.ts +5 -5
  105. package/template/src/modules/settings/presentation/settings.controller.ts +29 -35
  106. package/template/src/modules/settings/settings.module.ts +5 -5
  107. package/template/src/modules/settings/types/setting-definitions.ts +49 -33
  108. package/template/test/auth-refresh.spec.ts +90 -0
  109. package/template/test/role-permission-policy.spec.ts +94 -0
@@ -7,8 +7,9 @@ import {
7
7
  Patch,
8
8
  Post,
9
9
  Put,
10
+ Query,
10
11
  UseGuards,
11
- } from "@nestjs/common";
12
+ } from '@nestjs/common';
12
13
  import {
13
14
  ApiBearerAuth,
14
15
  ApiCreatedResponse,
@@ -16,142 +17,136 @@ import {
16
17
  ApiOperation,
17
18
  ApiParam,
18
19
  ApiTags,
19
- } from "@nestjs/swagger";
20
- import { DeletedResponseDto } from "../../../common/dto/mutation-response.dto";
21
- import { ApiProtectedErrorResponses } from "../../../common/swagger/api-error-responses";
22
- import { JwtAuthGuard } from "../../auth/infrastructure/passport/jwt-auth.guard";
23
- import { CurrentUser } from "../../auth/presentation/current-user.decorator";
24
- import { AuthenticatedUser } from "../../auth/types/authenticated-user";
25
- import { OrgScopeGuard } from "../../request-context/presentation/org-scope.guard";
26
- import { AccessControlService } from "../application/services/access-control.service";
27
- import { PermissionGuard } from "../application/services/permission.guard";
20
+ } from '@nestjs/swagger';
21
+ import { DeletedResponseDto } from '../../../common/dto/mutation-response.dto';
22
+ import { PaginationQueryDto } from '../../../common/dto/pagination-query.dto';
23
+ import { ApiProtectedErrorResponses } from '../../../common/swagger/api-error-responses';
24
+ import { JwtAuthGuard } from '../../auth/infrastructure/passport/jwt-auth.guard';
25
+ import { CurrentUser } from '../../auth/presentation/current-user.decorator';
26
+ import { AuthenticatedUser } from '../../auth/types/authenticated-user';
27
+ import { OrgScopeGuard } from '../../request-context/presentation/org-scope.guard';
28
+ import { AccessControlService } from '../application/services/access-control.service';
29
+ import { PermissionGuard } from '../application/services/permission.guard';
28
30
  import {
29
31
  PermissionResponseDto,
32
+ RoleListResponseDto,
30
33
  RoleResponseDto,
31
34
  RoutePermissionResponseDto,
32
- } from "../dto/access-control-response.dto";
33
- import { CreateRoleDto } from "../dto/create-role.dto";
34
- import { UpdateRolePermissionsDto } from "../dto/update-role-permissions.dto";
35
- import { UpdateRoleDto } from "../dto/update-role.dto";
36
- import { RequirePermissions } from "./permissions.decorator";
35
+ } from '../dto/access-control-response.dto';
36
+ import { CreateRoleDto } from '../dto/create-role.dto';
37
+ import { UpdateRolePermissionsDto } from '../dto/update-role-permissions.dto';
38
+ import { UpdateRoleDto } from '../dto/update-role.dto';
39
+ import { RequirePermissions } from './permissions.decorator';
37
40
 
38
- @ApiTags("Access control")
41
+ @ApiTags('Access control')
39
42
  @ApiBearerAuth()
40
- @ApiParam({ name: "orgId", description: "Organisation ID.", format: "uuid" })
43
+ @ApiParam({ name: 'orgId', description: 'Organisation ID.', format: 'uuid' })
41
44
  @ApiProtectedErrorResponses(404, 409)
42
- @Controller("organisations/:orgId/access-control")
45
+ @Controller('organisations/:orgId/access-control')
43
46
  @UseGuards(JwtAuthGuard, OrgScopeGuard, PermissionGuard)
44
47
  export class AccessControlController {
45
48
  constructor(private readonly accessControlService: AccessControlService) {}
46
49
 
47
- @Get("permissions")
48
- @RequirePermissions("roles.read")
49
- @ApiOperation({ summary: "List the seeded permission catalogue." })
50
+ @Get('permissions')
51
+ @RequirePermissions('roles.read')
52
+ @ApiOperation({ summary: 'List the seeded permission catalogue.' })
50
53
  @ApiOkResponse({
51
- description: "Available permissions.",
54
+ description: 'Available permissions.',
52
55
  type: [PermissionResponseDto],
53
56
  })
54
57
  listPermissions() {
55
58
  return this.accessControlService.listPermissions();
56
59
  }
57
60
 
58
- @Get("route-permissions")
59
- @RequirePermissions("roles.read")
61
+ @Get('route-permissions')
62
+ @RequirePermissions('roles.read')
60
63
  @ApiOperation({
61
- summary: "List permission requirements for protected routes.",
64
+ summary: 'List permission requirements for protected routes.',
62
65
  })
63
66
  @ApiOkResponse({
64
- description: "Protected route permission registry.",
67
+ description: 'Protected route permission registry.',
65
68
  type: [RoutePermissionResponseDto],
66
69
  })
67
70
  listRoutePermissions() {
68
71
  return this.accessControlService.listRoutePermissions();
69
72
  }
70
73
 
71
- @Get("roles")
72
- @RequirePermissions("roles.read")
73
- @ApiOperation({ summary: "List organisation roles." })
74
+ @Get('roles')
75
+ @RequirePermissions('roles.read')
76
+ @ApiOperation({ summary: 'List organisation roles.' })
74
77
  @ApiOkResponse({
75
- description: "Organisation roles.",
76
- type: [RoleResponseDto],
78
+ description: 'Organisation roles.',
79
+ type: RoleListResponseDto,
77
80
  })
78
- listRoles(@Param("orgId") orgId: string) {
79
- return this.accessControlService.listRoles(orgId);
81
+ listRoles(@Param('orgId') orgId: string, @Query() query: PaginationQueryDto) {
82
+ return this.accessControlService.listRoles(orgId, query);
80
83
  }
81
84
 
82
- @Post("roles")
83
- @RequirePermissions("roles.manage")
84
- @ApiOperation({ summary: "Create an organisation role." })
85
- @ApiCreatedResponse({ description: "Role created.", type: RoleResponseDto })
85
+ @Post('roles')
86
+ @RequirePermissions('roles.manage')
87
+ @ApiOperation({ summary: 'Create an organisation role.' })
88
+ @ApiCreatedResponse({ description: 'Role created.', type: RoleResponseDto })
86
89
  createRole(
87
90
  @CurrentUser() user: AuthenticatedUser,
88
- @Param("orgId") orgId: string,
91
+ @Param('orgId') orgId: string,
89
92
  @Body() dto: CreateRoleDto,
90
93
  ) {
91
94
  return this.accessControlService.createRole(user, orgId, dto);
92
95
  }
93
96
 
94
- @Patch("roles/:roleId")
95
- @RequirePermissions("roles.manage")
96
- @ApiParam({ name: "roleId", description: "Role ID.", format: "uuid" })
97
- @ApiOperation({ summary: "Update role name or description." })
98
- @ApiOkResponse({ description: "Role updated.", type: RoleResponseDto })
97
+ @Patch('roles/:roleId')
98
+ @RequirePermissions('roles.manage')
99
+ @ApiParam({ name: 'roleId', description: 'Role ID.', format: 'uuid' })
100
+ @ApiOperation({ summary: 'Update role name or description.' })
101
+ @ApiOkResponse({ description: 'Role updated.', type: RoleResponseDto })
99
102
  updateRole(
100
103
  @CurrentUser() user: AuthenticatedUser,
101
- @Param("orgId") orgId: string,
102
- @Param("roleId") roleId: string,
104
+ @Param('orgId') orgId: string,
105
+ @Param('roleId') roleId: string,
103
106
  @Body() dto: UpdateRoleDto,
104
107
  ) {
105
108
  return this.accessControlService.updateRole(user, orgId, roleId, dto);
106
109
  }
107
110
 
108
- @Delete("roles/:roleId")
109
- @RequirePermissions("roles.manage")
110
- @ApiParam({ name: "roleId", description: "Role ID.", format: "uuid" })
111
- @ApiOperation({ summary: "Delete an unused non-system role." })
112
- @ApiOkResponse({ description: "Role deleted.", type: DeletedResponseDto })
111
+ @Delete('roles/:roleId')
112
+ @RequirePermissions('roles.manage')
113
+ @ApiParam({ name: 'roleId', description: 'Role ID.', format: 'uuid' })
114
+ @ApiOperation({ summary: 'Delete an unused non-system role.' })
115
+ @ApiOkResponse({ description: 'Role deleted.', type: DeletedResponseDto })
113
116
  deleteRole(
114
117
  @CurrentUser() user: AuthenticatedUser,
115
- @Param("orgId") orgId: string,
116
- @Param("roleId") roleId: string,
118
+ @Param('orgId') orgId: string,
119
+ @Param('roleId') roleId: string,
117
120
  ) {
118
121
  return this.accessControlService.deleteRole(user, orgId, roleId);
119
122
  }
120
123
 
121
- @Get("roles/:roleId/permissions")
122
- @RequirePermissions("roles.read")
123
- @ApiParam({ name: "roleId", description: "Role ID.", format: "uuid" })
124
- @ApiOperation({ summary: "Return role permissions." })
124
+ @Get('roles/:roleId/permissions')
125
+ @RequirePermissions('roles.read')
126
+ @ApiParam({ name: 'roleId', description: 'Role ID.', format: 'uuid' })
127
+ @ApiOperation({ summary: 'Return role permissions.' })
125
128
  @ApiOkResponse({
126
- description: "Role with assigned permissions.",
129
+ description: 'Role with assigned permissions.',
127
130
  type: RoleResponseDto,
128
131
  })
129
- listRolePermissions(
130
- @Param("orgId") orgId: string,
131
- @Param("roleId") roleId: string,
132
- ) {
132
+ listRolePermissions(@Param('orgId') orgId: string, @Param('roleId') roleId: string) {
133
133
  return this.accessControlService.listRolePermissions(orgId, roleId);
134
134
  }
135
135
 
136
- @Put("roles/:roleId/permissions")
137
- @RequirePermissions("permissions.assign")
138
- @ApiParam({ name: "roleId", description: "Role ID.", format: "uuid" })
139
- @ApiOperation({ summary: "Replace all permissions assigned to a role." })
136
+ @Put('roles/:roleId/permissions')
137
+ @RequirePermissions('permissions.assign')
138
+ @ApiParam({ name: 'roleId', description: 'Role ID.', format: 'uuid' })
139
+ @ApiOperation({ summary: 'Replace all permissions assigned to a role.' })
140
140
  @ApiOkResponse({
141
- description: "Role with replacement permissions.",
141
+ description: 'Role with replacement permissions.',
142
142
  type: RoleResponseDto,
143
143
  })
144
144
  replaceRolePermissions(
145
145
  @CurrentUser() user: AuthenticatedUser,
146
- @Param("orgId") orgId: string,
147
- @Param("roleId") roleId: string,
146
+ @Param('orgId') orgId: string,
147
+ @Param('roleId') roleId: string,
148
148
  @Body() dto: UpdateRolePermissionsDto,
149
149
  ) {
150
- return this.accessControlService.replaceRolePermissions(
151
- user,
152
- orgId,
153
- roleId,
154
- dto,
155
- );
150
+ return this.accessControlService.replaceRolePermissions(user, orgId, roleId, dto);
156
151
  }
157
152
  }
@@ -1,7 +1,7 @@
1
- import { SetMetadata } from "@nestjs/common";
2
- import { PermissionKey } from "../types/permission-key";
1
+ import { SetMetadata } from '@nestjs/common';
2
+ import { PermissionKey } from '../types/permission-key';
3
3
 
4
- export const REQUIRED_PERMISSIONS_KEY = "requiredPermissions";
4
+ export const REQUIRED_PERMISSIONS_KEY = 'requiredPermissions';
5
5
 
6
6
  export function RequirePermissions(...permissions: PermissionKey[]) {
7
7
  return SetMetadata(REQUIRED_PERMISSIONS_KEY, permissions);
@@ -1,6 +1,6 @@
1
- import { SetMetadata } from "@nestjs/common";
1
+ import { SetMetadata } from '@nestjs/common';
2
2
 
3
- export const IS_PUBLIC_KEY = "isPublic";
3
+ export const IS_PUBLIC_KEY = 'isPublic';
4
4
 
5
5
  export function Public() {
6
6
  return SetMetadata(IS_PUBLIC_KEY, true);
@@ -1,22 +1,22 @@
1
1
  export const permissionKeys = [
2
- "users.read",
3
- "users.create",
4
- "users.update",
5
- "users.suspend",
6
- "organisations.read",
7
- "organisations.update",
8
- "memberships.read",
9
- "memberships.invite",
10
- "memberships.revoke",
11
- "roles.read",
12
- "roles.manage",
13
- "permissions.assign",
14
- "billing.read",
15
- "billing.manage",
16
- "settings.read",
17
- "settings.update",
18
- "audit.read",
19
- "platform.admin",
2
+ 'users.read',
3
+ 'users.create',
4
+ 'users.update',
5
+ 'users.suspend',
6
+ 'organisations.read',
7
+ 'organisations.update',
8
+ 'memberships.read',
9
+ 'memberships.invite',
10
+ 'memberships.revoke',
11
+ 'roles.read',
12
+ 'roles.manage',
13
+ 'permissions.assign',
14
+ 'billing.read',
15
+ 'billing.manage',
16
+ 'settings.read',
17
+ 'settings.update',
18
+ 'audit.read',
19
+ 'platform.admin',
20
20
  ] as const;
21
21
 
22
22
  export type PermissionKey = (typeof permissionKeys)[number];
@@ -28,7 +28,7 @@ export type RoutePermissionEntry = {
28
28
  };
29
29
 
30
30
  export function permissionKeyToRule(key: string) {
31
- const [subject, action] = key.split(".", 2);
31
+ const [subject, action] = key.split('.', 2);
32
32
  if (!subject || !action) {
33
33
  throw new Error(`Invalid permission key: ${key}`);
34
34
  }
@@ -1,129 +1,129 @@
1
- import { RoutePermissionEntry } from "./permission-key";
1
+ import { RoutePermissionEntry } from './permission-key';
2
2
 
3
3
  export const routePermissionRegistry: RoutePermissionEntry[] = [
4
4
  {
5
- method: "GET",
6
- path: "/organisations/:orgId/memberships/me",
7
- permissions: ["memberships.read"],
5
+ method: 'GET',
6
+ path: '/organisations/:orgId/memberships/me',
7
+ permissions: ['memberships.read'],
8
8
  },
9
9
  {
10
- method: "GET",
11
- path: "/organisations/:orgId/memberships",
12
- permissions: ["memberships.read"],
10
+ method: 'GET',
11
+ path: '/organisations/:orgId/memberships',
12
+ permissions: ['memberships.read'],
13
13
  },
14
14
  {
15
- method: "PATCH",
16
- path: "/organisations/:orgId/memberships/:membershipId/status",
17
- permissions: ["memberships.revoke"],
15
+ method: 'PATCH',
16
+ path: '/organisations/:orgId/memberships/:membershipId/status',
17
+ permissions: ['memberships.revoke'],
18
18
  },
19
19
  {
20
- method: "PATCH",
21
- path: "/organisations/:orgId/memberships/:membershipId/role",
22
- permissions: ["roles.manage"],
20
+ method: 'PATCH',
21
+ path: '/organisations/:orgId/memberships/:membershipId/role',
22
+ permissions: ['roles.manage'],
23
23
  },
24
24
  {
25
- method: "PATCH",
26
- path: "/organisations/:orgId/memberships/:membershipId/owner",
27
- permissions: ["roles.manage"],
25
+ method: 'PATCH',
26
+ path: '/organisations/:orgId/memberships/:membershipId/owner',
27
+ permissions: ['roles.manage'],
28
28
  },
29
29
  {
30
- method: "PATCH",
31
- path: "/organisations/:orgId/memberships/:membershipId/billing-contact",
32
- permissions: ["billing.manage"],
30
+ method: 'PATCH',
31
+ path: '/organisations/:orgId/memberships/:membershipId/billing-contact',
32
+ permissions: ['billing.manage'],
33
33
  },
34
34
  {
35
- method: "POST",
36
- path: "/organisations/:orgId/memberships/transfer-owner",
37
- permissions: ["roles.manage"],
35
+ method: 'POST',
36
+ path: '/organisations/:orgId/memberships/transfer-owner',
37
+ permissions: ['roles.manage'],
38
38
  },
39
39
  {
40
- method: "POST",
41
- path: "/organisations/:orgId/invitations",
42
- permissions: ["memberships.invite"],
40
+ method: 'POST',
41
+ path: '/organisations/:orgId/invitations',
42
+ permissions: ['memberships.invite'],
43
43
  },
44
44
  {
45
- method: "GET",
46
- path: "/organisations/:orgId/invitations",
47
- permissions: ["memberships.read"],
45
+ method: 'GET',
46
+ path: '/organisations/:orgId/invitations',
47
+ permissions: ['memberships.read'],
48
48
  },
49
49
  {
50
- method: "POST",
51
- path: "/organisations/:orgId/invitations/:invitationId/revoke",
52
- permissions: ["memberships.revoke"],
50
+ method: 'POST',
51
+ path: '/organisations/:orgId/invitations/:invitationId/revoke',
52
+ permissions: ['memberships.revoke'],
53
53
  },
54
54
  {
55
- method: "POST",
56
- path: "/organisations/:orgId/invitations/:invitationId/resend",
57
- permissions: ["memberships.invite"],
55
+ method: 'POST',
56
+ path: '/organisations/:orgId/invitations/:invitationId/resend',
57
+ permissions: ['memberships.invite'],
58
58
  },
59
59
  {
60
- method: "GET",
61
- path: "/organisations/:orgId/access-control/permissions",
62
- permissions: ["roles.read"],
60
+ method: 'GET',
61
+ path: '/organisations/:orgId/access-control/permissions',
62
+ permissions: ['roles.read'],
63
63
  },
64
64
  {
65
- method: "GET",
66
- path: "/organisations/:orgId/access-control/roles",
67
- permissions: ["roles.read"],
65
+ method: 'GET',
66
+ path: '/organisations/:orgId/access-control/roles',
67
+ permissions: ['roles.read'],
68
68
  },
69
69
  {
70
- method: "POST",
71
- path: "/organisations/:orgId/access-control/roles",
72
- permissions: ["roles.manage"],
70
+ method: 'POST',
71
+ path: '/organisations/:orgId/access-control/roles',
72
+ permissions: ['roles.manage'],
73
73
  },
74
74
  {
75
- method: "PATCH",
76
- path: "/organisations/:orgId/access-control/roles/:roleId",
77
- permissions: ["roles.manage"],
75
+ method: 'PATCH',
76
+ path: '/organisations/:orgId/access-control/roles/:roleId',
77
+ permissions: ['roles.manage'],
78
78
  },
79
79
  {
80
- method: "DELETE",
81
- path: "/organisations/:orgId/access-control/roles/:roleId",
82
- permissions: ["roles.manage"],
80
+ method: 'DELETE',
81
+ path: '/organisations/:orgId/access-control/roles/:roleId',
82
+ permissions: ['roles.manage'],
83
83
  },
84
84
  {
85
- method: "GET",
86
- path: "/organisations/:orgId/access-control/roles/:roleId/permissions",
87
- permissions: ["roles.read"],
85
+ method: 'GET',
86
+ path: '/organisations/:orgId/access-control/roles/:roleId/permissions',
87
+ permissions: ['roles.read'],
88
88
  },
89
89
  {
90
- method: "PUT",
91
- path: "/organisations/:orgId/access-control/roles/:roleId/permissions",
92
- permissions: ["permissions.assign"],
90
+ method: 'PUT',
91
+ path: '/organisations/:orgId/access-control/roles/:roleId/permissions',
92
+ permissions: ['permissions.assign'],
93
93
  },
94
94
  {
95
- method: "GET",
96
- path: "/organisations/:orgId/access-control/route-permissions",
97
- permissions: ["roles.read"],
95
+ method: 'GET',
96
+ path: '/organisations/:orgId/access-control/route-permissions',
97
+ permissions: ['roles.read'],
98
98
  },
99
99
  {
100
- method: "GET",
101
- path: "/organisations/:orgId/audit",
102
- permissions: ["audit.read"],
100
+ method: 'GET',
101
+ path: '/organisations/:orgId/audit',
102
+ permissions: ['audit.read'],
103
103
  },
104
104
  {
105
- method: "GET",
106
- path: "/organisations/:orgId/settings",
107
- permissions: ["settings.read"],
105
+ method: 'GET',
106
+ path: '/organisations/:orgId/settings',
107
+ permissions: ['settings.read'],
108
108
  },
109
109
  {
110
- method: "GET",
111
- path: "/organisations/:orgId/settings/:key",
112
- permissions: ["settings.read"],
110
+ method: 'GET',
111
+ path: '/organisations/:orgId/settings/:key',
112
+ permissions: ['settings.read'],
113
113
  },
114
114
  {
115
- method: "PATCH",
116
- path: "/organisations/:orgId/settings",
117
- permissions: ["settings.update"],
115
+ method: 'PATCH',
116
+ path: '/organisations/:orgId/settings',
117
+ permissions: ['settings.update'],
118
118
  },
119
119
  {
120
- method: "GET",
121
- path: "/organisations/:orgId/sample/status",
122
- permissions: ["organisations.read"],
120
+ method: 'GET',
121
+ path: '/organisations/:orgId/sample/status',
122
+ permissions: ['organisations.read'],
123
123
  },
124
124
  {
125
- method: "POST",
126
- path: "/organisations/:orgId/sample/echo",
127
- permissions: ["organisations.update"],
125
+ method: 'POST',
126
+ path: '/organisations/:orgId/sample/echo',
127
+ permissions: ['organisations.update'],
128
128
  },
129
129
  ];
@@ -1,8 +1,8 @@
1
- import { BadRequestException, Injectable } from "@nestjs/common";
2
- import { Prisma } from "@prisma/client";
3
- import { PrismaService } from "../../../../database/prisma/prisma.service";
4
- import { RequestContextService } from "../../../request-context/application/services/request-context.service";
5
- import { ListAuditLogsQueryDto } from "../../dto/list-audit-logs-query.dto";
1
+ import { BadRequestException, Injectable } from '@nestjs/common';
2
+ import { Prisma } from '@prisma/client';
3
+ import { PrismaService } from '../../../../database/prisma/prisma.service';
4
+ import { RequestContextService } from '../../../request-context/application/services/request-context.service';
5
+ import { ListAuditLogsQueryDto } from '../../dto/list-audit-logs-query.dto';
6
6
 
7
7
  type PrismaClient = Prisma.TransactionClient | PrismaService;
8
8
 
@@ -47,7 +47,7 @@ export class AuditService {
47
47
 
48
48
  const limit = Math.min(query.limit ?? DEFAULT_LIMIT, MAX_LIMIT);
49
49
  if (query.from && query.to && new Date(query.from) > new Date(query.to)) {
50
- throw new BadRequestException("from must be before or equal to to.");
50
+ throw new BadRequestException('from must be before or equal to to.');
51
51
  }
52
52
 
53
53
  const createdAt: Prisma.DateTimeFilter =
@@ -76,7 +76,7 @@ export class AuditService {
76
76
  },
77
77
  },
78
78
  },
79
- orderBy: [{ createdAt: "desc" }, { id: "desc" }],
79
+ orderBy: [{ createdAt: 'desc' }, { id: 'desc' }],
80
80
  take: limit + 1,
81
81
  ...(query.cursor
82
82
  ? {
@@ -1,7 +1,7 @@
1
- import { Global, Module } from "@nestjs/common";
2
- import { AuthModule } from "../auth/auth.module";
3
- import { AuditService } from "./application/services/audit.service";
4
- import { AuditController } from "./presentation/audit.controller";
1
+ import { Global, Module } from '@nestjs/common';
2
+ import { AuthModule } from '../auth/auth.module';
3
+ import { AuditService } from './application/services/audit.service';
4
+ import { AuditController } from './presentation/audit.controller';
5
5
 
6
6
  @Global()
7
7
  @Module({
@@ -1,62 +1,62 @@
1
- import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
1
+ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
2
2
 
3
3
  class AuditActorResponseDto {
4
4
  @ApiProperty({
5
- example: "4a4f0d8a-4bd2-469f-a6a9-3e1cb6a2b456",
6
- format: "uuid",
5
+ example: '4a4f0d8a-4bd2-469f-a6a9-3e1cb6a2b456',
6
+ format: 'uuid',
7
7
  })
8
8
  id!: string;
9
9
 
10
- @ApiPropertyOptional({ example: "Starter Owner", nullable: true })
10
+ @ApiPropertyOptional({ example: 'Starter Owner', nullable: true })
11
11
  displayName?: string | null;
12
12
  }
13
13
 
14
14
  export class AuditLogResponseDto {
15
15
  @ApiProperty({
16
- example: "df6537c4-f58b-452e-a67e-18ec528d0f0f",
17
- format: "uuid",
16
+ example: 'df6537c4-f58b-452e-a67e-18ec528d0f0f',
17
+ format: 'uuid',
18
18
  })
19
19
  id!: string;
20
20
 
21
21
  @ApiPropertyOptional({
22
- example: "2c67399d-670c-4025-a5fd-1ea9a211891e",
23
- format: "uuid",
22
+ example: '2c67399d-670c-4025-a5fd-1ea9a211891e',
23
+ format: 'uuid',
24
24
  nullable: true,
25
25
  })
26
26
  orgId?: string | null;
27
27
 
28
28
  @ApiPropertyOptional({
29
- example: "4a4f0d8a-4bd2-469f-a6a9-3e1cb6a2b456",
30
- format: "uuid",
29
+ example: '4a4f0d8a-4bd2-469f-a6a9-3e1cb6a2b456',
30
+ format: 'uuid',
31
31
  nullable: true,
32
32
  })
33
33
  actorUserId?: string | null;
34
34
 
35
- @ApiProperty({ example: "membership.status.update" })
35
+ @ApiProperty({ example: 'membership.status.update' })
36
36
  action!: string;
37
37
 
38
- @ApiProperty({ example: "Membership" })
38
+ @ApiProperty({ example: 'Membership' })
39
39
  targetType!: string;
40
40
 
41
41
  @ApiPropertyOptional({
42
- example: "0a57fb4a-95c6-4f7e-bd5a-f96dbe0599e3",
42
+ example: '0a57fb4a-95c6-4f7e-bd5a-f96dbe0599e3',
43
43
  nullable: true,
44
44
  })
45
45
  targetId?: string | null;
46
46
 
47
47
  @ApiPropertyOptional({
48
- example: { previousStatus: "ACTIVE", nextStatus: "SUSPENDED" },
48
+ example: { previousStatus: 'ACTIVE', nextStatus: 'SUSPENDED' },
49
49
  nullable: true,
50
50
  })
51
51
  metadata?: Record<string, unknown> | null;
52
52
 
53
- @ApiPropertyOptional({ example: "127.0.0.1", nullable: true })
53
+ @ApiPropertyOptional({ example: '127.0.0.1', nullable: true })
54
54
  ipAddress?: string | null;
55
55
 
56
- @ApiPropertyOptional({ example: "Mozilla/5.0", nullable: true })
56
+ @ApiPropertyOptional({ example: 'Mozilla/5.0', nullable: true })
57
57
  userAgent?: string | null;
58
58
 
59
- @ApiProperty({ example: "2026-06-01T10:30:00.000Z", format: "date-time" })
59
+ @ApiProperty({ example: '2026-06-01T10:30:00.000Z', format: 'date-time' })
60
60
  createdAt!: string;
61
61
 
62
62
  @ApiPropertyOptional({ type: AuditActorResponseDto, nullable: true })
@@ -68,7 +68,7 @@ export class AuditLogListResponseDto {
68
68
  items!: AuditLogResponseDto[];
69
69
 
70
70
  @ApiPropertyOptional({
71
- example: "df6537c4-f58b-452e-a67e-18ec528d0f0f",
71
+ example: 'df6537c4-f58b-452e-a67e-18ec528d0f0f',
72
72
  nullable: true,
73
73
  })
74
74
  nextCursor?: string | null;