@ftisindia/create-app 0.1.3 → 0.1.5
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.
- package/package.json +1 -1
- package/template/.env.example +6 -0
- package/template/README.md +11 -1
- package/template/_package.json +0 -2
- package/template/docs/API_REFERENCE.md +13 -0
- package/template/docs/OAUTH.md +7 -3
- package/template/scripts/gen-module.mjs +2 -0
- package/template/src/app.module.ts +16 -22
- package/template/src/common/dto/error-response.dto.ts +3 -3
- package/template/src/common/dto/membership-response.dto.ts +26 -14
- package/template/src/common/dto/mutation-response.dto.ts +1 -1
- package/template/src/common/dto/pagination-query.dto.ts +37 -0
- package/template/src/common/dto/role-summary.dto.ts +5 -5
- package/template/src/common/dto/user-summary.dto.ts +6 -6
- package/template/src/common/filters/http-exception.filter.ts +9 -19
- package/template/src/common/swagger/api-error-responses.ts +12 -12
- package/template/src/config/app.config.ts +8 -3
- package/template/src/config/auth.config.ts +3 -3
- package/template/src/config/database.config.ts +3 -3
- package/template/src/config/env.validation.ts +78 -40
- package/template/src/config/index.ts +5 -5
- package/template/src/config/rbac.config.ts +3 -3
- package/template/src/database/prisma/prisma-transaction.ts +1 -1
- package/template/src/database/prisma/prisma.module.ts +2 -2
- package/template/src/database/prisma/prisma.service.ts +3 -6
- package/template/src/main.ts +24 -11
- package/template/src/modules/access-control/access-control.module.ts +11 -10
- package/template/src/modules/access-control/application/role-permission-policy.ts +71 -0
- package/template/src/modules/access-control/application/route-registry.validator.ts +34 -63
- package/template/src/modules/access-control/application/services/ability.factory.ts +5 -9
- package/template/src/modules/access-control/application/services/access-control.service.ts +78 -85
- package/template/src/modules/access-control/application/services/permission.guard.ts +16 -21
- package/template/src/modules/access-control/application/services/rbac-cache.service.ts +7 -9
- package/template/src/modules/access-control/dto/access-control-response.dto.ts +32 -20
- package/template/src/modules/access-control/dto/create-role.dto.ts +6 -6
- package/template/src/modules/access-control/dto/current-access-control-response.dto.ts +31 -0
- package/template/src/modules/access-control/dto/update-role-permissions.dto.ts +3 -10
- package/template/src/modules/access-control/dto/update-role.dto.ts +6 -6
- package/template/src/modules/access-control/presentation/access-control.controller.ts +69 -74
- package/template/src/modules/access-control/presentation/current-access-control.controller.ts +40 -0
- package/template/src/modules/access-control/presentation/permissions.decorator.ts +3 -3
- package/template/src/modules/access-control/presentation/public.decorator.ts +2 -2
- package/template/src/modules/access-control/types/permission-key.ts +19 -19
- package/template/src/modules/access-control/types/route-permission-registry.ts +76 -76
- package/template/src/modules/audit/application/services/audit.service.ts +7 -7
- package/template/src/modules/audit/audit.module.ts +4 -4
- package/template/src/modules/audit/dto/audit-response.dto.ts +18 -18
- package/template/src/modules/audit/dto/list-audit-logs-query.dto.ts +14 -14
- package/template/src/modules/audit/presentation/audit.controller.ts +17 -23
- package/template/src/modules/auth/application/services/auth.service.ts +147 -110
- package/template/src/modules/auth/application/services/password.service.ts +2 -2
- package/template/src/modules/auth/application/services/token.service.ts +20 -21
- package/template/src/modules/auth/auth.module.ts +20 -47
- package/template/src/modules/auth/dto/auth-response.dto.ts +9 -10
- package/template/src/modules/auth/dto/login.dto.ts +4 -4
- package/template/src/modules/auth/dto/logout.dto.ts +1 -1
- package/template/src/modules/auth/dto/oauth-exchange.dto.ts +4 -5
- package/template/src/modules/auth/dto/refresh-token.dto.ts +4 -5
- package/template/src/modules/auth/dto/signup.dto.ts +5 -11
- package/template/src/modules/auth/infrastructure/passport/google-auth.guard.ts +6 -14
- package/template/src/modules/auth/infrastructure/passport/google-oauth-state.store.ts +98 -0
- package/template/src/modules/auth/infrastructure/passport/google.strategy.ts +21 -30
- package/template/src/modules/auth/infrastructure/passport/jwt-auth.guard.ts +3 -3
- package/template/src/modules/auth/infrastructure/passport/jwt.strategy.ts +11 -11
- package/template/src/modules/auth/presentation/auth.controller.ts +45 -45
- package/template/src/modules/auth/presentation/current-user.decorator.ts +3 -5
- package/template/src/modules/auth/presentation/google-oauth-exception.filter.ts +5 -10
- package/template/src/modules/health/dto/health-response.dto.ts +5 -5
- package/template/src/modules/health/health.module.ts +2 -2
- package/template/src/modules/health/presentation/health.controller.ts +13 -13
- package/template/src/modules/invitations/application/services/invitations.service.ts +127 -176
- package/template/src/modules/invitations/dto/accept-invitation.dto.ts +6 -7
- package/template/src/modules/invitations/dto/create-invitation.dto.ts +14 -15
- package/template/src/modules/invitations/dto/invitation-response.dto.ts +37 -29
- package/template/src/modules/invitations/dto/invitation-token.dto.ts +4 -4
- package/template/src/modules/invitations/invitations.module.ts +5 -5
- package/template/src/modules/invitations/presentation/invitations.controller.ts +61 -63
- package/template/src/modules/memberships/application/services/memberships.service.ts +70 -84
- package/template/src/modules/memberships/dto/transfer-owner.dto.ts +4 -4
- package/template/src/modules/memberships/dto/update-billing-contact.dto.ts +2 -2
- package/template/src/modules/memberships/dto/update-membership-owner.dto.ts +2 -2
- package/template/src/modules/memberships/dto/update-membership-role.dto.ts +4 -4
- package/template/src/modules/memberships/dto/update-membership-status.dto.ts +3 -3
- package/template/src/modules/memberships/memberships.module.ts +4 -4
- package/template/src/modules/memberships/presentation/memberships.controller.ts +83 -99
- package/template/src/modules/organisations/application/services/organisations.service.ts +87 -23
- package/template/src/modules/organisations/dto/create-organisation.dto.ts +6 -13
- package/template/src/modules/organisations/dto/organisation-response.dto.ts +65 -14
- package/template/src/modules/organisations/infrastructure/repositories/organisations.repository.ts +4 -7
- package/template/src/modules/organisations/organisations.module.ts +5 -5
- package/template/src/modules/organisations/presentation/organisations.controller.ts +31 -18
- package/template/src/modules/organisations/types/default-organisation-data.ts +3 -9
- package/template/src/modules/request-context/application/services/request-context.service.ts +15 -7
- package/template/src/modules/request-context/presentation/org-scope.guard.ts +4 -9
- package/template/src/modules/request-context/presentation/request-context.interceptor.ts +4 -9
- package/template/src/modules/request-context/presentation/request-context.middleware.ts +7 -8
- package/template/src/modules/request-context/request-context.module.ts +7 -7
- package/template/src/modules/request-context/types/request-context.ts +2 -2
- package/template/src/modules/sample/application/services/sample.service.ts +10 -8
- package/template/src/modules/sample/dto/sample-echo.dto.ts +3 -3
- package/template/src/modules/sample/dto/sample-response.dto.ts +12 -12
- package/template/src/modules/sample/presentation/sample.controller.ts +25 -42
- package/template/src/modules/sample/sample.module.ts +4 -4
- package/template/src/modules/settings/application/services/settings.service.ts +15 -27
- package/template/src/modules/settings/dto/setting-response.dto.ts +9 -9
- package/template/src/modules/settings/dto/update-setting.dto.ts +5 -5
- package/template/src/modules/settings/presentation/settings.controller.ts +29 -35
- package/template/src/modules/settings/settings.module.ts +5 -5
- package/template/src/modules/settings/types/setting-definitions.ts +49 -33
- package/template/test/auth-refresh.spec.ts +90 -0
- package/template/test/frontend-bootstrap.spec.ts +181 -0
- package/template/test/role-permission-policy.spec.ts +94 -0
- package/template/test/route-registry.validator.spec.ts +12 -0
- package/template/test/security.e2e-spec.ts +134 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ApiProperty, ApiPropertyOptional } from
|
|
2
|
-
import { InvitationTargetType } from
|
|
3
|
-
import { Type } from
|
|
1
|
+
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
2
|
+
import { InvitationTargetType } from '@prisma/client';
|
|
3
|
+
import { Type } from 'class-transformer';
|
|
4
4
|
import {
|
|
5
5
|
isEmail,
|
|
6
6
|
IsEnum,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
ValidationArguments,
|
|
17
17
|
ValidatorConstraint,
|
|
18
18
|
ValidatorConstraintInterface,
|
|
19
|
-
} from
|
|
19
|
+
} from 'class-validator';
|
|
20
20
|
|
|
21
21
|
const mobileTargetPattern = /^\+?[1-9]\d{6,14}$/;
|
|
22
22
|
|
|
@@ -24,10 +24,10 @@ type InvitationTargetValueObject = {
|
|
|
24
24
|
targetType?: InvitationTargetType;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
-
@ValidatorConstraint({ name:
|
|
27
|
+
@ValidatorConstraint({ name: 'InvitationTargetValue', async: false })
|
|
28
28
|
class InvitationTargetValueConstraint implements ValidatorConstraintInterface {
|
|
29
29
|
validate(value: unknown, args: ValidationArguments) {
|
|
30
|
-
if (typeof value !==
|
|
30
|
+
if (typeof value !== 'string') {
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -46,14 +46,14 @@ class InvitationTargetValueConstraint implements ValidatorConstraintInterface {
|
|
|
46
46
|
defaultMessage(args: ValidationArguments) {
|
|
47
47
|
const targetType = (args.object as InvitationTargetValueObject).targetType;
|
|
48
48
|
if (targetType === InvitationTargetType.EMAIL) {
|
|
49
|
-
return
|
|
49
|
+
return 'targetValue must be a valid email address when targetType is EMAIL';
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if (targetType === InvitationTargetType.MOBILE) {
|
|
53
|
-
return
|
|
53
|
+
return 'targetValue must be an E.164-style mobile number when targetType is MOBILE';
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
return
|
|
56
|
+
return 'targetValue must match targetType';
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -66,9 +66,8 @@ export class CreateInvitationDto {
|
|
|
66
66
|
targetType!: InvitationTargetType;
|
|
67
67
|
|
|
68
68
|
@ApiProperty({
|
|
69
|
-
description:
|
|
70
|
-
|
|
71
|
-
example: "new.member@example.com",
|
|
69
|
+
description: 'Email address or E.164-style mobile number matching targetType.',
|
|
70
|
+
example: 'new.member@example.com',
|
|
72
71
|
minLength: 3,
|
|
73
72
|
maxLength: 320,
|
|
74
73
|
})
|
|
@@ -79,14 +78,14 @@ export class CreateInvitationDto {
|
|
|
79
78
|
targetValue!: string;
|
|
80
79
|
|
|
81
80
|
@ApiProperty({
|
|
82
|
-
example:
|
|
83
|
-
format:
|
|
81
|
+
example: 'f602c057-04f4-4ef8-8c84-1b7c62fbf8c5',
|
|
82
|
+
format: 'uuid',
|
|
84
83
|
})
|
|
85
84
|
@IsUUID()
|
|
86
85
|
roleId!: string;
|
|
87
86
|
|
|
88
87
|
@ApiPropertyOptional({
|
|
89
|
-
description:
|
|
88
|
+
description: 'Invitation lifetime in days.',
|
|
90
89
|
example: 7,
|
|
91
90
|
minimum: 1,
|
|
92
91
|
maximum: 30,
|
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
import { ApiProperty, ApiPropertyOptional } from
|
|
2
|
-
import { InvitationStatus, InvitationTargetType } from
|
|
3
|
-
import { MembershipResponseDto } from
|
|
4
|
-
import { RoleSummaryDto } from
|
|
5
|
-
import {
|
|
6
|
-
ActiveUserSummaryDto,
|
|
7
|
-
UserSummaryDto,
|
|
8
|
-
} from "../../../common/dto/user-summary.dto";
|
|
1
|
+
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
2
|
+
import { InvitationStatus, InvitationTargetType } from '@prisma/client';
|
|
3
|
+
import { MembershipResponseDto } from '../../../common/dto/membership-response.dto';
|
|
4
|
+
import { RoleSummaryDto } from '../../../common/dto/role-summary.dto';
|
|
5
|
+
import { ActiveUserSummaryDto, UserSummaryDto } from '../../../common/dto/user-summary.dto';
|
|
9
6
|
|
|
10
7
|
export class InvitationResponseDto {
|
|
11
8
|
@ApiProperty({
|
|
12
|
-
example:
|
|
13
|
-
format:
|
|
9
|
+
example: '17a21ad7-bd1b-42d8-b809-0a3892bb60c3',
|
|
10
|
+
format: 'uuid',
|
|
14
11
|
})
|
|
15
12
|
id!: string;
|
|
16
13
|
|
|
17
14
|
@ApiProperty({
|
|
18
|
-
example:
|
|
19
|
-
format:
|
|
15
|
+
example: '2c67399d-670c-4025-a5fd-1ea9a211891e',
|
|
16
|
+
format: 'uuid',
|
|
20
17
|
})
|
|
21
18
|
orgId!: string;
|
|
22
19
|
|
|
@@ -26,33 +23,33 @@ export class InvitationResponseDto {
|
|
|
26
23
|
})
|
|
27
24
|
targetType!: InvitationTargetType;
|
|
28
25
|
|
|
29
|
-
@ApiProperty({ example:
|
|
26
|
+
@ApiProperty({ example: 'new.member@example.com' })
|
|
30
27
|
targetValue!: string;
|
|
31
28
|
|
|
32
|
-
@ApiProperty({ example:
|
|
29
|
+
@ApiProperty({ example: 'new.member@example.com' })
|
|
33
30
|
normalizedTargetValue!: string;
|
|
34
31
|
|
|
35
32
|
@ApiProperty({
|
|
36
|
-
example:
|
|
37
|
-
format:
|
|
33
|
+
example: 'f602c057-04f4-4ef8-8c84-1b7c62fbf8c5',
|
|
34
|
+
format: 'uuid',
|
|
38
35
|
})
|
|
39
36
|
roleId!: string;
|
|
40
37
|
|
|
41
38
|
@ApiProperty({ enum: InvitationStatus, example: InvitationStatus.PENDING })
|
|
42
39
|
status!: InvitationStatus;
|
|
43
40
|
|
|
44
|
-
@ApiProperty({ example:
|
|
41
|
+
@ApiProperty({ example: '2026-06-08T10:30:00.000Z', format: 'date-time' })
|
|
45
42
|
expiresAt!: string;
|
|
46
43
|
|
|
47
44
|
@ApiProperty({
|
|
48
|
-
example:
|
|
49
|
-
format:
|
|
45
|
+
example: '4a4f0d8a-4bd2-469f-a6a9-3e1cb6a2b456',
|
|
46
|
+
format: 'uuid',
|
|
50
47
|
})
|
|
51
48
|
invitedByUserId!: string;
|
|
52
49
|
|
|
53
50
|
@ApiPropertyOptional({
|
|
54
|
-
example:
|
|
55
|
-
format:
|
|
51
|
+
example: '7efd9a26-fbec-4511-ae37-7fb1c35e5215',
|
|
52
|
+
format: 'uuid',
|
|
56
53
|
nullable: true,
|
|
57
54
|
})
|
|
58
55
|
acceptedByUserId?: string | null;
|
|
@@ -66,19 +63,19 @@ export class InvitationResponseDto {
|
|
|
66
63
|
@ApiPropertyOptional({ type: UserSummaryDto, nullable: true })
|
|
67
64
|
acceptedByUser?: UserSummaryDto | null;
|
|
68
65
|
|
|
69
|
-
@ApiProperty({ example:
|
|
66
|
+
@ApiProperty({ example: '2026-06-01T10:30:00.000Z', format: 'date-time' })
|
|
70
67
|
createdAt!: string;
|
|
71
68
|
|
|
72
69
|
@ApiPropertyOptional({
|
|
73
|
-
example:
|
|
74
|
-
format:
|
|
70
|
+
example: '2026-06-01T10:35:00.000Z',
|
|
71
|
+
format: 'date-time',
|
|
75
72
|
nullable: true,
|
|
76
73
|
})
|
|
77
74
|
acceptedAt?: string | null;
|
|
78
75
|
|
|
79
76
|
@ApiPropertyOptional({
|
|
80
|
-
example:
|
|
81
|
-
format:
|
|
77
|
+
example: '2026-06-01T10:40:00.000Z',
|
|
78
|
+
format: 'date-time',
|
|
82
79
|
nullable: true,
|
|
83
80
|
})
|
|
84
81
|
revokedAt?: string | null;
|
|
@@ -89,13 +86,24 @@ export class InvitationWithTokenResponseDto {
|
|
|
89
86
|
invitation!: InvitationResponseDto;
|
|
90
87
|
|
|
91
88
|
@ApiProperty({
|
|
92
|
-
description:
|
|
93
|
-
|
|
94
|
-
example: "k0Y7QJr7pC1r7GJrFXdN2vzmw1lYkT5YhJdORQb4Pp4",
|
|
89
|
+
description: 'One-time invitation token. This is returned only at create/resend time.',
|
|
90
|
+
example: 'k0Y7QJr7pC1r7GJrFXdN2vzmw1lYkT5YhJdORQb4Pp4',
|
|
95
91
|
})
|
|
96
92
|
inviteToken!: string;
|
|
97
93
|
}
|
|
98
94
|
|
|
95
|
+
export class InvitationListResponseDto {
|
|
96
|
+
@ApiProperty({ type: [InvitationResponseDto] })
|
|
97
|
+
items!: InvitationResponseDto[];
|
|
98
|
+
|
|
99
|
+
@ApiPropertyOptional({
|
|
100
|
+
example: '17a21ad7-bd1b-42d8-b809-0a3892bb60c3',
|
|
101
|
+
format: 'uuid',
|
|
102
|
+
nullable: true,
|
|
103
|
+
})
|
|
104
|
+
nextCursor!: string | null;
|
|
105
|
+
}
|
|
106
|
+
|
|
99
107
|
export class AcceptInvitationResponseDto {
|
|
100
108
|
@ApiProperty({ type: InvitationResponseDto })
|
|
101
109
|
invitation!: InvitationResponseDto;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ApiProperty } from
|
|
2
|
-
import { IsString, MaxLength, MinLength } from
|
|
1
|
+
import { ApiProperty } from '@nestjs/swagger';
|
|
2
|
+
import { IsString, MaxLength, MinLength } from 'class-validator';
|
|
3
3
|
|
|
4
4
|
export class InvitationTokenDto {
|
|
5
5
|
@ApiProperty({
|
|
6
|
-
description:
|
|
7
|
-
example:
|
|
6
|
+
description: 'One-time invitation token from create/resend invitation.',
|
|
7
|
+
example: 'k0Y7QJr7pC1r7GJrFXdN2vzmw1lYkT5YhJdORQb4Pp4',
|
|
8
8
|
minLength: 20,
|
|
9
9
|
maxLength: 256,
|
|
10
10
|
})
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Module } from
|
|
2
|
-
import { AuthModule } from
|
|
3
|
-
import { MembershipsModule } from
|
|
4
|
-
import { InvitationsService } from
|
|
5
|
-
import { InvitationsController } from
|
|
1
|
+
import { Module } from '@nestjs/common';
|
|
2
|
+
import { AuthModule } from '../auth/auth.module';
|
|
3
|
+
import { MembershipsModule } from '../memberships/memberships.module';
|
|
4
|
+
import { InvitationsService } from './application/services/invitations.service';
|
|
5
|
+
import { InvitationsController } from './presentation/invitations.controller';
|
|
6
6
|
|
|
7
7
|
@Module({
|
|
8
8
|
imports: [AuthModule, MembershipsModule],
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Body,
|
|
3
|
-
Controller,
|
|
4
|
-
Get,
|
|
5
|
-
HttpCode,
|
|
6
|
-
Param,
|
|
7
|
-
Post,
|
|
8
|
-
UseGuards,
|
|
9
|
-
} from "@nestjs/common";
|
|
1
|
+
import { Body, Controller, Get, HttpCode, Param, Post, Query, UseGuards } from '@nestjs/common';
|
|
10
2
|
import {
|
|
11
3
|
ApiBearerAuth,
|
|
12
4
|
ApiCreatedResponse,
|
|
@@ -14,120 +6,126 @@ import {
|
|
|
14
6
|
ApiOperation,
|
|
15
7
|
ApiParam,
|
|
16
8
|
ApiTags,
|
|
17
|
-
} from
|
|
18
|
-
import { ApiErrorResponses } from
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
9
|
+
} from '@nestjs/swagger';
|
|
10
|
+
import { ApiErrorResponses } from '../../../common/swagger/api-error-responses';
|
|
11
|
+
import { PaginationQueryDto } from '../../../common/dto/pagination-query.dto';
|
|
12
|
+
import { PermissionGuard } from '../../access-control/application/services/permission.guard';
|
|
13
|
+
import { RequirePermissions } from '../../access-control/presentation/permissions.decorator';
|
|
14
|
+
import { JwtAuthGuard } from '../../auth/infrastructure/passport/jwt-auth.guard';
|
|
15
|
+
import { CurrentUser } from '../../auth/presentation/current-user.decorator';
|
|
16
|
+
import { AuthenticatedUser } from '../../auth/types/authenticated-user';
|
|
17
|
+
import { OrgScopeGuard } from '../../request-context/presentation/org-scope.guard';
|
|
18
|
+
import { InvitationsService } from '../application/services/invitations.service';
|
|
19
|
+
import { AcceptInvitationDto } from '../dto/accept-invitation.dto';
|
|
20
|
+
import { CreateInvitationDto } from '../dto/create-invitation.dto';
|
|
21
|
+
import { InvitationTokenDto } from '../dto/invitation-token.dto';
|
|
29
22
|
import {
|
|
30
23
|
AcceptInvitationResponseDto,
|
|
24
|
+
InvitationListResponseDto,
|
|
31
25
|
InvitationResponseDto,
|
|
32
26
|
InvitationWithTokenResponseDto,
|
|
33
|
-
} from
|
|
27
|
+
} from '../dto/invitation-response.dto';
|
|
34
28
|
|
|
35
|
-
@ApiTags(
|
|
29
|
+
@ApiTags('Invitations')
|
|
36
30
|
@Controller()
|
|
37
31
|
export class InvitationsController {
|
|
38
32
|
constructor(private readonly invitationsService: InvitationsService) {}
|
|
39
33
|
|
|
40
|
-
@Post(
|
|
34
|
+
@Post('organisations/:orgId/invitations')
|
|
41
35
|
@UseGuards(JwtAuthGuard, OrgScopeGuard, PermissionGuard)
|
|
42
|
-
@RequirePermissions(
|
|
36
|
+
@RequirePermissions('memberships.invite')
|
|
43
37
|
@ApiBearerAuth()
|
|
44
|
-
@ApiParam({ name:
|
|
38
|
+
@ApiParam({ name: 'orgId', description: 'Organisation ID.', format: 'uuid' })
|
|
45
39
|
@ApiOperation({
|
|
46
|
-
summary:
|
|
40
|
+
summary: 'Create an invitation for an email or mobile target.',
|
|
47
41
|
})
|
|
48
42
|
@ApiCreatedResponse({
|
|
49
|
-
description:
|
|
43
|
+
description: 'Invitation created. The inviteToken is shown once.',
|
|
50
44
|
type: InvitationWithTokenResponseDto,
|
|
51
45
|
})
|
|
52
46
|
@ApiErrorResponses(400, 401, 403, 404, 409)
|
|
53
47
|
create(
|
|
54
48
|
@CurrentUser() user: AuthenticatedUser,
|
|
55
|
-
@Param(
|
|
49
|
+
@Param('orgId') orgId: string,
|
|
56
50
|
@Body() dto: CreateInvitationDto,
|
|
57
51
|
) {
|
|
58
52
|
return this.invitationsService.createInvitation(user, orgId, dto);
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
@Get(
|
|
55
|
+
@Get('organisations/:orgId/invitations')
|
|
62
56
|
@UseGuards(JwtAuthGuard, OrgScopeGuard, PermissionGuard)
|
|
63
|
-
@RequirePermissions(
|
|
57
|
+
@RequirePermissions('memberships.read')
|
|
64
58
|
@ApiBearerAuth()
|
|
65
|
-
@ApiParam({ name:
|
|
66
|
-
@ApiOperation({ summary:
|
|
59
|
+
@ApiParam({ name: 'orgId', description: 'Organisation ID.', format: 'uuid' })
|
|
60
|
+
@ApiOperation({ summary: 'List invitations for an organisation.' })
|
|
67
61
|
@ApiOkResponse({
|
|
68
|
-
description:
|
|
69
|
-
type:
|
|
62
|
+
description: 'Organisation invitations.',
|
|
63
|
+
type: InvitationListResponseDto,
|
|
70
64
|
})
|
|
71
65
|
@ApiErrorResponses(400, 401, 403)
|
|
72
|
-
list(
|
|
73
|
-
|
|
66
|
+
list(
|
|
67
|
+
@CurrentUser() user: AuthenticatedUser,
|
|
68
|
+
@Param('orgId') orgId: string,
|
|
69
|
+
@Query() query: PaginationQueryDto,
|
|
70
|
+
) {
|
|
71
|
+
return this.invitationsService.listInvitations(user, orgId, query);
|
|
74
72
|
}
|
|
75
73
|
|
|
76
|
-
@Post(
|
|
74
|
+
@Post('organisations/:orgId/invitations/:invitationId/revoke')
|
|
77
75
|
@HttpCode(200)
|
|
78
76
|
@UseGuards(JwtAuthGuard, OrgScopeGuard, PermissionGuard)
|
|
79
|
-
@RequirePermissions(
|
|
77
|
+
@RequirePermissions('memberships.revoke')
|
|
80
78
|
@ApiBearerAuth()
|
|
81
|
-
@ApiParam({ name:
|
|
79
|
+
@ApiParam({ name: 'orgId', description: 'Organisation ID.', format: 'uuid' })
|
|
82
80
|
@ApiParam({
|
|
83
|
-
name:
|
|
84
|
-
description:
|
|
85
|
-
format:
|
|
81
|
+
name: 'invitationId',
|
|
82
|
+
description: 'Invitation ID.',
|
|
83
|
+
format: 'uuid',
|
|
86
84
|
})
|
|
87
|
-
@ApiOperation({ summary:
|
|
85
|
+
@ApiOperation({ summary: 'Revoke a pending invitation.' })
|
|
88
86
|
@ApiOkResponse({
|
|
89
|
-
description:
|
|
87
|
+
description: 'Revoked invitation.',
|
|
90
88
|
type: InvitationResponseDto,
|
|
91
89
|
})
|
|
92
90
|
@ApiErrorResponses(400, 401, 403, 404, 409, 410)
|
|
93
91
|
revoke(
|
|
94
92
|
@CurrentUser() user: AuthenticatedUser,
|
|
95
|
-
@Param(
|
|
96
|
-
@Param(
|
|
93
|
+
@Param('orgId') orgId: string,
|
|
94
|
+
@Param('invitationId') invitationId: string,
|
|
97
95
|
) {
|
|
98
96
|
return this.invitationsService.revokeInvitation(user, orgId, invitationId);
|
|
99
97
|
}
|
|
100
98
|
|
|
101
|
-
@Post(
|
|
99
|
+
@Post('organisations/:orgId/invitations/:invitationId/resend')
|
|
102
100
|
@HttpCode(200)
|
|
103
101
|
@UseGuards(JwtAuthGuard, OrgScopeGuard, PermissionGuard)
|
|
104
|
-
@RequirePermissions(
|
|
102
|
+
@RequirePermissions('memberships.invite')
|
|
105
103
|
@ApiBearerAuth()
|
|
106
|
-
@ApiParam({ name:
|
|
104
|
+
@ApiParam({ name: 'orgId', description: 'Organisation ID.', format: 'uuid' })
|
|
107
105
|
@ApiParam({
|
|
108
|
-
name:
|
|
109
|
-
description:
|
|
110
|
-
format:
|
|
106
|
+
name: 'invitationId',
|
|
107
|
+
description: 'Invitation ID.',
|
|
108
|
+
format: 'uuid',
|
|
111
109
|
})
|
|
112
|
-
@ApiOperation({ summary:
|
|
110
|
+
@ApiOperation({ summary: 'Resend a pending or expired invitation.' })
|
|
113
111
|
@ApiOkResponse({
|
|
114
|
-
description:
|
|
112
|
+
description: 'Invitation resent. The new inviteToken is shown once.',
|
|
115
113
|
type: InvitationWithTokenResponseDto,
|
|
116
114
|
})
|
|
117
115
|
@ApiErrorResponses(400, 401, 403, 404, 409)
|
|
118
116
|
resend(
|
|
119
117
|
@CurrentUser() user: AuthenticatedUser,
|
|
120
|
-
@Param(
|
|
121
|
-
@Param(
|
|
118
|
+
@Param('orgId') orgId: string,
|
|
119
|
+
@Param('invitationId') invitationId: string,
|
|
122
120
|
) {
|
|
123
121
|
return this.invitationsService.resendInvitation(user, orgId, invitationId);
|
|
124
122
|
}
|
|
125
123
|
|
|
126
|
-
@Post(
|
|
124
|
+
@Post('invitations/accept')
|
|
127
125
|
@HttpCode(200)
|
|
128
|
-
@ApiOperation({ summary:
|
|
126
|
+
@ApiOperation({ summary: 'Accept an invitation token.' })
|
|
129
127
|
@ApiOkResponse({
|
|
130
|
-
description:
|
|
128
|
+
description: 'Invitation accepted and membership created.',
|
|
131
129
|
type: AcceptInvitationResponseDto,
|
|
132
130
|
})
|
|
133
131
|
@ApiErrorResponses(400, 401, 409, 410)
|
|
@@ -135,11 +133,11 @@ export class InvitationsController {
|
|
|
135
133
|
return this.invitationsService.acceptInvitation(dto);
|
|
136
134
|
}
|
|
137
135
|
|
|
138
|
-
@Post(
|
|
136
|
+
@Post('invitations/decline')
|
|
139
137
|
@HttpCode(200)
|
|
140
|
-
@ApiOperation({ summary:
|
|
138
|
+
@ApiOperation({ summary: 'Decline an invitation token.' })
|
|
141
139
|
@ApiOkResponse({
|
|
142
|
-
description:
|
|
140
|
+
description: 'Declined invitation.',
|
|
143
141
|
type: InvitationResponseDto,
|
|
144
142
|
})
|
|
145
143
|
@ApiErrorResponses(400, 401, 409, 410)
|