@open-kingdom/shared-backend-feature-user-management 0.0.2-10
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/README.md +11 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/lib/controllers/index.d.ts +3 -0
- package/dist/lib/controllers/index.d.ts.map +1 -0
- package/dist/lib/controllers/index.js +5 -0
- package/dist/lib/controllers/invitations.controller.d.ts +16 -0
- package/dist/lib/controllers/invitations.controller.d.ts.map +1 -0
- package/dist/lib/controllers/invitations.controller.js +102 -0
- package/dist/lib/controllers/users.controller.d.ts +12 -0
- package/dist/lib/controllers/users.controller.d.ts.map +1 -0
- package/dist/lib/controllers/users.controller.js +88 -0
- package/dist/lib/dto/accept-invitation.dto.d.ts +7 -0
- package/dist/lib/dto/accept-invitation.dto.d.ts.map +1 -0
- package/dist/lib/dto/accept-invitation.dto.js +39 -0
- package/dist/lib/dto/index.d.ts +3 -0
- package/dist/lib/dto/index.d.ts.map +1 -0
- package/dist/lib/dto/index.js +5 -0
- package/dist/lib/dto/invite-user.dto.d.ts +5 -0
- package/dist/lib/dto/invite-user.dto.d.ts.map +1 -0
- package/dist/lib/dto/invite-user.dto.js +26 -0
- package/dist/lib/feature-user-management.module.d.ts +8 -0
- package/dist/lib/feature-user-management.module.d.ts.map +1 -0
- package/dist/lib/feature-user-management.module.js +35 -0
- package/dist/lib/schemas/index.d.ts +3 -0
- package/dist/lib/schemas/index.d.ts.map +1 -0
- package/dist/lib/schemas/index.js +5 -0
- package/dist/lib/schemas/invitations.schema.d.ts +158 -0
- package/dist/lib/schemas/invitations.schema.d.ts.map +1 -0
- package/dist/lib/schemas/invitations.schema.js +24 -0
- package/dist/lib/schemas/user-roles.schema.d.ts +100 -0
- package/dist/lib/schemas/user-roles.schema.d.ts.map +1 -0
- package/dist/lib/schemas/user-roles.schema.js +18 -0
- package/dist/lib/services/index.d.ts +3 -0
- package/dist/lib/services/index.d.ts.map +1 -0
- package/dist/lib/services/index.js +5 -0
- package/dist/lib/services/invitations.service.d.ts +31 -0
- package/dist/lib/services/invitations.service.d.ts.map +1 -0
- package/dist/lib/services/invitations.service.js +152 -0
- package/dist/lib/services/user-management.service.d.ts +11 -0
- package/dist/lib/services/user-management.service.d.ts.map +1 -0
- package/dist/lib/services/user-management.service.js +41 -0
- package/dist/lib/templates/index.d.ts +2 -0
- package/dist/lib/templates/index.d.ts.map +1 -0
- package/dist/lib/templates/index.js +4 -0
- package/dist/lib/templates/invitation-email.template.d.ts +7 -0
- package/dist/lib/templates/invitation-email.template.d.ts.map +1 -0
- package/dist/lib/templates/invitation-email.template.js +16 -0
- package/dist/lib/types.d.ts +36 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +11 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# feature-user-management
|
|
2
|
+
|
|
3
|
+
This library was generated with [Nx](https://nx.dev).
|
|
4
|
+
|
|
5
|
+
## Building
|
|
6
|
+
|
|
7
|
+
Run `nx build feature-user-management` to build the library.
|
|
8
|
+
|
|
9
|
+
## Running unit tests
|
|
10
|
+
|
|
11
|
+
Run `nx test feature-user-management` to execute the unit tests via [Jest](https://jestjs.io).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sCAAsC,CAAC;AACrD,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./lib/feature-user-management.module"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./lib/schemas"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./lib/services"), exports);
|
|
7
|
+
tslib_1.__exportStar(require("./lib/dto"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/controllers/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InvitationsService } from '../services';
|
|
2
|
+
import { InviteUserDto, AcceptInvitationDto } from '../dto';
|
|
3
|
+
import type { AuthenticatedRequest } from '../types';
|
|
4
|
+
export declare class InvitationsController {
|
|
5
|
+
private readonly invitationsService;
|
|
6
|
+
constructor(invitationsService: InvitationsService);
|
|
7
|
+
invite(dto: InviteUserDto, req: AuthenticatedRequest): Promise<import("../services").InvitationResponse>;
|
|
8
|
+
validate(token: string): Promise<import("../types").ValidationResult>;
|
|
9
|
+
accept(dto: AcceptInvitationDto): Promise<{
|
|
10
|
+
id: number;
|
|
11
|
+
email: string;
|
|
12
|
+
firstName: string | null;
|
|
13
|
+
lastName: string | null;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=invitations.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitations.controller.d.ts","sourceRoot":"","sources":["../../../src/lib/controllers/invitations.controller.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC5D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,qBAEa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,kBAAkB;gBAAlB,kBAAkB,EAAE,kBAAkB;IAoB7D,MAAM,CACF,GAAG,EAAE,aAAa,EACf,GAAG,EAAE,oBAAoB;IA8BhC,QAAQ,CAAiB,KAAK,EAAE,MAAM;IAiBtC,MAAM,CAAS,GAAG,EAAE,mBAAmB;;;;;;CAW9C"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InvitationsController = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
7
|
+
const passport_1 = require("@nestjs/passport");
|
|
8
|
+
const services_1 = require("../services");
|
|
9
|
+
const dto_1 = require("../dto");
|
|
10
|
+
let InvitationsController = class InvitationsController {
|
|
11
|
+
constructor(invitationsService) {
|
|
12
|
+
this.invitationsService = invitationsService;
|
|
13
|
+
}
|
|
14
|
+
async invite(dto, req) {
|
|
15
|
+
return this.invitationsService.invite(dto.email, dto.role ?? 'guest', req.user.id);
|
|
16
|
+
}
|
|
17
|
+
async validate(token) {
|
|
18
|
+
return this.invitationsService.validate(token);
|
|
19
|
+
}
|
|
20
|
+
async accept(dto) {
|
|
21
|
+
const user = await this.invitationsService.accept(dto.token, dto.password, dto.firstName, dto.lastName);
|
|
22
|
+
const { password: _password, ...userWithoutPassword } = user;
|
|
23
|
+
return userWithoutPassword;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
exports.InvitationsController = InvitationsController;
|
|
27
|
+
tslib_1.__decorate([
|
|
28
|
+
(0, common_1.Post)('invite'),
|
|
29
|
+
(0, swagger_1.ApiBearerAuth)('JWT-auth'),
|
|
30
|
+
(0, common_1.UseGuards)((0, passport_1.AuthGuard)('jwt')),
|
|
31
|
+
(0, swagger_1.ApiOperation)({
|
|
32
|
+
summary: 'Invite a new user',
|
|
33
|
+
description: 'Send an invitation to a new user. Requires authentication.',
|
|
34
|
+
}),
|
|
35
|
+
(0, swagger_1.ApiBody)({ type: dto_1.InviteUserDto }),
|
|
36
|
+
(0, swagger_1.ApiResponse)({
|
|
37
|
+
status: 201,
|
|
38
|
+
description: 'Invitation created successfully',
|
|
39
|
+
}),
|
|
40
|
+
(0, swagger_1.ApiBadRequestResponse)({
|
|
41
|
+
description: 'User already exists or pending invitation exists',
|
|
42
|
+
}),
|
|
43
|
+
(0, swagger_1.ApiUnauthorizedResponse)({
|
|
44
|
+
description: 'Unauthorized - Invalid or missing JWT token',
|
|
45
|
+
}),
|
|
46
|
+
tslib_1.__param(0, (0, common_1.Body)()),
|
|
47
|
+
tslib_1.__param(1, (0, common_1.Request)()),
|
|
48
|
+
tslib_1.__metadata("design:type", Function),
|
|
49
|
+
tslib_1.__metadata("design:paramtypes", [dto_1.InviteUserDto, Object]),
|
|
50
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
51
|
+
], InvitationsController.prototype, "invite", null);
|
|
52
|
+
tslib_1.__decorate([
|
|
53
|
+
(0, common_1.Get)('validate/:token'),
|
|
54
|
+
(0, swagger_1.ApiOperation)({
|
|
55
|
+
summary: 'Validate an invitation token',
|
|
56
|
+
description: 'Check if an invitation token is valid and not expired',
|
|
57
|
+
}),
|
|
58
|
+
(0, swagger_1.ApiResponse)({
|
|
59
|
+
status: 200,
|
|
60
|
+
description: 'Validation result',
|
|
61
|
+
schema: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
properties: {
|
|
64
|
+
valid: { type: 'boolean' },
|
|
65
|
+
email: { type: 'string', nullable: true },
|
|
66
|
+
role: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
enum: ['guest', 'user', 'admin'],
|
|
69
|
+
nullable: true,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
}),
|
|
74
|
+
tslib_1.__param(0, (0, common_1.Param)('token')),
|
|
75
|
+
tslib_1.__metadata("design:type", Function),
|
|
76
|
+
tslib_1.__metadata("design:paramtypes", [String]),
|
|
77
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
78
|
+
], InvitationsController.prototype, "validate", null);
|
|
79
|
+
tslib_1.__decorate([
|
|
80
|
+
(0, common_1.Post)('accept'),
|
|
81
|
+
(0, swagger_1.ApiOperation)({
|
|
82
|
+
summary: 'Accept an invitation',
|
|
83
|
+
description: 'Accept an invitation and create a new user account',
|
|
84
|
+
}),
|
|
85
|
+
(0, swagger_1.ApiBody)({ type: dto_1.AcceptInvitationDto }),
|
|
86
|
+
(0, swagger_1.ApiResponse)({
|
|
87
|
+
status: 201,
|
|
88
|
+
description: 'User created successfully',
|
|
89
|
+
}),
|
|
90
|
+
(0, swagger_1.ApiBadRequestResponse)({
|
|
91
|
+
description: 'Invalid or expired invitation token',
|
|
92
|
+
}),
|
|
93
|
+
tslib_1.__param(0, (0, common_1.Body)()),
|
|
94
|
+
tslib_1.__metadata("design:type", Function),
|
|
95
|
+
tslib_1.__metadata("design:paramtypes", [dto_1.AcceptInvitationDto]),
|
|
96
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
97
|
+
], InvitationsController.prototype, "accept", null);
|
|
98
|
+
exports.InvitationsController = InvitationsController = tslib_1.__decorate([
|
|
99
|
+
(0, swagger_1.ApiTags)('Invitations'),
|
|
100
|
+
(0, common_1.Controller)('invitations'),
|
|
101
|
+
tslib_1.__metadata("design:paramtypes", [services_1.InvitationsService])
|
|
102
|
+
], InvitationsController);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { UserManagementService } from '../services';
|
|
2
|
+
import type { AuthenticatedRequest } from '../types';
|
|
3
|
+
export declare class UsersController {
|
|
4
|
+
private readonly userManagementService;
|
|
5
|
+
constructor(userManagementService: UserManagementService);
|
|
6
|
+
findAll(): Promise<import("../services").UserWithoutPassword[]>;
|
|
7
|
+
findOne(id: number): Promise<import("../services").UserWithoutPassword>;
|
|
8
|
+
delete(id: number, req: AuthenticatedRequest): Promise<{
|
|
9
|
+
message: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=users.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.controller.d.ts","sourceRoot":"","sources":["../../../src/lib/controllers/users.controller.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,qBAOa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBAArB,qBAAqB,EAAE,qBAAqB;IAWnE,OAAO;IAgBP,OAAO,CAA4B,EAAE,EAAE,MAAM;IAmB7C,MAAM,CACiB,EAAE,EAAE,MAAM,EAC1B,GAAG,EAAE,oBAAoB;;;CAKvC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UsersController = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
7
|
+
const passport_1 = require("@nestjs/passport");
|
|
8
|
+
const services_1 = require("../services");
|
|
9
|
+
let UsersController = class UsersController {
|
|
10
|
+
constructor(userManagementService) {
|
|
11
|
+
this.userManagementService = userManagementService;
|
|
12
|
+
}
|
|
13
|
+
async findAll() {
|
|
14
|
+
return this.userManagementService.findAll();
|
|
15
|
+
}
|
|
16
|
+
async findOne(id) {
|
|
17
|
+
return this.userManagementService.findById(id);
|
|
18
|
+
}
|
|
19
|
+
async delete(id, req) {
|
|
20
|
+
await this.userManagementService.delete(id, req.user.id);
|
|
21
|
+
return { message: 'User deleted successfully' };
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
exports.UsersController = UsersController;
|
|
25
|
+
tslib_1.__decorate([
|
|
26
|
+
(0, common_1.Get)(),
|
|
27
|
+
(0, swagger_1.ApiOperation)({
|
|
28
|
+
summary: 'List all users',
|
|
29
|
+
description: 'Returns a list of all users without passwords',
|
|
30
|
+
}),
|
|
31
|
+
(0, swagger_1.ApiResponse)({
|
|
32
|
+
status: 200,
|
|
33
|
+
description: 'List of users',
|
|
34
|
+
}),
|
|
35
|
+
tslib_1.__metadata("design:type", Function),
|
|
36
|
+
tslib_1.__metadata("design:paramtypes", []),
|
|
37
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
38
|
+
], UsersController.prototype, "findAll", null);
|
|
39
|
+
tslib_1.__decorate([
|
|
40
|
+
(0, common_1.Get)(':id'),
|
|
41
|
+
(0, swagger_1.ApiOperation)({
|
|
42
|
+
summary: 'Get a user by ID',
|
|
43
|
+
description: 'Returns a single user by their ID',
|
|
44
|
+
}),
|
|
45
|
+
(0, swagger_1.ApiResponse)({
|
|
46
|
+
status: 200,
|
|
47
|
+
description: 'User found',
|
|
48
|
+
}),
|
|
49
|
+
(0, swagger_1.ApiNotFoundResponse)({
|
|
50
|
+
description: 'User not found',
|
|
51
|
+
}),
|
|
52
|
+
tslib_1.__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
|
53
|
+
tslib_1.__metadata("design:type", Function),
|
|
54
|
+
tslib_1.__metadata("design:paramtypes", [Number]),
|
|
55
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
56
|
+
], UsersController.prototype, "findOne", null);
|
|
57
|
+
tslib_1.__decorate([
|
|
58
|
+
(0, common_1.Delete)(':id'),
|
|
59
|
+
(0, swagger_1.ApiOperation)({
|
|
60
|
+
summary: 'Delete a user',
|
|
61
|
+
description: 'Delete a user by their ID. Cannot delete your own account.',
|
|
62
|
+
}),
|
|
63
|
+
(0, swagger_1.ApiResponse)({
|
|
64
|
+
status: 200,
|
|
65
|
+
description: 'User deleted successfully',
|
|
66
|
+
}),
|
|
67
|
+
(0, swagger_1.ApiNotFoundResponse)({
|
|
68
|
+
description: 'User not found',
|
|
69
|
+
}),
|
|
70
|
+
(0, swagger_1.ApiForbiddenResponse)({
|
|
71
|
+
description: 'Cannot delete your own account',
|
|
72
|
+
}),
|
|
73
|
+
tslib_1.__param(0, (0, common_1.Param)('id', common_1.ParseIntPipe)),
|
|
74
|
+
tslib_1.__param(1, (0, common_1.Request)()),
|
|
75
|
+
tslib_1.__metadata("design:type", Function),
|
|
76
|
+
tslib_1.__metadata("design:paramtypes", [Number, Object]),
|
|
77
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
78
|
+
], UsersController.prototype, "delete", null);
|
|
79
|
+
exports.UsersController = UsersController = tslib_1.__decorate([
|
|
80
|
+
(0, swagger_1.ApiTags)('Users'),
|
|
81
|
+
(0, common_1.Controller)('users'),
|
|
82
|
+
(0, swagger_1.ApiBearerAuth)('JWT-auth'),
|
|
83
|
+
(0, common_1.UseGuards)((0, passport_1.AuthGuard)('jwt')),
|
|
84
|
+
(0, swagger_1.ApiUnauthorizedResponse)({
|
|
85
|
+
description: 'Unauthorized - Invalid or missing JWT token',
|
|
86
|
+
}),
|
|
87
|
+
tslib_1.__metadata("design:paramtypes", [services_1.UserManagementService])
|
|
88
|
+
], UsersController);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"accept-invitation.dto.d.ts","sourceRoot":"","sources":["../../../src/lib/dto/accept-invitation.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,mBAAmB;IAK9B,KAAK,EAAG,MAAM,CAAC;IAOf,QAAQ,EAAG,MAAM,CAAC;IAOlB,SAAS,CAAC,EAAE,MAAM,CAAC;IAOnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AcceptInvitationDto = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
6
|
+
class AcceptInvitationDto {
|
|
7
|
+
}
|
|
8
|
+
exports.AcceptInvitationDto = AcceptInvitationDto;
|
|
9
|
+
tslib_1.__decorate([
|
|
10
|
+
(0, swagger_1.ApiProperty)({
|
|
11
|
+
description: 'Invitation token from the invite link',
|
|
12
|
+
example: 'abc123def456',
|
|
13
|
+
}),
|
|
14
|
+
tslib_1.__metadata("design:type", String)
|
|
15
|
+
], AcceptInvitationDto.prototype, "token", void 0);
|
|
16
|
+
tslib_1.__decorate([
|
|
17
|
+
(0, swagger_1.ApiProperty)({
|
|
18
|
+
description: 'Password for the new account',
|
|
19
|
+
example: 'securePassword123',
|
|
20
|
+
minLength: 8,
|
|
21
|
+
}),
|
|
22
|
+
tslib_1.__metadata("design:type", String)
|
|
23
|
+
], AcceptInvitationDto.prototype, "password", void 0);
|
|
24
|
+
tslib_1.__decorate([
|
|
25
|
+
(0, swagger_1.ApiProperty)({
|
|
26
|
+
description: 'First name of the user',
|
|
27
|
+
example: 'John',
|
|
28
|
+
required: false,
|
|
29
|
+
}),
|
|
30
|
+
tslib_1.__metadata("design:type", String)
|
|
31
|
+
], AcceptInvitationDto.prototype, "firstName", void 0);
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, swagger_1.ApiProperty)({
|
|
34
|
+
description: 'Last name of the user',
|
|
35
|
+
example: 'Doe',
|
|
36
|
+
required: false,
|
|
37
|
+
}),
|
|
38
|
+
tslib_1.__metadata("design:type", String)
|
|
39
|
+
], AcceptInvitationDto.prototype, "lastName", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/dto/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invite-user.dto.d.ts","sourceRoot":"","sources":["../../../src/lib/dto/invite-user.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,aAAa;IAMxB,KAAK,EAAG,MAAM,CAAC;IASf,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CACnC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InviteUserDto = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
6
|
+
class InviteUserDto {
|
|
7
|
+
}
|
|
8
|
+
exports.InviteUserDto = InviteUserDto;
|
|
9
|
+
tslib_1.__decorate([
|
|
10
|
+
(0, swagger_1.ApiProperty)({
|
|
11
|
+
description: 'Email address of the user to invite',
|
|
12
|
+
example: 'newuser@example.com',
|
|
13
|
+
format: 'email',
|
|
14
|
+
}),
|
|
15
|
+
tslib_1.__metadata("design:type", String)
|
|
16
|
+
], InviteUserDto.prototype, "email", void 0);
|
|
17
|
+
tslib_1.__decorate([
|
|
18
|
+
(0, swagger_1.ApiProperty)({
|
|
19
|
+
description: 'Role to assign to the invited user',
|
|
20
|
+
example: 'user',
|
|
21
|
+
enum: ['guest', 'user', 'admin'],
|
|
22
|
+
default: 'guest',
|
|
23
|
+
required: false,
|
|
24
|
+
}),
|
|
25
|
+
tslib_1.__metadata("design:type", String)
|
|
26
|
+
], InviteUserDto.prototype, "role", void 0);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DynamicModule } from '@nestjs/common';
|
|
2
|
+
import type { UserManagementModuleOptions } from './types';
|
|
3
|
+
export { USER_MANAGEMENT_OPTIONS, EMAIL_SENDER, INVITATION_STATUS, } from './types';
|
|
4
|
+
export type { UserManagementModuleOptions, EmailSender, AuthenticatedRequest, Role, InvitationStatus, ValidationResult, } from './types';
|
|
5
|
+
export declare class FeatureUserManagementModule {
|
|
6
|
+
static forRoot(options: UserManagementModuleOptions): DynamicModule;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=feature-user-management.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-user-management.module.d.ts","sourceRoot":"","sources":["../../src/lib/feature-user-management.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAOvD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAE3D,OAAO,EACL,uBAAuB,EACvB,YAAY,EACZ,iBAAiB,GAClB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,2BAA2B,EAC3B,WAAW,EACX,oBAAoB,EACpB,IAAI,EACJ,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,qBACa,2BAA2B;IACtC,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,2BAA2B,GAAG,aAAa;CAcpE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var FeatureUserManagementModule_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.FeatureUserManagementModule = exports.INVITATION_STATUS = exports.EMAIL_SENDER = exports.USER_MANAGEMENT_OPTIONS = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const shared_backend_data_access_users_1 = require("@open-kingdom/shared-backend-data-access-users");
|
|
8
|
+
const shared_backend_feature_email_1 = require("@open-kingdom/shared-backend-feature-email");
|
|
9
|
+
const services_1 = require("./services");
|
|
10
|
+
const controllers_1 = require("./controllers");
|
|
11
|
+
const types_1 = require("./types");
|
|
12
|
+
var types_2 = require("./types");
|
|
13
|
+
Object.defineProperty(exports, "USER_MANAGEMENT_OPTIONS", { enumerable: true, get: function () { return types_2.USER_MANAGEMENT_OPTIONS; } });
|
|
14
|
+
Object.defineProperty(exports, "EMAIL_SENDER", { enumerable: true, get: function () { return types_2.EMAIL_SENDER; } });
|
|
15
|
+
Object.defineProperty(exports, "INVITATION_STATUS", { enumerable: true, get: function () { return types_2.INVITATION_STATUS; } });
|
|
16
|
+
let FeatureUserManagementModule = FeatureUserManagementModule_1 = class FeatureUserManagementModule {
|
|
17
|
+
static forRoot(options) {
|
|
18
|
+
return {
|
|
19
|
+
module: FeatureUserManagementModule_1,
|
|
20
|
+
imports: [shared_backend_data_access_users_1.OpenKingdomDataAccessBackendUsersModule],
|
|
21
|
+
controllers: [controllers_1.InvitationsController, controllers_1.UsersController],
|
|
22
|
+
providers: [
|
|
23
|
+
{ provide: types_1.USER_MANAGEMENT_OPTIONS, useValue: options },
|
|
24
|
+
{ provide: types_1.EMAIL_SENDER, useExisting: shared_backend_feature_email_1.EmailService },
|
|
25
|
+
services_1.InvitationsService,
|
|
26
|
+
services_1.UserManagementService,
|
|
27
|
+
],
|
|
28
|
+
exports: [services_1.InvitationsService, services_1.UserManagementService],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
exports.FeatureUserManagementModule = FeatureUserManagementModule;
|
|
33
|
+
exports.FeatureUserManagementModule = FeatureUserManagementModule = FeatureUserManagementModule_1 = tslib_1.__decorate([
|
|
34
|
+
(0, common_1.Module)({})
|
|
35
|
+
], FeatureUserManagementModule);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/schemas/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import * as t from 'drizzle-orm/sqlite-core';
|
|
2
|
+
export declare const InvitationsTableName = "invitations";
|
|
3
|
+
export declare const invitations: t.SQLiteTableWithColumns<{
|
|
4
|
+
name: "invitations";
|
|
5
|
+
schema: undefined;
|
|
6
|
+
columns: {
|
|
7
|
+
id: t.SQLiteColumn<{
|
|
8
|
+
name: "id";
|
|
9
|
+
tableName: "invitations";
|
|
10
|
+
dataType: "number";
|
|
11
|
+
columnType: "SQLiteInteger";
|
|
12
|
+
data: number;
|
|
13
|
+
driverParam: number;
|
|
14
|
+
notNull: true;
|
|
15
|
+
hasDefault: true;
|
|
16
|
+
isPrimaryKey: true;
|
|
17
|
+
isAutoincrement: false;
|
|
18
|
+
hasRuntimeDefault: false;
|
|
19
|
+
enumValues: undefined;
|
|
20
|
+
baseColumn: never;
|
|
21
|
+
identity: undefined;
|
|
22
|
+
generated: undefined;
|
|
23
|
+
}, {}, {}>;
|
|
24
|
+
email: t.SQLiteColumn<{
|
|
25
|
+
name: "email";
|
|
26
|
+
tableName: "invitations";
|
|
27
|
+
dataType: "string";
|
|
28
|
+
columnType: "SQLiteText";
|
|
29
|
+
data: string;
|
|
30
|
+
driverParam: string;
|
|
31
|
+
notNull: true;
|
|
32
|
+
hasDefault: false;
|
|
33
|
+
isPrimaryKey: false;
|
|
34
|
+
isAutoincrement: false;
|
|
35
|
+
hasRuntimeDefault: false;
|
|
36
|
+
enumValues: [string, ...string[]];
|
|
37
|
+
baseColumn: never;
|
|
38
|
+
identity: undefined;
|
|
39
|
+
generated: undefined;
|
|
40
|
+
}, {}, {
|
|
41
|
+
length: undefined;
|
|
42
|
+
}>;
|
|
43
|
+
token: t.SQLiteColumn<{
|
|
44
|
+
name: "token";
|
|
45
|
+
tableName: "invitations";
|
|
46
|
+
dataType: "string";
|
|
47
|
+
columnType: "SQLiteText";
|
|
48
|
+
data: string;
|
|
49
|
+
driverParam: string;
|
|
50
|
+
notNull: true;
|
|
51
|
+
hasDefault: false;
|
|
52
|
+
isPrimaryKey: false;
|
|
53
|
+
isAutoincrement: false;
|
|
54
|
+
hasRuntimeDefault: false;
|
|
55
|
+
enumValues: [string, ...string[]];
|
|
56
|
+
baseColumn: never;
|
|
57
|
+
identity: undefined;
|
|
58
|
+
generated: undefined;
|
|
59
|
+
}, {}, {
|
|
60
|
+
length: undefined;
|
|
61
|
+
}>;
|
|
62
|
+
tokenExpiry: t.SQLiteColumn<{
|
|
63
|
+
name: "token_expiry";
|
|
64
|
+
tableName: "invitations";
|
|
65
|
+
dataType: "number";
|
|
66
|
+
columnType: "SQLiteInteger";
|
|
67
|
+
data: number;
|
|
68
|
+
driverParam: number;
|
|
69
|
+
notNull: true;
|
|
70
|
+
hasDefault: false;
|
|
71
|
+
isPrimaryKey: false;
|
|
72
|
+
isAutoincrement: false;
|
|
73
|
+
hasRuntimeDefault: false;
|
|
74
|
+
enumValues: undefined;
|
|
75
|
+
baseColumn: never;
|
|
76
|
+
identity: undefined;
|
|
77
|
+
generated: undefined;
|
|
78
|
+
}, {}, {}>;
|
|
79
|
+
invitedBy: t.SQLiteColumn<{
|
|
80
|
+
name: "invited_by";
|
|
81
|
+
tableName: "invitations";
|
|
82
|
+
dataType: "number";
|
|
83
|
+
columnType: "SQLiteInteger";
|
|
84
|
+
data: number;
|
|
85
|
+
driverParam: number;
|
|
86
|
+
notNull: true;
|
|
87
|
+
hasDefault: false;
|
|
88
|
+
isPrimaryKey: false;
|
|
89
|
+
isAutoincrement: false;
|
|
90
|
+
hasRuntimeDefault: false;
|
|
91
|
+
enumValues: undefined;
|
|
92
|
+
baseColumn: never;
|
|
93
|
+
identity: undefined;
|
|
94
|
+
generated: undefined;
|
|
95
|
+
}, {}, {}>;
|
|
96
|
+
invitedAt: t.SQLiteColumn<{
|
|
97
|
+
name: "invited_at";
|
|
98
|
+
tableName: "invitations";
|
|
99
|
+
dataType: "number";
|
|
100
|
+
columnType: "SQLiteInteger";
|
|
101
|
+
data: number;
|
|
102
|
+
driverParam: number;
|
|
103
|
+
notNull: true;
|
|
104
|
+
hasDefault: false;
|
|
105
|
+
isPrimaryKey: false;
|
|
106
|
+
isAutoincrement: false;
|
|
107
|
+
hasRuntimeDefault: false;
|
|
108
|
+
enumValues: undefined;
|
|
109
|
+
baseColumn: never;
|
|
110
|
+
identity: undefined;
|
|
111
|
+
generated: undefined;
|
|
112
|
+
}, {}, {}>;
|
|
113
|
+
role: t.SQLiteColumn<{
|
|
114
|
+
name: "role";
|
|
115
|
+
tableName: "invitations";
|
|
116
|
+
dataType: "string";
|
|
117
|
+
columnType: "SQLiteText";
|
|
118
|
+
data: "guest" | "user" | "admin";
|
|
119
|
+
driverParam: string;
|
|
120
|
+
notNull: true;
|
|
121
|
+
hasDefault: true;
|
|
122
|
+
isPrimaryKey: false;
|
|
123
|
+
isAutoincrement: false;
|
|
124
|
+
hasRuntimeDefault: false;
|
|
125
|
+
enumValues: [string, ...string[]];
|
|
126
|
+
baseColumn: never;
|
|
127
|
+
identity: undefined;
|
|
128
|
+
generated: undefined;
|
|
129
|
+
}, {}, {
|
|
130
|
+
length: undefined;
|
|
131
|
+
$type: "guest" | "user" | "admin";
|
|
132
|
+
}>;
|
|
133
|
+
status: t.SQLiteColumn<{
|
|
134
|
+
name: "status";
|
|
135
|
+
tableName: "invitations";
|
|
136
|
+
dataType: "string";
|
|
137
|
+
columnType: "SQLiteText";
|
|
138
|
+
data: "pending" | "accepted" | "expired";
|
|
139
|
+
driverParam: string;
|
|
140
|
+
notNull: false;
|
|
141
|
+
hasDefault: true;
|
|
142
|
+
isPrimaryKey: false;
|
|
143
|
+
isAutoincrement: false;
|
|
144
|
+
hasRuntimeDefault: false;
|
|
145
|
+
enumValues: [string, ...string[]];
|
|
146
|
+
baseColumn: never;
|
|
147
|
+
identity: undefined;
|
|
148
|
+
generated: undefined;
|
|
149
|
+
}, {}, {
|
|
150
|
+
length: undefined;
|
|
151
|
+
$type: "pending" | "accepted" | "expired";
|
|
152
|
+
}>;
|
|
153
|
+
};
|
|
154
|
+
dialect: "sqlite";
|
|
155
|
+
}>;
|
|
156
|
+
export type Invitation = typeof invitations.$inferSelect;
|
|
157
|
+
export type NewInvitation = typeof invitations.$inferInsert;
|
|
158
|
+
//# sourceMappingURL=invitations.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitations.schema.d.ts","sourceRoot":"","sources":["../../../src/lib/schemas/invitations.schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,yBAAyB,CAAC;AAI7C,eAAO,MAAM,oBAAoB,gBAAgB,CAAC;AAElD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAetB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,OAAO,WAAW,CAAC,YAAY,CAAC;AACzD,MAAM,MAAM,aAAa,GAAG,OAAO,WAAW,CAAC,YAAY,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.invitations = exports.InvitationsTableName = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const sqlite_core_1 = require("drizzle-orm/sqlite-core");
|
|
6
|
+
const t = tslib_1.__importStar(require("drizzle-orm/sqlite-core"));
|
|
7
|
+
const shared_backend_data_access_users_1 = require("@open-kingdom/shared-backend-data-access-users");
|
|
8
|
+
exports.InvitationsTableName = 'invitations';
|
|
9
|
+
exports.invitations = (0, sqlite_core_1.sqliteTable)(exports.InvitationsTableName, {
|
|
10
|
+
id: t.int().primaryKey({ autoIncrement: true }),
|
|
11
|
+
email: t.text().notNull(),
|
|
12
|
+
token: t.text().notNull().unique(),
|
|
13
|
+
tokenExpiry: t.int('token_expiry').notNull(),
|
|
14
|
+
invitedBy: t
|
|
15
|
+
.int('invited_by')
|
|
16
|
+
.notNull()
|
|
17
|
+
.references(() => shared_backend_data_access_users_1.users.id),
|
|
18
|
+
invitedAt: t.int('invited_at').notNull(),
|
|
19
|
+
role: t.text().$type().notNull().default('guest'),
|
|
20
|
+
status: t
|
|
21
|
+
.text()
|
|
22
|
+
.$type()
|
|
23
|
+
.default('pending'),
|
|
24
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as t from 'drizzle-orm/sqlite-core';
|
|
2
|
+
export declare const UserRolesTableName = "user_roles";
|
|
3
|
+
export declare const userRoles: t.SQLiteTableWithColumns<{
|
|
4
|
+
name: "user_roles";
|
|
5
|
+
schema: undefined;
|
|
6
|
+
columns: {
|
|
7
|
+
id: t.SQLiteColumn<{
|
|
8
|
+
name: "id";
|
|
9
|
+
tableName: "user_roles";
|
|
10
|
+
dataType: "number";
|
|
11
|
+
columnType: "SQLiteInteger";
|
|
12
|
+
data: number;
|
|
13
|
+
driverParam: number;
|
|
14
|
+
notNull: true;
|
|
15
|
+
hasDefault: true;
|
|
16
|
+
isPrimaryKey: true;
|
|
17
|
+
isAutoincrement: false;
|
|
18
|
+
hasRuntimeDefault: false;
|
|
19
|
+
enumValues: undefined;
|
|
20
|
+
baseColumn: never;
|
|
21
|
+
identity: undefined;
|
|
22
|
+
generated: undefined;
|
|
23
|
+
}, {}, {}>;
|
|
24
|
+
userId: t.SQLiteColumn<{
|
|
25
|
+
name: "user_id";
|
|
26
|
+
tableName: "user_roles";
|
|
27
|
+
dataType: "number";
|
|
28
|
+
columnType: "SQLiteInteger";
|
|
29
|
+
data: number;
|
|
30
|
+
driverParam: number;
|
|
31
|
+
notNull: true;
|
|
32
|
+
hasDefault: false;
|
|
33
|
+
isPrimaryKey: false;
|
|
34
|
+
isAutoincrement: false;
|
|
35
|
+
hasRuntimeDefault: false;
|
|
36
|
+
enumValues: undefined;
|
|
37
|
+
baseColumn: never;
|
|
38
|
+
identity: undefined;
|
|
39
|
+
generated: undefined;
|
|
40
|
+
}, {}, {}>;
|
|
41
|
+
role: t.SQLiteColumn<{
|
|
42
|
+
name: "role";
|
|
43
|
+
tableName: "user_roles";
|
|
44
|
+
dataType: "string";
|
|
45
|
+
columnType: "SQLiteText";
|
|
46
|
+
data: "guest" | "user" | "admin";
|
|
47
|
+
driverParam: string;
|
|
48
|
+
notNull: true;
|
|
49
|
+
hasDefault: true;
|
|
50
|
+
isPrimaryKey: false;
|
|
51
|
+
isAutoincrement: false;
|
|
52
|
+
hasRuntimeDefault: false;
|
|
53
|
+
enumValues: [string, ...string[]];
|
|
54
|
+
baseColumn: never;
|
|
55
|
+
identity: undefined;
|
|
56
|
+
generated: undefined;
|
|
57
|
+
}, {}, {
|
|
58
|
+
length: undefined;
|
|
59
|
+
$type: "guest" | "user" | "admin";
|
|
60
|
+
}>;
|
|
61
|
+
assignedAt: t.SQLiteColumn<{
|
|
62
|
+
name: "assigned_at";
|
|
63
|
+
tableName: "user_roles";
|
|
64
|
+
dataType: "number";
|
|
65
|
+
columnType: "SQLiteInteger";
|
|
66
|
+
data: number;
|
|
67
|
+
driverParam: number;
|
|
68
|
+
notNull: true;
|
|
69
|
+
hasDefault: false;
|
|
70
|
+
isPrimaryKey: false;
|
|
71
|
+
isAutoincrement: false;
|
|
72
|
+
hasRuntimeDefault: false;
|
|
73
|
+
enumValues: undefined;
|
|
74
|
+
baseColumn: never;
|
|
75
|
+
identity: undefined;
|
|
76
|
+
generated: undefined;
|
|
77
|
+
}, {}, {}>;
|
|
78
|
+
assignedBy: t.SQLiteColumn<{
|
|
79
|
+
name: "assigned_by";
|
|
80
|
+
tableName: "user_roles";
|
|
81
|
+
dataType: "number";
|
|
82
|
+
columnType: "SQLiteInteger";
|
|
83
|
+
data: number;
|
|
84
|
+
driverParam: number;
|
|
85
|
+
notNull: false;
|
|
86
|
+
hasDefault: false;
|
|
87
|
+
isPrimaryKey: false;
|
|
88
|
+
isAutoincrement: false;
|
|
89
|
+
hasRuntimeDefault: false;
|
|
90
|
+
enumValues: undefined;
|
|
91
|
+
baseColumn: never;
|
|
92
|
+
identity: undefined;
|
|
93
|
+
generated: undefined;
|
|
94
|
+
}, {}, {}>;
|
|
95
|
+
};
|
|
96
|
+
dialect: "sqlite";
|
|
97
|
+
}>;
|
|
98
|
+
export type UserRole = typeof userRoles.$inferSelect;
|
|
99
|
+
export type NewUserRole = typeof userRoles.$inferInsert;
|
|
100
|
+
//# sourceMappingURL=user-roles.schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-roles.schema.d.ts","sourceRoot":"","sources":["../../../src/lib/schemas/user-roles.schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,CAAC,MAAM,yBAAyB,CAAC;AAI7C,eAAO,MAAM,kBAAkB,eAAe,CAAC;AAE/C,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EASpB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,SAAS,CAAC,YAAY,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,OAAO,SAAS,CAAC,YAAY,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.userRoles = exports.UserRolesTableName = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const sqlite_core_1 = require("drizzle-orm/sqlite-core");
|
|
6
|
+
const t = tslib_1.__importStar(require("drizzle-orm/sqlite-core"));
|
|
7
|
+
const shared_backend_data_access_users_1 = require("@open-kingdom/shared-backend-data-access-users");
|
|
8
|
+
exports.UserRolesTableName = 'user_roles';
|
|
9
|
+
exports.userRoles = (0, sqlite_core_1.sqliteTable)(exports.UserRolesTableName, {
|
|
10
|
+
id: t.int().primaryKey({ autoIncrement: true }),
|
|
11
|
+
userId: t
|
|
12
|
+
.int('user_id')
|
|
13
|
+
.notNull()
|
|
14
|
+
.references(() => shared_backend_data_access_users_1.users.id),
|
|
15
|
+
role: t.text().$type().notNull().default('guest'),
|
|
16
|
+
assignedAt: t.int('assigned_at').notNull(),
|
|
17
|
+
assignedBy: t.int('assigned_by').references(() => shared_backend_data_access_users_1.users.id),
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
|
2
|
+
import { UsersService, User, users, UsersTableName } from '@open-kingdom/shared-backend-data-access-users';
|
|
3
|
+
import { invitations, Invitation, InvitationsTableName } from '../schemas/invitations.schema';
|
|
4
|
+
import type { UserManagementModuleOptions, EmailSender, Role, ValidationResult } from '../types';
|
|
5
|
+
export type InvitationResponse = Omit<Invitation, 'token'>;
|
|
6
|
+
type Schema = {
|
|
7
|
+
[UsersTableName]: typeof users;
|
|
8
|
+
[InvitationsTableName]: typeof invitations;
|
|
9
|
+
};
|
|
10
|
+
export declare class InvitationsService {
|
|
11
|
+
private readonly db;
|
|
12
|
+
private readonly options;
|
|
13
|
+
private readonly usersService;
|
|
14
|
+
private readonly emailSender?;
|
|
15
|
+
private readonly logger;
|
|
16
|
+
constructor(db: BetterSQLite3Database<Schema>, options: UserManagementModuleOptions, usersService: UsersService, emailSender?: EmailSender | undefined);
|
|
17
|
+
invite(email: string, role: Role, invitedById: number): Promise<InvitationResponse>;
|
|
18
|
+
validate(token: string): Promise<ValidationResult>;
|
|
19
|
+
accept(token: string, password: string, firstName?: string, lastName?: string): Promise<User>;
|
|
20
|
+
private ensureUserDoesNotExist;
|
|
21
|
+
private ensureNoPendingInvitation;
|
|
22
|
+
private isExpired;
|
|
23
|
+
private findByToken;
|
|
24
|
+
private markAsExpired;
|
|
25
|
+
private markAsAccepted;
|
|
26
|
+
private get expiryDays();
|
|
27
|
+
private generateToken;
|
|
28
|
+
private sendInvitationEmail;
|
|
29
|
+
}
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=invitations.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitations.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/invitations.service.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAKnE,OAAO,EACL,YAAY,EACZ,IAAI,EACJ,KAAK,EACL,cAAc,EACf,MAAM,gDAAgD,CAAC;AACxD,OAAO,EACL,WAAW,EACX,UAAU,EACV,oBAAoB,EACrB,MAAM,+BAA+B,CAAC;AAUvC,OAAO,KAAK,EACV,2BAA2B,EAC3B,WAAW,EACX,IAAI,EACJ,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAE3D,KAAK,MAAM,GAAG;IACZ,CAAC,cAAc,CAAC,EAAE,OAAO,KAAK,CAAC;IAC/B,CAAC,oBAAoB,CAAC,EAAE,OAAO,WAAW,CAAC;CAC5C,CAAC;AAKF,qBACa,kBAAkB;IAIX,OAAO,CAAC,QAAQ,CAAC,EAAE;IAEnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IACK,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAPjE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAG3B,EAAE,EAAE,qBAAqB,CAAC,MAAM,CAAC,EAEjD,OAAO,EAAE,2BAA2B,EACpC,YAAY,EAAE,YAAY,EACQ,WAAW,CAAC,EAAE,WAAW,YAAA;IAGxE,MAAM,CACV,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAqCxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAmBlD,MAAM,CACV,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;YAmBF,sBAAsB;YAQtB,yBAAyB;IAevC,OAAO,CAAC,SAAS;YAIH,WAAW;YAMX,aAAa;YAOb,cAAc;IAO5B,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,CAAC,aAAa;YAUP,mBAAmB;CAyBlC"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var InvitationsService_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.InvitationsService = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const better_sqlite3_1 = require("drizzle-orm/better-sqlite3");
|
|
8
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const shared_poly_util_constants_1 = require("@open-kingdom/shared-poly-util-constants");
|
|
11
|
+
const shared_backend_data_access_users_1 = require("@open-kingdom/shared-backend-data-access-users");
|
|
12
|
+
const invitations_schema_1 = require("../schemas/invitations.schema");
|
|
13
|
+
const types_1 = require("../types");
|
|
14
|
+
const templates_1 = require("../templates");
|
|
15
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
16
|
+
const DEFAULT_EXPIRY_DAYS = 7;
|
|
17
|
+
let InvitationsService = InvitationsService_1 = class InvitationsService {
|
|
18
|
+
constructor(db, options, usersService, emailSender) {
|
|
19
|
+
this.db = db;
|
|
20
|
+
this.options = options;
|
|
21
|
+
this.usersService = usersService;
|
|
22
|
+
this.emailSender = emailSender;
|
|
23
|
+
this.logger = new common_1.Logger(InvitationsService_1.name);
|
|
24
|
+
}
|
|
25
|
+
async invite(email, role, invitedById) {
|
|
26
|
+
await this.ensureUserDoesNotExist(email);
|
|
27
|
+
await this.ensureNoPendingInvitation(email);
|
|
28
|
+
const { token, expiresAt } = this.generateToken(email);
|
|
29
|
+
await this.db.insert(invitations_schema_1.invitations).values({
|
|
30
|
+
email,
|
|
31
|
+
token,
|
|
32
|
+
tokenExpiry: expiresAt,
|
|
33
|
+
invitedBy: invitedById,
|
|
34
|
+
invitedAt: Date.now(),
|
|
35
|
+
role,
|
|
36
|
+
status: types_1.INVITATION_STATUS.PENDING,
|
|
37
|
+
});
|
|
38
|
+
const invitation = await this.findByToken(token);
|
|
39
|
+
try {
|
|
40
|
+
await this.sendInvitationEmail(email, token);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.logger.error(`Failed to send invitation email to ${email}, rolling back invitation`, error);
|
|
44
|
+
await this.db.delete(invitations_schema_1.invitations).where((0, drizzle_orm_1.eq)(invitations_schema_1.invitations.token, token));
|
|
45
|
+
throw new common_1.BadRequestException('Failed to send invitation email. Please try again.');
|
|
46
|
+
}
|
|
47
|
+
// Never return token - it's only sent via email
|
|
48
|
+
const { token: _token, ...invitationWithoutToken } = invitation;
|
|
49
|
+
return invitationWithoutToken;
|
|
50
|
+
}
|
|
51
|
+
async validate(token) {
|
|
52
|
+
const invitation = await this.findByToken(token);
|
|
53
|
+
if (!invitation || invitation.status !== types_1.INVITATION_STATUS.PENDING) {
|
|
54
|
+
return { valid: false };
|
|
55
|
+
}
|
|
56
|
+
if (this.isExpired(invitation.tokenExpiry)) {
|
|
57
|
+
await this.markAsExpired(invitation.id);
|
|
58
|
+
return { valid: false };
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
valid: true,
|
|
62
|
+
email: invitation.email,
|
|
63
|
+
role: invitation.role,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async accept(token, password, firstName, lastName) {
|
|
67
|
+
const validation = await this.validate(token);
|
|
68
|
+
if (!validation.valid || !validation.email) {
|
|
69
|
+
throw new common_1.BadRequestException('Invalid or expired invitation token');
|
|
70
|
+
}
|
|
71
|
+
const user = await this.usersService.create({
|
|
72
|
+
email: validation.email,
|
|
73
|
+
password,
|
|
74
|
+
firstName: firstName ?? null,
|
|
75
|
+
lastName: lastName ?? null,
|
|
76
|
+
});
|
|
77
|
+
await this.markAsAccepted(token);
|
|
78
|
+
return user;
|
|
79
|
+
}
|
|
80
|
+
async ensureUserDoesNotExist(email) {
|
|
81
|
+
const existingUser = await this.usersService.findOne(email);
|
|
82
|
+
if (existingUser) {
|
|
83
|
+
throw new common_1.BadRequestException('User with this email already exists');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async ensureNoPendingInvitation(email) {
|
|
87
|
+
const existing = await this.db.query.invitations.findFirst({
|
|
88
|
+
where: (0, drizzle_orm_1.eq)(invitations_schema_1.invitations.email, email),
|
|
89
|
+
});
|
|
90
|
+
if (existing?.status === types_1.INVITATION_STATUS.PENDING &&
|
|
91
|
+
!this.isExpired(existing.tokenExpiry)) {
|
|
92
|
+
throw new common_1.BadRequestException('A pending invitation already exists for this email');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
isExpired(tokenExpiry) {
|
|
96
|
+
return tokenExpiry < Date.now();
|
|
97
|
+
}
|
|
98
|
+
async findByToken(token) {
|
|
99
|
+
return this.db.query.invitations.findFirst({
|
|
100
|
+
where: (0, drizzle_orm_1.eq)(invitations_schema_1.invitations.token, token),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async markAsExpired(id) {
|
|
104
|
+
await this.db
|
|
105
|
+
.update(invitations_schema_1.invitations)
|
|
106
|
+
.set({ status: types_1.INVITATION_STATUS.EXPIRED })
|
|
107
|
+
.where((0, drizzle_orm_1.eq)(invitations_schema_1.invitations.id, id));
|
|
108
|
+
}
|
|
109
|
+
async markAsAccepted(token) {
|
|
110
|
+
await this.db
|
|
111
|
+
.update(invitations_schema_1.invitations)
|
|
112
|
+
.set({ status: types_1.INVITATION_STATUS.ACCEPTED })
|
|
113
|
+
.where((0, drizzle_orm_1.eq)(invitations_schema_1.invitations.token, token));
|
|
114
|
+
}
|
|
115
|
+
get expiryDays() {
|
|
116
|
+
return this.options.invitationExpiryDays ?? DEFAULT_EXPIRY_DAYS;
|
|
117
|
+
}
|
|
118
|
+
generateToken(email) {
|
|
119
|
+
const expiresAt = Date.now() + this.expiryDays * MS_PER_DAY;
|
|
120
|
+
const payload = `${email}:${expiresAt}:${(0, crypto_1.randomBytes)(16).toString('hex')}`;
|
|
121
|
+
const token = (0, crypto_1.createHmac)('sha256', this.options.invitationTokenSecret)
|
|
122
|
+
.update(payload)
|
|
123
|
+
.digest('hex');
|
|
124
|
+
return { token, expiresAt };
|
|
125
|
+
}
|
|
126
|
+
async sendInvitationEmail(email, token) {
|
|
127
|
+
const inviteUrl = `${this.options.frontendBaseUrl}/accept-invitation?token=${token}`;
|
|
128
|
+
this.logger.debug(`Invitation for ${email}: ${inviteUrl}`);
|
|
129
|
+
if (!this.emailSender) {
|
|
130
|
+
this.logger.warn('EmailSender not configured - skipping invitation email');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
await this.emailSender.send({
|
|
134
|
+
to: email,
|
|
135
|
+
subject: templates_1.INVITATION_EMAIL_SUBJECT,
|
|
136
|
+
body: (0, templates_1.buildInvitationEmailBody)({
|
|
137
|
+
inviteUrl,
|
|
138
|
+
expiryDays: this.expiryDays,
|
|
139
|
+
}),
|
|
140
|
+
});
|
|
141
|
+
this.logger.log(`Invitation email sent to ${email}`);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
exports.InvitationsService = InvitationsService;
|
|
145
|
+
exports.InvitationsService = InvitationsService = InvitationsService_1 = tslib_1.__decorate([
|
|
146
|
+
(0, common_1.Injectable)(),
|
|
147
|
+
tslib_1.__param(0, (0, common_1.Inject)(shared_poly_util_constants_1.DB_TAG)),
|
|
148
|
+
tslib_1.__param(1, (0, common_1.Inject)(types_1.USER_MANAGEMENT_OPTIONS)),
|
|
149
|
+
tslib_1.__param(3, (0, common_1.Optional)()),
|
|
150
|
+
tslib_1.__param(3, (0, common_1.Inject)(types_1.EMAIL_SENDER)),
|
|
151
|
+
tslib_1.__metadata("design:paramtypes", [better_sqlite3_1.BetterSQLite3Database, Object, shared_backend_data_access_users_1.UsersService, Object])
|
|
152
|
+
], InvitationsService);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { UsersService, User } from '@open-kingdom/shared-backend-data-access-users';
|
|
2
|
+
export type UserWithoutPassword = Omit<User, 'password'>;
|
|
3
|
+
export declare class UserManagementService {
|
|
4
|
+
private readonly usersService;
|
|
5
|
+
constructor(usersService: UsersService);
|
|
6
|
+
findAll(): Promise<UserWithoutPassword[]>;
|
|
7
|
+
findById(id: number): Promise<UserWithoutPassword>;
|
|
8
|
+
delete(id: number, requesterId: number): Promise<void>;
|
|
9
|
+
private excludePassword;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=user-management.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-management.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/user-management.service.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,YAAY,EACZ,IAAI,EACL,MAAM,gDAAgD,CAAC;AAExD,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAEzD,qBACa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAAZ,YAAY,EAAE,YAAY;IAEjD,OAAO,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAKzC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQlD,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa5D,OAAO,CAAC,eAAe;CAIxB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UserManagementService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
const shared_backend_data_access_users_1 = require("@open-kingdom/shared-backend-data-access-users");
|
|
7
|
+
let UserManagementService = class UserManagementService {
|
|
8
|
+
constructor(usersService) {
|
|
9
|
+
this.usersService = usersService;
|
|
10
|
+
}
|
|
11
|
+
async findAll() {
|
|
12
|
+
const users = await this.usersService.findAll();
|
|
13
|
+
return users.map((user) => this.excludePassword(user));
|
|
14
|
+
}
|
|
15
|
+
async findById(id) {
|
|
16
|
+
const user = await this.usersService.findById(id);
|
|
17
|
+
if (!user) {
|
|
18
|
+
throw new common_1.NotFoundException('User not found');
|
|
19
|
+
}
|
|
20
|
+
return this.excludePassword(user);
|
|
21
|
+
}
|
|
22
|
+
async delete(id, requesterId) {
|
|
23
|
+
if (id === requesterId) {
|
|
24
|
+
throw new common_1.ForbiddenException('Cannot delete your own account');
|
|
25
|
+
}
|
|
26
|
+
const user = await this.usersService.findById(id);
|
|
27
|
+
if (!user) {
|
|
28
|
+
throw new common_1.NotFoundException('User not found');
|
|
29
|
+
}
|
|
30
|
+
await this.usersService.delete(id);
|
|
31
|
+
}
|
|
32
|
+
excludePassword(user) {
|
|
33
|
+
const { password: _password, ...userWithoutPassword } = user;
|
|
34
|
+
return userWithoutPassword;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.UserManagementService = UserManagementService;
|
|
38
|
+
exports.UserManagementService = UserManagementService = tslib_1.__decorate([
|
|
39
|
+
(0, common_1.Injectable)(),
|
|
40
|
+
tslib_1.__metadata("design:paramtypes", [shared_backend_data_access_users_1.UsersService])
|
|
41
|
+
], UserManagementService);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/templates/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface InvitationEmailParams {
|
|
2
|
+
inviteUrl: string;
|
|
3
|
+
expiryDays: number;
|
|
4
|
+
}
|
|
5
|
+
export declare const INVITATION_EMAIL_SUBJECT = "You have been invited";
|
|
6
|
+
export declare const buildInvitationEmailBody: (params: InvitationEmailParams) => string;
|
|
7
|
+
//# sourceMappingURL=invitation-email.template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitation-email.template.d.ts","sourceRoot":"","sources":["../../../src/lib/templates/invitation-email.template.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AAEhE,eAAO,MAAM,wBAAwB,GACnC,QAAQ,qBAAqB,KAC5B,MAUF,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildInvitationEmailBody = exports.INVITATION_EMAIL_SUBJECT = void 0;
|
|
4
|
+
exports.INVITATION_EMAIL_SUBJECT = 'You have been invited';
|
|
5
|
+
const buildInvitationEmailBody = (params) => {
|
|
6
|
+
return [
|
|
7
|
+
'You have been invited to join the platform.',
|
|
8
|
+
'',
|
|
9
|
+
'Click the link below to accept the invitation and create your account:',
|
|
10
|
+
'',
|
|
11
|
+
params.inviteUrl,
|
|
12
|
+
'',
|
|
13
|
+
`This invitation will expire in ${params.expiryDays} days.`,
|
|
14
|
+
].join('\n');
|
|
15
|
+
};
|
|
16
|
+
exports.buildInvitationEmailBody = buildInvitationEmailBody;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
export declare const USER_MANAGEMENT_OPTIONS = "USER_MANAGEMENT_OPTIONS";
|
|
3
|
+
export declare const EMAIL_SENDER = "EMAIL_SENDER";
|
|
4
|
+
export interface UserManagementModuleOptions {
|
|
5
|
+
invitationTokenSecret: string;
|
|
6
|
+
invitationExpiryDays?: number;
|
|
7
|
+
frontendBaseUrl: string;
|
|
8
|
+
}
|
|
9
|
+
export interface AuthenticatedRequest extends Request {
|
|
10
|
+
user: {
|
|
11
|
+
id: number;
|
|
12
|
+
email: string;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export type Role = 'guest' | 'user' | 'admin';
|
|
16
|
+
export type InvitationStatus = 'pending' | 'accepted' | 'expired';
|
|
17
|
+
export declare const INVITATION_STATUS: {
|
|
18
|
+
readonly PENDING: "pending";
|
|
19
|
+
readonly ACCEPTED: "accepted";
|
|
20
|
+
readonly EXPIRED: "expired";
|
|
21
|
+
};
|
|
22
|
+
export interface ValidationResult {
|
|
23
|
+
valid: boolean;
|
|
24
|
+
email?: string;
|
|
25
|
+
role?: Role;
|
|
26
|
+
}
|
|
27
|
+
export interface EmailSender {
|
|
28
|
+
send(message: {
|
|
29
|
+
to: string;
|
|
30
|
+
subject: string;
|
|
31
|
+
body: string;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
success: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/lib/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGvC,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AACjE,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAG3C,MAAM,WAAW,2BAA2B;IAC1C,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC;AAGD,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9C,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAElE,eAAO,MAAM,iBAAiB;;;;CAIpB,CAAC;AAEX,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAGD,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,OAAO,EAAE;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACnC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.INVITATION_STATUS = exports.EMAIL_SENDER = exports.USER_MANAGEMENT_OPTIONS = void 0;
|
|
4
|
+
// Injection tokens
|
|
5
|
+
exports.USER_MANAGEMENT_OPTIONS = 'USER_MANAGEMENT_OPTIONS';
|
|
6
|
+
exports.EMAIL_SENDER = 'EMAIL_SENDER';
|
|
7
|
+
exports.INVITATION_STATUS = {
|
|
8
|
+
PENDING: 'pending',
|
|
9
|
+
ACCEPTED: 'accepted',
|
|
10
|
+
EXPIRED: 'expired',
|
|
11
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@open-kingdom/shared-backend-feature-user-management",
|
|
3
|
+
"version": "0.0.2-10",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
"./package.json": "./package.json",
|
|
12
|
+
".": {
|
|
13
|
+
"@open-kingdom/source": "./src/index.ts",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"!**/*.tsbuildinfo"
|
|
22
|
+
],
|
|
23
|
+
"nx": {
|
|
24
|
+
"tags": [
|
|
25
|
+
"scope:shared",
|
|
26
|
+
"type:feature",
|
|
27
|
+
"environment:backend"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"tslib": "^2.3.0",
|
|
32
|
+
"@nestjs/common": "^11.0.0",
|
|
33
|
+
"@nestjs/passport": "^11.0.5",
|
|
34
|
+
"@nestjs/swagger": "^11.2.3",
|
|
35
|
+
"@open-kingdom/shared-backend-data-access-users": "0.0.2-10",
|
|
36
|
+
"@open-kingdom/shared-backend-feature-email": "0.0.2-10",
|
|
37
|
+
"@open-kingdom/shared-poly-util-constants": "0.0.2-10",
|
|
38
|
+
"drizzle-orm": "^0.44.5",
|
|
39
|
+
"express": "5.2.1"
|
|
40
|
+
}
|
|
41
|
+
}
|