@ciscode/authentication-kit 1.1.1 → 1.1.2
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/dist/auth-kit.module.d.ts +7 -0
- package/dist/auth-kit.module.js +50 -0
- package/dist/config/db.config.d.ts +1 -0
- package/dist/config/db.config.js +22 -0
- package/dist/config/passport.config.d.ts +3 -0
- package/dist/config/passport.config.js +272 -0
- package/dist/controllers/admin.controller.d.ts +4 -0
- package/dist/controllers/admin.controller.js +59 -0
- package/dist/controllers/auth.controller.d.ts +23 -0
- package/dist/controllers/auth.controller.js +645 -0
- package/dist/controllers/password-reset.controller.d.ts +8 -0
- package/dist/controllers/password-reset.controller.js +146 -0
- package/dist/controllers/permissions.controller.d.ts +7 -0
- package/dist/controllers/permissions.controller.js +115 -0
- package/dist/controllers/roles.controller.d.ts +7 -0
- package/dist/controllers/roles.controller.js +113 -0
- package/dist/controllers/users.controller.d.ts +8 -0
- package/dist/controllers/users.controller.js +259 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +14 -0
- package/dist/middleware/auth.guard.d.ts +4 -0
- package/dist/middleware/auth.guard.js +39 -0
- package/dist/middleware/authenticate.guard.d.ts +4 -0
- package/dist/middleware/authenticate.guard.js +44 -0
- package/dist/middleware/permission.guard.d.ts +4 -0
- package/dist/middleware/permission.guard.js +52 -0
- package/dist/middleware/tenant.guard.d.ts +4 -0
- package/dist/middleware/tenant.guard.js +39 -0
- package/dist/models/client.model.d.ts +54 -0
- package/dist/models/client.model.js +34 -0
- package/dist/models/permission.model.d.ts +19 -0
- package/dist/models/permission.model.js +17 -0
- package/dist/models/role.model.d.ts +33 -0
- package/dist/models/role.model.js +19 -0
- package/dist/models/tenant.model.d.ts +19 -0
- package/dist/models/tenant.model.js +15 -0
- package/dist/models/user.model.d.ts +63 -0
- package/dist/models/user.model.js +41 -0
- package/dist/standalone.d.ts +1 -0
- package/dist/standalone.js +12 -0
- package/dist/utils/helper.d.ts +1 -0
- package/dist/utils/helper.js +22 -0
- package/package.json +2 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.PasswordResetController = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const node_crypto_1 = require("node:crypto");
|
|
21
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
22
|
+
const nodemailer_1 = __importDefault(require("nodemailer"));
|
|
23
|
+
const user_model_1 = __importDefault(require("../models/user.model"));
|
|
24
|
+
const client_model_1 = __importDefault(require("../models/client.model"));
|
|
25
|
+
const ACCOUNT_TYPES = ['user', 'client'];
|
|
26
|
+
const isAccountType = (value) => ACCOUNT_TYPES.includes(value);
|
|
27
|
+
const getModel = (type) => (type === 'user' ? user_model_1.default : client_model_1.default);
|
|
28
|
+
let PasswordResetController = class PasswordResetController {
|
|
29
|
+
async requestPasswordReset(req, res) {
|
|
30
|
+
try {
|
|
31
|
+
const { email, type } = req.body;
|
|
32
|
+
if (!email || !type) {
|
|
33
|
+
return res.status(400).json({ message: 'Email and type are required.' });
|
|
34
|
+
}
|
|
35
|
+
if (!isAccountType(type)) {
|
|
36
|
+
return res.status(400).json({ message: 'Invalid account type.' });
|
|
37
|
+
}
|
|
38
|
+
const Model = getModel(type);
|
|
39
|
+
const account = await Model.findOne({ email });
|
|
40
|
+
if (!account) {
|
|
41
|
+
return res.status(200).json({
|
|
42
|
+
message: 'If that email address is in our system, a password reset link has been sent.'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const token = (0, node_crypto_1.randomBytes)(20).toString('hex');
|
|
46
|
+
account.resetPasswordToken = token;
|
|
47
|
+
account.resetPasswordExpires = Date.now() + 3600000;
|
|
48
|
+
await account.save();
|
|
49
|
+
const transporter = nodemailer_1.default.createTransport({
|
|
50
|
+
host: process.env.SMTP_HOST,
|
|
51
|
+
port: parseInt(process.env.SMTP_PORT, 10),
|
|
52
|
+
secure: process.env.SMTP_SECURE === 'true',
|
|
53
|
+
auth: {
|
|
54
|
+
user: process.env.SMTP_USER,
|
|
55
|
+
pass: process.env.SMTP_PASS
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const resetUrl = `${process.env.FRONTEND_URL}/reset-password?token=${token}&type=${type}`;
|
|
59
|
+
const mailOptions = {
|
|
60
|
+
from: process.env.FROM_EMAIL,
|
|
61
|
+
to: account.email,
|
|
62
|
+
subject: 'Password Reset',
|
|
63
|
+
text: `You are receiving this email because you (or someone else) requested a password reset.
|
|
64
|
+
Please click the link below, or paste it into your browser:
|
|
65
|
+
${resetUrl}
|
|
66
|
+
|
|
67
|
+
If you did not request this, please ignore this email.
|
|
68
|
+
This link will expire in 1 hour.`
|
|
69
|
+
};
|
|
70
|
+
await transporter.sendMail(mailOptions);
|
|
71
|
+
return res.status(200).json({
|
|
72
|
+
message: 'If that email address is in our system, a password reset link has been sent.'
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.error('Error in requestPasswordReset:', error);
|
|
77
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async resetPassword(req, res) {
|
|
81
|
+
try {
|
|
82
|
+
const { token, newPassword, type } = req.body;
|
|
83
|
+
if (!token || !newPassword || !type) {
|
|
84
|
+
return res.status(400).json({ message: 'Token, new password, and type are required.' });
|
|
85
|
+
}
|
|
86
|
+
if (!isAccountType(type)) {
|
|
87
|
+
return res.status(400).json({ message: 'Invalid account type.' });
|
|
88
|
+
}
|
|
89
|
+
const Model = getModel(type);
|
|
90
|
+
const account = await Model.findOne({
|
|
91
|
+
resetPasswordToken: token,
|
|
92
|
+
resetPasswordExpires: { $gt: Date.now() }
|
|
93
|
+
});
|
|
94
|
+
if (!account) {
|
|
95
|
+
return res.status(400).json({ message: 'Invalid or expired token.' });
|
|
96
|
+
}
|
|
97
|
+
const salt = await bcryptjs_1.default.genSalt(10);
|
|
98
|
+
account.password = await bcryptjs_1.default.hash(newPassword, salt);
|
|
99
|
+
account.resetPasswordToken = undefined;
|
|
100
|
+
account.resetPasswordExpires = undefined;
|
|
101
|
+
await account.save();
|
|
102
|
+
return res.status(200).json({ message: 'Password has been reset successfully.' });
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error('Error in resetPassword:', error);
|
|
106
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
forgotPassword(req, res) {
|
|
110
|
+
return this.requestPasswordReset(req, res);
|
|
111
|
+
}
|
|
112
|
+
requestPasswordResetRoute(req, res) {
|
|
113
|
+
return this.requestPasswordReset(req, res);
|
|
114
|
+
}
|
|
115
|
+
resetPasswordRoute(req, res) {
|
|
116
|
+
return this.resetPassword(req, res);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
exports.PasswordResetController = PasswordResetController;
|
|
120
|
+
__decorate([
|
|
121
|
+
(0, common_1.Post)('forgot-password'),
|
|
122
|
+
__param(0, (0, common_1.Req)()),
|
|
123
|
+
__param(1, (0, common_1.Res)()),
|
|
124
|
+
__metadata("design:type", Function),
|
|
125
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
126
|
+
__metadata("design:returntype", void 0)
|
|
127
|
+
], PasswordResetController.prototype, "forgotPassword", null);
|
|
128
|
+
__decorate([
|
|
129
|
+
(0, common_1.Post)('request-password-reset'),
|
|
130
|
+
__param(0, (0, common_1.Req)()),
|
|
131
|
+
__param(1, (0, common_1.Res)()),
|
|
132
|
+
__metadata("design:type", Function),
|
|
133
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
134
|
+
__metadata("design:returntype", void 0)
|
|
135
|
+
], PasswordResetController.prototype, "requestPasswordResetRoute", null);
|
|
136
|
+
__decorate([
|
|
137
|
+
(0, common_1.Post)('reset-password'),
|
|
138
|
+
__param(0, (0, common_1.Req)()),
|
|
139
|
+
__param(1, (0, common_1.Res)()),
|
|
140
|
+
__metadata("design:type", Function),
|
|
141
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
142
|
+
__metadata("design:returntype", void 0)
|
|
143
|
+
], PasswordResetController.prototype, "resetPasswordRoute", null);
|
|
144
|
+
exports.PasswordResetController = PasswordResetController = __decorate([
|
|
145
|
+
(0, common_1.Controller)('api/auth')
|
|
146
|
+
], PasswordResetController);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
export declare class PermissionsController {
|
|
3
|
+
createPermission(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
4
|
+
getPermissions(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
5
|
+
updatePermission(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
6
|
+
deletePermission(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.PermissionsController = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const permission_model_1 = __importDefault(require("../models/permission.model"));
|
|
21
|
+
let PermissionsController = class PermissionsController {
|
|
22
|
+
async createPermission(req, res) {
|
|
23
|
+
try {
|
|
24
|
+
const { name, description } = req.body;
|
|
25
|
+
if (!name) {
|
|
26
|
+
return res.status(400).json({ message: 'Permission name is required.' });
|
|
27
|
+
}
|
|
28
|
+
const newPermission = new permission_model_1.default({ name, description });
|
|
29
|
+
await newPermission.save();
|
|
30
|
+
return res.status(201).json(newPermission);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Error creating permission:', error);
|
|
34
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async getPermissions(req, res) {
|
|
38
|
+
try {
|
|
39
|
+
const { page, limit } = req.query;
|
|
40
|
+
const permissions = await permission_model_1.default.paginate({}, {
|
|
41
|
+
page: parseInt(page, 10) || 1,
|
|
42
|
+
limit: parseInt(limit, 10) || 10
|
|
43
|
+
});
|
|
44
|
+
return res.status(200).json(permissions);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('Error retrieving permissions:', error);
|
|
48
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async updatePermission(req, res) {
|
|
52
|
+
try {
|
|
53
|
+
const { id } = req.params;
|
|
54
|
+
const updatedPermission = await permission_model_1.default.findByIdAndUpdate(id, req.body, { new: true });
|
|
55
|
+
if (!updatedPermission) {
|
|
56
|
+
return res.status(404).json({ message: 'Permission not found.' });
|
|
57
|
+
}
|
|
58
|
+
return res.status(200).json(updatedPermission);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error('Error updating permission:', error);
|
|
62
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async deletePermission(req, res) {
|
|
66
|
+
try {
|
|
67
|
+
const { id } = req.params;
|
|
68
|
+
const deletedPermission = await permission_model_1.default.findByIdAndDelete(id);
|
|
69
|
+
if (!deletedPermission) {
|
|
70
|
+
return res.status(404).json({ message: 'Permission not found.' });
|
|
71
|
+
}
|
|
72
|
+
return res.status(200).json({ message: 'Permission deleted successfully.' });
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error('Error deleting permission:', error);
|
|
76
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
exports.PermissionsController = PermissionsController;
|
|
81
|
+
__decorate([
|
|
82
|
+
(0, common_1.Post)('add-permission'),
|
|
83
|
+
__param(0, (0, common_1.Req)()),
|
|
84
|
+
__param(1, (0, common_1.Res)()),
|
|
85
|
+
__metadata("design:type", Function),
|
|
86
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
87
|
+
__metadata("design:returntype", Promise)
|
|
88
|
+
], PermissionsController.prototype, "createPermission", null);
|
|
89
|
+
__decorate([
|
|
90
|
+
(0, common_1.Get)('get-permission'),
|
|
91
|
+
__param(0, (0, common_1.Req)()),
|
|
92
|
+
__param(1, (0, common_1.Res)()),
|
|
93
|
+
__metadata("design:type", Function),
|
|
94
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
95
|
+
__metadata("design:returntype", Promise)
|
|
96
|
+
], PermissionsController.prototype, "getPermissions", null);
|
|
97
|
+
__decorate([
|
|
98
|
+
(0, common_1.Put)('update-permission/:id'),
|
|
99
|
+
__param(0, (0, common_1.Req)()),
|
|
100
|
+
__param(1, (0, common_1.Res)()),
|
|
101
|
+
__metadata("design:type", Function),
|
|
102
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
103
|
+
__metadata("design:returntype", Promise)
|
|
104
|
+
], PermissionsController.prototype, "updatePermission", null);
|
|
105
|
+
__decorate([
|
|
106
|
+
(0, common_1.Delete)('delete-permission/:id'),
|
|
107
|
+
__param(0, (0, common_1.Req)()),
|
|
108
|
+
__param(1, (0, common_1.Res)()),
|
|
109
|
+
__metadata("design:type", Function),
|
|
110
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
111
|
+
__metadata("design:returntype", Promise)
|
|
112
|
+
], PermissionsController.prototype, "deletePermission", null);
|
|
113
|
+
exports.PermissionsController = PermissionsController = __decorate([
|
|
114
|
+
(0, common_1.Controller)('api/auth/permissions')
|
|
115
|
+
], PermissionsController);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
export declare class RolesController {
|
|
3
|
+
createRole(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
4
|
+
getRoles(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
5
|
+
updateRole(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
6
|
+
deleteRole(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.RolesController = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const role_model_1 = __importDefault(require("../models/role.model"));
|
|
21
|
+
let RolesController = class RolesController {
|
|
22
|
+
async createRole(req, res) {
|
|
23
|
+
try {
|
|
24
|
+
const { tenantId, name, description, permissions } = req.body;
|
|
25
|
+
if (!tenantId || !name) {
|
|
26
|
+
return res.status(400).json({ message: 'tenantId and role name are required.' });
|
|
27
|
+
}
|
|
28
|
+
const newRole = new role_model_1.default({ tenantId, name, description, permissions });
|
|
29
|
+
await newRole.save();
|
|
30
|
+
return res.status(201).json(newRole);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Error creating role:', error);
|
|
34
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async getRoles(req, res) {
|
|
38
|
+
try {
|
|
39
|
+
const { tenantId } = req.params;
|
|
40
|
+
if (!tenantId) {
|
|
41
|
+
return res.status(400).json({ message: 'tenantId is required in the URL.' });
|
|
42
|
+
}
|
|
43
|
+
const roles = await role_model_1.default.paginate({ tenantId }, { page: 1, limit: 100 });
|
|
44
|
+
return res.status(200).json(roles);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error('Error retrieving roles:', error);
|
|
48
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async updateRole(req, res) {
|
|
52
|
+
try {
|
|
53
|
+
const updatedRole = await role_model_1.default.findByIdAndUpdate(req.params.id, req.body, { new: true });
|
|
54
|
+
if (!updatedRole) {
|
|
55
|
+
return res.status(404).json({ message: 'Role not found.' });
|
|
56
|
+
}
|
|
57
|
+
return res.status(200).json(updatedRole);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error('Error updating role:', error);
|
|
61
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async deleteRole(req, res) {
|
|
65
|
+
try {
|
|
66
|
+
const deletedRole = await role_model_1.default.findByIdAndDelete(req.params.id);
|
|
67
|
+
if (!deletedRole) {
|
|
68
|
+
return res.status(404).json({ message: 'Role not found.' });
|
|
69
|
+
}
|
|
70
|
+
return res.status(200).json({ message: 'Role deleted successfully.' });
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.error('Error deleting role:', error);
|
|
74
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
exports.RolesController = RolesController;
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, common_1.Post)(),
|
|
81
|
+
__param(0, (0, common_1.Req)()),
|
|
82
|
+
__param(1, (0, common_1.Res)()),
|
|
83
|
+
__metadata("design:type", Function),
|
|
84
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
85
|
+
__metadata("design:returntype", Promise)
|
|
86
|
+
], RolesController.prototype, "createRole", null);
|
|
87
|
+
__decorate([
|
|
88
|
+
(0, common_1.Get)(':tenantId'),
|
|
89
|
+
__param(0, (0, common_1.Req)()),
|
|
90
|
+
__param(1, (0, common_1.Res)()),
|
|
91
|
+
__metadata("design:type", Function),
|
|
92
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
93
|
+
__metadata("design:returntype", Promise)
|
|
94
|
+
], RolesController.prototype, "getRoles", null);
|
|
95
|
+
__decorate([
|
|
96
|
+
(0, common_1.Put)(':id'),
|
|
97
|
+
__param(0, (0, common_1.Req)()),
|
|
98
|
+
__param(1, (0, common_1.Res)()),
|
|
99
|
+
__metadata("design:type", Function),
|
|
100
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
101
|
+
__metadata("design:returntype", Promise)
|
|
102
|
+
], RolesController.prototype, "updateRole", null);
|
|
103
|
+
__decorate([
|
|
104
|
+
(0, common_1.Delete)(':id'),
|
|
105
|
+
__param(0, (0, common_1.Req)()),
|
|
106
|
+
__param(1, (0, common_1.Res)()),
|
|
107
|
+
__metadata("design:type", Function),
|
|
108
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
109
|
+
__metadata("design:returntype", Promise)
|
|
110
|
+
], RolesController.prototype, "deleteRole", null);
|
|
111
|
+
exports.RolesController = RolesController = __decorate([
|
|
112
|
+
(0, common_1.Controller)('api/auth/roles')
|
|
113
|
+
], RolesController);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Request, Response } from 'express';
|
|
2
|
+
export declare class UsersController {
|
|
3
|
+
createUser(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
4
|
+
updateUser(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
5
|
+
deleteUser(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
6
|
+
createUserInvitation(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
7
|
+
getAllUsers(req: Request, res: Response): Promise<Response<any, Record<string, any>>>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.UsersController = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const user_model_1 = __importDefault(require("../models/user.model"));
|
|
21
|
+
const nodemailer_1 = __importDefault(require("nodemailer"));
|
|
22
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
23
|
+
const node_crypto_1 = require("node:crypto");
|
|
24
|
+
let UsersController = class UsersController {
|
|
25
|
+
async createUser(req, res) {
|
|
26
|
+
try {
|
|
27
|
+
const { email, password, name, tenantId, microsoftId, roles } = req.body;
|
|
28
|
+
if (!email) {
|
|
29
|
+
return res.status(400).json({ message: 'Email is required.' });
|
|
30
|
+
}
|
|
31
|
+
if (!tenantId) {
|
|
32
|
+
return res.status(400).json({ message: 'TenantId is required.' });
|
|
33
|
+
}
|
|
34
|
+
if (!microsoftId && !password) {
|
|
35
|
+
return res.status(400).json({ message: 'Password is required for local login.' });
|
|
36
|
+
}
|
|
37
|
+
const existingUser = await user_model_1.default.findOne({ email, tenantId });
|
|
38
|
+
if (existingUser) {
|
|
39
|
+
return res.status(400).json({ message: 'User with this email already exists.' });
|
|
40
|
+
}
|
|
41
|
+
const salt = await bcryptjs_1.default.genSalt(10);
|
|
42
|
+
const hashedPassword = password ? await bcryptjs_1.default.hash(password, salt) : undefined;
|
|
43
|
+
const status = 'pending';
|
|
44
|
+
const tokenExpiryHours = parseFloat(process.env.EMAIL_TOKEN_EXPIRATION_HOURS || '0') || 24;
|
|
45
|
+
const tokenExpiration = Date.now() + tokenExpiryHours * 60 * 60 * 1000;
|
|
46
|
+
const confirmationToken = (0, node_crypto_1.randomBytes)(20).toString('hex');
|
|
47
|
+
const newUser = new user_model_1.default({
|
|
48
|
+
email,
|
|
49
|
+
password: hashedPassword,
|
|
50
|
+
name,
|
|
51
|
+
tenantId,
|
|
52
|
+
microsoftId,
|
|
53
|
+
roles,
|
|
54
|
+
status,
|
|
55
|
+
resetPasswordToken: confirmationToken,
|
|
56
|
+
resetPasswordExpires: tokenExpiration
|
|
57
|
+
});
|
|
58
|
+
await newUser.save();
|
|
59
|
+
const transporter = nodemailer_1.default.createTransport({
|
|
60
|
+
host: process.env.SMTP_HOST,
|
|
61
|
+
port: parseInt(process.env.SMTP_PORT, 10),
|
|
62
|
+
secure: process.env.SMTP_SECURE === 'true',
|
|
63
|
+
auth: {
|
|
64
|
+
user: process.env.SMTP_USER,
|
|
65
|
+
pass: process.env.SMTP_PASS
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const confirmationUrl = `${process.env.FRONTEND_URL}/confirm-email?token=${confirmationToken}&email=${encodeURIComponent(email)}`;
|
|
69
|
+
const mailOptions = {
|
|
70
|
+
from: process.env.FROM_EMAIL,
|
|
71
|
+
to: email,
|
|
72
|
+
subject: 'Confirm Your Email Address',
|
|
73
|
+
text: `Hello,
|
|
74
|
+
|
|
75
|
+
Thank you for registering. Please confirm your account by clicking the link below:
|
|
76
|
+
|
|
77
|
+
${confirmationUrl}
|
|
78
|
+
|
|
79
|
+
This link will expire in ${tokenExpiryHours} hour(s).
|
|
80
|
+
|
|
81
|
+
If you did not initiate this registration, please ignore this email.
|
|
82
|
+
|
|
83
|
+
Thank you.`
|
|
84
|
+
};
|
|
85
|
+
await transporter.sendMail(mailOptions);
|
|
86
|
+
return res.status(201).json({ message: 'User created and confirmation email sent successfully.', user: newUser });
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.error('Error creating user:', error);
|
|
90
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async updateUser(req, res) {
|
|
94
|
+
try {
|
|
95
|
+
const userId = req.params.id;
|
|
96
|
+
if (req.body.password) {
|
|
97
|
+
const salt = await bcryptjs_1.default.genSalt(10);
|
|
98
|
+
req.body.password = await bcryptjs_1.default.hash(req.body.password, salt);
|
|
99
|
+
}
|
|
100
|
+
const updatedUser = await user_model_1.default.findByIdAndUpdate(userId, req.body, { new: true });
|
|
101
|
+
if (!updatedUser) {
|
|
102
|
+
return res.status(404).json({ message: 'User not found.' });
|
|
103
|
+
}
|
|
104
|
+
return res.status(200).json(updatedUser);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
console.error('Error updating user:', error);
|
|
108
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async deleteUser(req, res) {
|
|
112
|
+
try {
|
|
113
|
+
const userId = req.params.id;
|
|
114
|
+
const deletedUser = await user_model_1.default.findByIdAndDelete(userId);
|
|
115
|
+
if (!deletedUser) {
|
|
116
|
+
return res.status(404).json({ message: 'User not found.' });
|
|
117
|
+
}
|
|
118
|
+
return res.status(200).json({ message: 'User deleted successfully.' });
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Error deleting user:', error);
|
|
122
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async createUserInvitation(req, res) {
|
|
126
|
+
try {
|
|
127
|
+
const { email, tenantId, name } = req.body;
|
|
128
|
+
if (!email) {
|
|
129
|
+
return res.status(400).json({ message: 'Email is required.' });
|
|
130
|
+
}
|
|
131
|
+
if (!tenantId) {
|
|
132
|
+
return res.status(400).json({ message: 'TenantId is required.' });
|
|
133
|
+
}
|
|
134
|
+
const existingUser = await user_model_1.default.findOne({ email, tenantId });
|
|
135
|
+
if (existingUser) {
|
|
136
|
+
return res.status(400).json({ message: 'User with this email already exists.' });
|
|
137
|
+
}
|
|
138
|
+
const token = (0, node_crypto_1.randomBytes)(20).toString('hex');
|
|
139
|
+
const tokenExpiration = Date.now() + 24 * 60 * 60 * 1000;
|
|
140
|
+
const newUser = new user_model_1.default({
|
|
141
|
+
email,
|
|
142
|
+
tenantId,
|
|
143
|
+
name,
|
|
144
|
+
resetPasswordToken: token,
|
|
145
|
+
resetPasswordExpires: tokenExpiration
|
|
146
|
+
});
|
|
147
|
+
await newUser.save();
|
|
148
|
+
const transporter = nodemailer_1.default.createTransport({
|
|
149
|
+
host: process.env.SMTP_HOST,
|
|
150
|
+
port: parseInt(process.env.SMTP_PORT, 10),
|
|
151
|
+
secure: process.env.SMTP_SECURE === 'true',
|
|
152
|
+
auth: {
|
|
153
|
+
user: process.env.SMTP_USER,
|
|
154
|
+
pass: process.env.SMTP_PASS
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
const invitationUrl = `${process.env.FRONTEND_URL}/set-password?token=${token}&email=${encodeURIComponent(email)}`;
|
|
158
|
+
const mailOptions = {
|
|
159
|
+
from: process.env.FROM_EMAIL,
|
|
160
|
+
to: email,
|
|
161
|
+
subject: "You're invited: Set up your password",
|
|
162
|
+
text: `Hello,
|
|
163
|
+
|
|
164
|
+
You have been invited to join our platform. Please click on the link below to set your password and complete your registration:
|
|
165
|
+
|
|
166
|
+
${invitationUrl}
|
|
167
|
+
|
|
168
|
+
This link will expire in 24 hours. If you did not request this or believe it to be in error, please ignore this email.
|
|
169
|
+
|
|
170
|
+
Thank you!`
|
|
171
|
+
};
|
|
172
|
+
await transporter.sendMail(mailOptions);
|
|
173
|
+
return res.status(201).json({ message: 'Invitation sent successfully. Please check your email.' });
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
console.error('Error in createUserInvitation:', error);
|
|
177
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
async getAllUsers(req, res) {
|
|
181
|
+
try {
|
|
182
|
+
const filter = {};
|
|
183
|
+
if (req.query.tenantId)
|
|
184
|
+
filter.tenantId = req.query.tenantId;
|
|
185
|
+
if (req.query.email)
|
|
186
|
+
filter.email = req.query.email;
|
|
187
|
+
const page = Math.max(parseInt(req.query.page, 10) || 1, 1);
|
|
188
|
+
const limit = Math.min(parseInt(req.query.limit, 10) || 20, 100);
|
|
189
|
+
const skip = (page - 1) * limit;
|
|
190
|
+
const [totalItems, users] = await Promise.all([
|
|
191
|
+
user_model_1.default.countDocuments(filter),
|
|
192
|
+
user_model_1.default.find(filter)
|
|
193
|
+
.populate({ path: 'roles', select: '-__v' })
|
|
194
|
+
.skip(skip)
|
|
195
|
+
.limit(limit)
|
|
196
|
+
.lean()
|
|
197
|
+
]);
|
|
198
|
+
return res.status(200).json({
|
|
199
|
+
data: users,
|
|
200
|
+
pagination: {
|
|
201
|
+
totalItems,
|
|
202
|
+
limit,
|
|
203
|
+
totalPages: Math.ceil(totalItems / limit) || 1,
|
|
204
|
+
currentPage: page,
|
|
205
|
+
hasNextPage: page * limit < totalItems,
|
|
206
|
+
hasPrevPage: page > 1
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
console.error('Error fetching users:', error);
|
|
212
|
+
return res.status(500).json({ message: 'Server error', error: error.message });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
exports.UsersController = UsersController;
|
|
217
|
+
__decorate([
|
|
218
|
+
(0, common_1.Post)(),
|
|
219
|
+
__param(0, (0, common_1.Req)()),
|
|
220
|
+
__param(1, (0, common_1.Res)()),
|
|
221
|
+
__metadata("design:type", Function),
|
|
222
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
223
|
+
__metadata("design:returntype", Promise)
|
|
224
|
+
], UsersController.prototype, "createUser", null);
|
|
225
|
+
__decorate([
|
|
226
|
+
(0, common_1.Put)(':id'),
|
|
227
|
+
__param(0, (0, common_1.Req)()),
|
|
228
|
+
__param(1, (0, common_1.Res)()),
|
|
229
|
+
__metadata("design:type", Function),
|
|
230
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
231
|
+
__metadata("design:returntype", Promise)
|
|
232
|
+
], UsersController.prototype, "updateUser", null);
|
|
233
|
+
__decorate([
|
|
234
|
+
(0, common_1.Delete)(':id'),
|
|
235
|
+
__param(0, (0, common_1.Req)()),
|
|
236
|
+
__param(1, (0, common_1.Res)()),
|
|
237
|
+
__metadata("design:type", Function),
|
|
238
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
239
|
+
__metadata("design:returntype", Promise)
|
|
240
|
+
], UsersController.prototype, "deleteUser", null);
|
|
241
|
+
__decorate([
|
|
242
|
+
(0, common_1.Post)('invite'),
|
|
243
|
+
__param(0, (0, common_1.Req)()),
|
|
244
|
+
__param(1, (0, common_1.Res)()),
|
|
245
|
+
__metadata("design:type", Function),
|
|
246
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
247
|
+
__metadata("design:returntype", Promise)
|
|
248
|
+
], UsersController.prototype, "createUserInvitation", null);
|
|
249
|
+
__decorate([
|
|
250
|
+
(0, common_1.Get)(),
|
|
251
|
+
__param(0, (0, common_1.Req)()),
|
|
252
|
+
__param(1, (0, common_1.Res)()),
|
|
253
|
+
__metadata("design:type", Function),
|
|
254
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
255
|
+
__metadata("design:returntype", Promise)
|
|
256
|
+
], UsersController.prototype, "getAllUsers", null);
|
|
257
|
+
exports.UsersController = UsersController = __decorate([
|
|
258
|
+
(0, common_1.Controller)('api/users')
|
|
259
|
+
], UsersController);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
export { AuthKitModule } from './auth-kit.module';
|
|
3
|
+
export { AuthenticateGuard } from './middleware/authenticate.guard';
|
|
4
|
+
export { AuthGuard } from './middleware/auth.guard';
|
|
5
|
+
export { TenantGuard } from './middleware/tenant.guard';
|
|
6
|
+
export { hasPermission } from './middleware/permission.guard';
|