@miguelmorales13/nestkit 0.1.0 → 0.3.0
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 +305 -1
- package/dist/auth/auth-user.entity.d.ts +8 -0
- package/dist/auth/auth-user.port.d.ts +16 -0
- package/dist/auth/auth.controller.d.ts +25 -0
- package/dist/auth/auth.dto.d.ts +13 -0
- package/dist/auth/auth.service.d.ts +24 -0
- package/dist/auth/authenticated-user.d.ts +7 -0
- package/dist/auth/current-tenant.decorator.d.ts +2 -0
- package/dist/auth/current-user.decorator.d.ts +1 -0
- package/dist/auth/hash.util.d.ts +2 -0
- package/dist/auth/index.cjs +265 -0
- package/dist/auth/index.d.ts +16 -0
- package/dist/auth/index.js +265 -0
- package/dist/auth/jwt-auth.guard.d.ts +5 -0
- package/dist/auth/require-tenant.guard.d.ts +9 -0
- package/dist/auth/roles.decorator.d.ts +3 -0
- package/dist/auth/roles.guard.d.ts +11 -0
- package/dist/auth/token.service.d.ts +7 -0
- package/dist/bootstrap/index.cjs +11 -0
- package/dist/bootstrap/index.js +3 -2
- package/dist/chunk-2REOCMUD.cjs +16 -0
- package/dist/chunk-3CLYZC3T.cjs +104 -0
- package/dist/chunk-7FQQDWOZ.cjs +73 -0
- package/dist/chunk-7SOM7EZP.cjs +1 -0
- package/dist/chunk-DQYAIQQ5.js +0 -0
- package/dist/chunk-FDNGAYTZ.cjs +39 -0
- package/dist/chunk-KVBQBT3D.cjs +1 -0
- package/dist/chunk-M3EL5O6T.cjs +36 -0
- package/dist/chunk-MR2IFCZE.cjs +1 -0
- package/dist/chunk-O2ZMI3EK.cjs +32 -0
- package/dist/{chunk-HGJX2GPE.js → chunk-ORWJ7LES.js} +1 -1
- package/dist/{chunk-EQXYK6AL.js → chunk-Q45IEPWU.js} +5 -13
- package/dist/chunk-QS2W5XCQ.cjs +12 -0
- package/dist/chunk-R7BVS6CI.cjs +13 -0
- package/dist/chunk-RF75KC63.cjs +50 -0
- package/dist/{chunk-KP7GRCZW.js → chunk-RHNQGTAT.js} +3 -3
- package/dist/chunk-SPTDXUED.cjs +39 -0
- package/dist/chunk-TJHRABML.cjs +29 -0
- package/dist/chunk-V2M75FN3.cjs +40 -0
- package/dist/chunk-YFYHLYHN.js +13 -0
- package/dist/chunk-ZA56XBCK.cjs +20 -0
- package/dist/crud/index.cjs +9 -0
- package/dist/database/mongo/index.cjs +1 -0
- package/dist/database/postgres/index.cjs +11 -0
- package/dist/database/supabase/index.cjs +11 -0
- package/dist/email/nodemailer/index.cjs +40 -0
- package/dist/email/nodemailer/index.d.ts +1 -0
- package/dist/email/nodemailer/index.js +40 -0
- package/dist/email/nodemailer/nodemailer.module.d.ts +4 -0
- package/dist/email/resend/index.cjs +31 -0
- package/dist/email/resend/index.d.ts +1 -0
- package/dist/email/resend/index.js +31 -0
- package/dist/email/resend/resend.module.d.ts +4 -0
- package/dist/entities/index.cjs +7 -0
- package/dist/errors/index.cjs +25 -0
- package/dist/errors/index.js +6 -3
- package/dist/i18n/index.cjs +9 -0
- package/dist/index.cjs +78 -0
- package/dist/index.js +26 -23
- package/dist/response/index.cjs +9 -0
- package/dist/stripe/index.cjs +78 -0
- package/dist/stripe/index.d.ts +3 -0
- package/dist/stripe/index.js +78 -0
- package/dist/stripe/stripe-webhook.controller.d.ts +20 -0
- package/dist/stripe/stripe.module.d.ts +4 -0
- package/dist/telegram/index.cjs +31 -0
- package/dist/telegram/index.d.ts +1 -0
- package/dist/telegram/index.js +31 -0
- package/dist/telegram/telegram.module.d.ts +8 -0
- package/dist/tracking/index.cjs +15 -0
- package/dist/whatsapp/index.cjs +68 -0
- package/dist/whatsapp/index.d.ts +3 -0
- package/dist/whatsapp/index.js +68 -0
- package/dist/whatsapp/whatsapp-client.d.ts +21 -0
- package/dist/whatsapp/whatsapp.module.d.ts +4 -0
- package/package.json +96 -21
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
var _chunkFDNGAYTZcjs = require('../chunk-FDNGAYTZ.cjs');
|
|
6
|
+
require('../chunk-R7BVS6CI.cjs');
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunk2REOCMUDcjs = require('../chunk-2REOCMUD.cjs');
|
|
11
|
+
|
|
12
|
+
// src/auth/hash.util.ts
|
|
13
|
+
var _bcryptjs = require('bcryptjs');
|
|
14
|
+
var SALT_ROUNDS = 10;
|
|
15
|
+
function hashPassword(plain) {
|
|
16
|
+
return _bcryptjs.hash.call(void 0, plain, SALT_ROUNDS);
|
|
17
|
+
}
|
|
18
|
+
function verifyPassword(plain, passwordHash) {
|
|
19
|
+
return _bcryptjs.compare.call(void 0, plain, passwordHash);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/auth/token.service.ts
|
|
23
|
+
var _jsonwebtoken = require('jsonwebtoken'); var _jsonwebtoken2 = _interopRequireDefault(_jsonwebtoken);
|
|
24
|
+
function requireEnv(name) {
|
|
25
|
+
const value = process.env[name];
|
|
26
|
+
if (!value) {
|
|
27
|
+
throw new Error(`TokenService: ${name} environment variable is not set`);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
var TokenService = class {
|
|
32
|
+
signAccessToken(payload) {
|
|
33
|
+
return _jsonwebtoken2.default.sign(payload, requireEnv("JWT_ACCESS_SECRET"), {
|
|
34
|
+
expiresIn: _nullishCoalesce(process.env.JWT_ACCESS_EXPIRES_IN, () => ( "15m"))
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
signRefreshToken(payload) {
|
|
38
|
+
return _jsonwebtoken2.default.sign(payload, requireEnv("JWT_REFRESH_SECRET"), {
|
|
39
|
+
expiresIn: _nullishCoalesce(process.env.JWT_REFRESH_EXPIRES_IN, () => ( "30d"))
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
verifyAccessToken(token) {
|
|
43
|
+
try {
|
|
44
|
+
return _jsonwebtoken2.default.verify(token, requireEnv("JWT_ACCESS_SECRET"));
|
|
45
|
+
} catch (e) {
|
|
46
|
+
throw new (0, _chunkFDNGAYTZcjs.UnauthorizedAppException)("Invalid or expired access token");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
verifyRefreshToken(token) {
|
|
50
|
+
try {
|
|
51
|
+
return _jsonwebtoken2.default.verify(token, requireEnv("JWT_REFRESH_SECRET"));
|
|
52
|
+
} catch (e2) {
|
|
53
|
+
throw new (0, _chunkFDNGAYTZcjs.UnauthorizedAppException)("Invalid or expired refresh token");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/auth/jwt-auth.guard.ts
|
|
59
|
+
var _common = require('@nestjs/common');
|
|
60
|
+
var JwtAuthGuard = class {
|
|
61
|
+
constructor() {
|
|
62
|
+
this.tokens = new TokenService();
|
|
63
|
+
}
|
|
64
|
+
canActivate(context) {
|
|
65
|
+
const req = context.switchToHttp().getRequest();
|
|
66
|
+
const header = req.headers.authorization;
|
|
67
|
+
const token = _optionalChain([header, 'optionalAccess', _2 => _2.startsWith, 'call', _3 => _3("Bearer ")]) ? header.slice("Bearer ".length) : void 0;
|
|
68
|
+
if (!token) {
|
|
69
|
+
throw new (0, _chunkFDNGAYTZcjs.UnauthorizedAppException)("Missing Authorization bearer token");
|
|
70
|
+
}
|
|
71
|
+
req.user = this.tokens.verifyAccessToken(token);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
JwtAuthGuard = exports.JwtAuthGuard = _chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
76
|
+
_common.Injectable.call(void 0, )
|
|
77
|
+
], JwtAuthGuard);
|
|
78
|
+
|
|
79
|
+
// src/auth/roles.decorator.ts
|
|
80
|
+
|
|
81
|
+
var ROLES_KEY = "nestkit:roles";
|
|
82
|
+
var Roles = (...roles) => _common.SetMetadata.call(void 0, ROLES_KEY, roles);
|
|
83
|
+
|
|
84
|
+
// src/auth/roles.guard.ts
|
|
85
|
+
|
|
86
|
+
require('@nestjs/core');
|
|
87
|
+
var RolesGuard = class {
|
|
88
|
+
constructor(reflector) {
|
|
89
|
+
this.reflector = reflector;
|
|
90
|
+
}
|
|
91
|
+
canActivate(context) {
|
|
92
|
+
const required = this.reflector.getAllAndOverride(ROLES_KEY, [
|
|
93
|
+
context.getHandler(),
|
|
94
|
+
context.getClass()
|
|
95
|
+
]);
|
|
96
|
+
if (!required || required.length === 0) return true;
|
|
97
|
+
const req = context.switchToHttp().getRequest();
|
|
98
|
+
const has = _nullishCoalesce(_optionalChain([req, 'access', _4 => _4.user, 'optionalAccess', _5 => _5.roles, 'access', _6 => _6.some, 'call', _7 => _7((role) => required.includes(role))]), () => ( false));
|
|
99
|
+
if (!has) {
|
|
100
|
+
throw new (0, _chunkFDNGAYTZcjs.ForbiddenAppException)("Insufficient role");
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
RolesGuard = exports.RolesGuard = _chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
106
|
+
_common.Injectable.call(void 0, )
|
|
107
|
+
], RolesGuard);
|
|
108
|
+
|
|
109
|
+
// src/auth/current-user.decorator.ts
|
|
110
|
+
|
|
111
|
+
var CurrentUser = _common.createParamDecorator.call(void 0,
|
|
112
|
+
(_, ctx) => ctx.switchToHttp().getRequest().user
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// src/auth/current-tenant.decorator.ts
|
|
116
|
+
|
|
117
|
+
var CurrentTenant = _common.createParamDecorator.call(void 0,
|
|
118
|
+
(_, ctx) => _optionalChain([ctx, 'access', _8 => _8.switchToHttp, 'call', _9 => _9(), 'access', _10 => _10.getRequest, 'call', _11 => _11(), 'access', _12 => _12.user, 'optionalAccess', _13 => _13.tenantId])
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// src/auth/require-tenant.guard.ts
|
|
122
|
+
|
|
123
|
+
var RequireTenantGuard = class {
|
|
124
|
+
canActivate(context) {
|
|
125
|
+
const req = context.switchToHttp().getRequest();
|
|
126
|
+
if (!_optionalChain([req, 'access', _14 => _14.user, 'optionalAccess', _15 => _15.tenantId])) {
|
|
127
|
+
throw new (0, _chunkFDNGAYTZcjs.ForbiddenAppException)("This action requires a company account");
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
RequireTenantGuard = exports.RequireTenantGuard = _chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
133
|
+
_common.Injectable.call(void 0, )
|
|
134
|
+
], RequireTenantGuard);
|
|
135
|
+
|
|
136
|
+
// src/auth/auth.dto.ts
|
|
137
|
+
var _classvalidator = require('class-validator');
|
|
138
|
+
var RegisterDto = class {
|
|
139
|
+
};
|
|
140
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
141
|
+
_classvalidator.IsEmail.call(void 0, )
|
|
142
|
+
], RegisterDto.prototype, "email", 2);
|
|
143
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
144
|
+
_classvalidator.IsString.call(void 0, ),
|
|
145
|
+
_classvalidator.MinLength.call(void 0, 8)
|
|
146
|
+
], RegisterDto.prototype, "password", 2);
|
|
147
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
148
|
+
_classvalidator.IsOptional.call(void 0, ),
|
|
149
|
+
_classvalidator.IsString.call(void 0, )
|
|
150
|
+
], RegisterDto.prototype, "tenantId", 2);
|
|
151
|
+
var LoginDto = class {
|
|
152
|
+
};
|
|
153
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
154
|
+
_classvalidator.IsEmail.call(void 0, )
|
|
155
|
+
], LoginDto.prototype, "email", 2);
|
|
156
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
157
|
+
_classvalidator.IsString.call(void 0, )
|
|
158
|
+
], LoginDto.prototype, "password", 2);
|
|
159
|
+
var RefreshDto = class {
|
|
160
|
+
};
|
|
161
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
162
|
+
_classvalidator.IsString.call(void 0, )
|
|
163
|
+
], RefreshDto.prototype, "refreshToken", 2);
|
|
164
|
+
|
|
165
|
+
// src/auth/auth.service.ts
|
|
166
|
+
var BaseAuthService = class {
|
|
167
|
+
constructor(users, tokens = new TokenService()) {
|
|
168
|
+
this.users = users;
|
|
169
|
+
this.tokens = tokens;
|
|
170
|
+
}
|
|
171
|
+
async register(data) {
|
|
172
|
+
const existing = await this.users.findByEmail(data.email);
|
|
173
|
+
if (existing) {
|
|
174
|
+
throw new (0, _chunkFDNGAYTZcjs.ConflictAppException)("Email already registered", { email: data.email }, "EMAIL_TAKEN");
|
|
175
|
+
}
|
|
176
|
+
const passwordHash = await hashPassword(data.password);
|
|
177
|
+
const user = await this.users.create({
|
|
178
|
+
email: data.email,
|
|
179
|
+
passwordHash,
|
|
180
|
+
tenantId: data.tenantId,
|
|
181
|
+
roles: ["user"]
|
|
182
|
+
});
|
|
183
|
+
return { user, ...this.issueTokens(user) };
|
|
184
|
+
}
|
|
185
|
+
async login(email, password) {
|
|
186
|
+
const user = await this.users.findByEmail(email);
|
|
187
|
+
if (!user || !await verifyPassword(password, user.passwordHash)) {
|
|
188
|
+
throw new (0, _chunkFDNGAYTZcjs.UnauthorizedAppException)("Invalid credentials");
|
|
189
|
+
}
|
|
190
|
+
return { user, ...this.issueTokens(user) };
|
|
191
|
+
}
|
|
192
|
+
async refresh(refreshToken) {
|
|
193
|
+
const payload = this.tokens.verifyRefreshToken(refreshToken);
|
|
194
|
+
const user = await this.users.findById(payload.sub);
|
|
195
|
+
if (!user) {
|
|
196
|
+
throw new (0, _chunkFDNGAYTZcjs.UnauthorizedAppException)("User no longer exists");
|
|
197
|
+
}
|
|
198
|
+
return this.issueTokens(user);
|
|
199
|
+
}
|
|
200
|
+
issueTokens(user) {
|
|
201
|
+
const payload = {
|
|
202
|
+
sub: user.id,
|
|
203
|
+
email: user.email,
|
|
204
|
+
tenantId: user.tenantId,
|
|
205
|
+
roles: user.roles
|
|
206
|
+
};
|
|
207
|
+
return {
|
|
208
|
+
accessToken: this.tokens.signAccessToken(payload),
|
|
209
|
+
refreshToken: this.tokens.signRefreshToken(payload)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// src/auth/auth.controller.ts
|
|
215
|
+
|
|
216
|
+
function createAuthController(serviceToken, options = {}) {
|
|
217
|
+
let AuthControllerHost = class {
|
|
218
|
+
constructor(service) {
|
|
219
|
+
this.service = service;
|
|
220
|
+
}
|
|
221
|
+
register(body) {
|
|
222
|
+
return this.service.register(body);
|
|
223
|
+
}
|
|
224
|
+
login(body) {
|
|
225
|
+
return this.service.login(body.email, body.password);
|
|
226
|
+
}
|
|
227
|
+
refresh(body) {
|
|
228
|
+
return this.service.refresh(body.refreshToken);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
232
|
+
_common.Post.call(void 0, "register"),
|
|
233
|
+
_chunk2REOCMUDcjs.__decorateParam.call(void 0, 0, _common.Body.call(void 0, ))
|
|
234
|
+
], AuthControllerHost.prototype, "register", 1);
|
|
235
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
236
|
+
_common.Post.call(void 0, "login"),
|
|
237
|
+
_chunk2REOCMUDcjs.__decorateParam.call(void 0, 0, _common.Body.call(void 0, ))
|
|
238
|
+
], AuthControllerHost.prototype, "login", 1);
|
|
239
|
+
_chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
240
|
+
_common.Post.call(void 0, "refresh"),
|
|
241
|
+
_chunk2REOCMUDcjs.__decorateParam.call(void 0, 0, _common.Body.call(void 0, ))
|
|
242
|
+
], AuthControllerHost.prototype, "refresh", 1);
|
|
243
|
+
AuthControllerHost = _chunk2REOCMUDcjs.__decorateClass.call(void 0, [
|
|
244
|
+
_common.Controller.call(void 0, _nullishCoalesce(options.path, () => ( "auth"))),
|
|
245
|
+
_chunk2REOCMUDcjs.__decorateParam.call(void 0, 0, _common.Inject.call(void 0, serviceToken))
|
|
246
|
+
], AuthControllerHost);
|
|
247
|
+
return AuthControllerHost;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
exports.BaseAuthService = BaseAuthService; exports.CurrentTenant = CurrentTenant; exports.CurrentUser = CurrentUser; exports.JwtAuthGuard = JwtAuthGuard; exports.LoginDto = LoginDto; exports.ROLES_KEY = ROLES_KEY; exports.RefreshDto = RefreshDto; exports.RegisterDto = RegisterDto; exports.RequireTenantGuard = RequireTenantGuard; exports.Roles = Roles; exports.RolesGuard = RolesGuard; exports.TokenService = TokenService; exports.createAuthController = createAuthController; exports.hashPassword = hashPassword; exports.verifyPassword = verifyPassword;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type { AuthUser } from './auth-user.entity.js';
|
|
2
|
+
export type { AuthUserPort } from './auth-user.port.js';
|
|
3
|
+
export type { AuthenticatedUser } from './authenticated-user.js';
|
|
4
|
+
export { hashPassword, verifyPassword } from './hash.util.js';
|
|
5
|
+
export { TokenService } from './token.service.js';
|
|
6
|
+
export { JwtAuthGuard } from './jwt-auth.guard.js';
|
|
7
|
+
export { Roles, ROLES_KEY } from './roles.decorator.js';
|
|
8
|
+
export { RolesGuard } from './roles.guard.js';
|
|
9
|
+
export { CurrentUser } from './current-user.decorator.js';
|
|
10
|
+
export { CurrentTenant } from './current-tenant.decorator.js';
|
|
11
|
+
export { RequireTenantGuard } from './require-tenant.guard.js';
|
|
12
|
+
export { RegisterDto, LoginDto, RefreshDto } from './auth.dto.js';
|
|
13
|
+
export { BaseAuthService } from './auth.service.js';
|
|
14
|
+
export type { AuthTokens } from './auth.service.js';
|
|
15
|
+
export { createAuthController } from './auth.controller.js';
|
|
16
|
+
export type { CreateAuthControllerOptions } from './auth.controller.js';
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConflictAppException,
|
|
3
|
+
ForbiddenAppException,
|
|
4
|
+
UnauthorizedAppException
|
|
5
|
+
} from "../chunk-ORWJ7LES.js";
|
|
6
|
+
import "../chunk-YFYHLYHN.js";
|
|
7
|
+
import {
|
|
8
|
+
__decorateClass,
|
|
9
|
+
__decorateParam
|
|
10
|
+
} from "../chunk-4MGIQFAJ.js";
|
|
11
|
+
|
|
12
|
+
// src/auth/hash.util.ts
|
|
13
|
+
import { compare, hash } from "bcryptjs";
|
|
14
|
+
var SALT_ROUNDS = 10;
|
|
15
|
+
function hashPassword(plain) {
|
|
16
|
+
return hash(plain, SALT_ROUNDS);
|
|
17
|
+
}
|
|
18
|
+
function verifyPassword(plain, passwordHash) {
|
|
19
|
+
return compare(plain, passwordHash);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/auth/token.service.ts
|
|
23
|
+
import jwt from "jsonwebtoken";
|
|
24
|
+
function requireEnv(name) {
|
|
25
|
+
const value = process.env[name];
|
|
26
|
+
if (!value) {
|
|
27
|
+
throw new Error(`TokenService: ${name} environment variable is not set`);
|
|
28
|
+
}
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
var TokenService = class {
|
|
32
|
+
signAccessToken(payload) {
|
|
33
|
+
return jwt.sign(payload, requireEnv("JWT_ACCESS_SECRET"), {
|
|
34
|
+
expiresIn: process.env.JWT_ACCESS_EXPIRES_IN ?? "15m"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
signRefreshToken(payload) {
|
|
38
|
+
return jwt.sign(payload, requireEnv("JWT_REFRESH_SECRET"), {
|
|
39
|
+
expiresIn: process.env.JWT_REFRESH_EXPIRES_IN ?? "30d"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
verifyAccessToken(token) {
|
|
43
|
+
try {
|
|
44
|
+
return jwt.verify(token, requireEnv("JWT_ACCESS_SECRET"));
|
|
45
|
+
} catch {
|
|
46
|
+
throw new UnauthorizedAppException("Invalid or expired access token");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
verifyRefreshToken(token) {
|
|
50
|
+
try {
|
|
51
|
+
return jwt.verify(token, requireEnv("JWT_REFRESH_SECRET"));
|
|
52
|
+
} catch {
|
|
53
|
+
throw new UnauthorizedAppException("Invalid or expired refresh token");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/auth/jwt-auth.guard.ts
|
|
59
|
+
import { Injectable } from "@nestjs/common";
|
|
60
|
+
var JwtAuthGuard = class {
|
|
61
|
+
constructor() {
|
|
62
|
+
this.tokens = new TokenService();
|
|
63
|
+
}
|
|
64
|
+
canActivate(context) {
|
|
65
|
+
const req = context.switchToHttp().getRequest();
|
|
66
|
+
const header = req.headers.authorization;
|
|
67
|
+
const token = header?.startsWith("Bearer ") ? header.slice("Bearer ".length) : void 0;
|
|
68
|
+
if (!token) {
|
|
69
|
+
throw new UnauthorizedAppException("Missing Authorization bearer token");
|
|
70
|
+
}
|
|
71
|
+
req.user = this.tokens.verifyAccessToken(token);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
JwtAuthGuard = __decorateClass([
|
|
76
|
+
Injectable()
|
|
77
|
+
], JwtAuthGuard);
|
|
78
|
+
|
|
79
|
+
// src/auth/roles.decorator.ts
|
|
80
|
+
import { SetMetadata } from "@nestjs/common";
|
|
81
|
+
var ROLES_KEY = "nestkit:roles";
|
|
82
|
+
var Roles = (...roles) => SetMetadata(ROLES_KEY, roles);
|
|
83
|
+
|
|
84
|
+
// src/auth/roles.guard.ts
|
|
85
|
+
import { Injectable as Injectable2 } from "@nestjs/common";
|
|
86
|
+
import "@nestjs/core";
|
|
87
|
+
var RolesGuard = class {
|
|
88
|
+
constructor(reflector) {
|
|
89
|
+
this.reflector = reflector;
|
|
90
|
+
}
|
|
91
|
+
canActivate(context) {
|
|
92
|
+
const required = this.reflector.getAllAndOverride(ROLES_KEY, [
|
|
93
|
+
context.getHandler(),
|
|
94
|
+
context.getClass()
|
|
95
|
+
]);
|
|
96
|
+
if (!required || required.length === 0) return true;
|
|
97
|
+
const req = context.switchToHttp().getRequest();
|
|
98
|
+
const has = req.user?.roles.some((role) => required.includes(role)) ?? false;
|
|
99
|
+
if (!has) {
|
|
100
|
+
throw new ForbiddenAppException("Insufficient role");
|
|
101
|
+
}
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
RolesGuard = __decorateClass([
|
|
106
|
+
Injectable2()
|
|
107
|
+
], RolesGuard);
|
|
108
|
+
|
|
109
|
+
// src/auth/current-user.decorator.ts
|
|
110
|
+
import { createParamDecorator } from "@nestjs/common";
|
|
111
|
+
var CurrentUser = createParamDecorator(
|
|
112
|
+
(_, ctx) => ctx.switchToHttp().getRequest().user
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// src/auth/current-tenant.decorator.ts
|
|
116
|
+
import { createParamDecorator as createParamDecorator2 } from "@nestjs/common";
|
|
117
|
+
var CurrentTenant = createParamDecorator2(
|
|
118
|
+
(_, ctx) => ctx.switchToHttp().getRequest().user?.tenantId
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
// src/auth/require-tenant.guard.ts
|
|
122
|
+
import { Injectable as Injectable3 } from "@nestjs/common";
|
|
123
|
+
var RequireTenantGuard = class {
|
|
124
|
+
canActivate(context) {
|
|
125
|
+
const req = context.switchToHttp().getRequest();
|
|
126
|
+
if (!req.user?.tenantId) {
|
|
127
|
+
throw new ForbiddenAppException("This action requires a company account");
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
RequireTenantGuard = __decorateClass([
|
|
133
|
+
Injectable3()
|
|
134
|
+
], RequireTenantGuard);
|
|
135
|
+
|
|
136
|
+
// src/auth/auth.dto.ts
|
|
137
|
+
import { IsEmail, IsOptional, IsString, MinLength } from "class-validator";
|
|
138
|
+
var RegisterDto = class {
|
|
139
|
+
};
|
|
140
|
+
__decorateClass([
|
|
141
|
+
IsEmail()
|
|
142
|
+
], RegisterDto.prototype, "email", 2);
|
|
143
|
+
__decorateClass([
|
|
144
|
+
IsString(),
|
|
145
|
+
MinLength(8)
|
|
146
|
+
], RegisterDto.prototype, "password", 2);
|
|
147
|
+
__decorateClass([
|
|
148
|
+
IsOptional(),
|
|
149
|
+
IsString()
|
|
150
|
+
], RegisterDto.prototype, "tenantId", 2);
|
|
151
|
+
var LoginDto = class {
|
|
152
|
+
};
|
|
153
|
+
__decorateClass([
|
|
154
|
+
IsEmail()
|
|
155
|
+
], LoginDto.prototype, "email", 2);
|
|
156
|
+
__decorateClass([
|
|
157
|
+
IsString()
|
|
158
|
+
], LoginDto.prototype, "password", 2);
|
|
159
|
+
var RefreshDto = class {
|
|
160
|
+
};
|
|
161
|
+
__decorateClass([
|
|
162
|
+
IsString()
|
|
163
|
+
], RefreshDto.prototype, "refreshToken", 2);
|
|
164
|
+
|
|
165
|
+
// src/auth/auth.service.ts
|
|
166
|
+
var BaseAuthService = class {
|
|
167
|
+
constructor(users, tokens = new TokenService()) {
|
|
168
|
+
this.users = users;
|
|
169
|
+
this.tokens = tokens;
|
|
170
|
+
}
|
|
171
|
+
async register(data) {
|
|
172
|
+
const existing = await this.users.findByEmail(data.email);
|
|
173
|
+
if (existing) {
|
|
174
|
+
throw new ConflictAppException("Email already registered", { email: data.email }, "EMAIL_TAKEN");
|
|
175
|
+
}
|
|
176
|
+
const passwordHash = await hashPassword(data.password);
|
|
177
|
+
const user = await this.users.create({
|
|
178
|
+
email: data.email,
|
|
179
|
+
passwordHash,
|
|
180
|
+
tenantId: data.tenantId,
|
|
181
|
+
roles: ["user"]
|
|
182
|
+
});
|
|
183
|
+
return { user, ...this.issueTokens(user) };
|
|
184
|
+
}
|
|
185
|
+
async login(email, password) {
|
|
186
|
+
const user = await this.users.findByEmail(email);
|
|
187
|
+
if (!user || !await verifyPassword(password, user.passwordHash)) {
|
|
188
|
+
throw new UnauthorizedAppException("Invalid credentials");
|
|
189
|
+
}
|
|
190
|
+
return { user, ...this.issueTokens(user) };
|
|
191
|
+
}
|
|
192
|
+
async refresh(refreshToken) {
|
|
193
|
+
const payload = this.tokens.verifyRefreshToken(refreshToken);
|
|
194
|
+
const user = await this.users.findById(payload.sub);
|
|
195
|
+
if (!user) {
|
|
196
|
+
throw new UnauthorizedAppException("User no longer exists");
|
|
197
|
+
}
|
|
198
|
+
return this.issueTokens(user);
|
|
199
|
+
}
|
|
200
|
+
issueTokens(user) {
|
|
201
|
+
const payload = {
|
|
202
|
+
sub: user.id,
|
|
203
|
+
email: user.email,
|
|
204
|
+
tenantId: user.tenantId,
|
|
205
|
+
roles: user.roles
|
|
206
|
+
};
|
|
207
|
+
return {
|
|
208
|
+
accessToken: this.tokens.signAccessToken(payload),
|
|
209
|
+
refreshToken: this.tokens.signRefreshToken(payload)
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// src/auth/auth.controller.ts
|
|
215
|
+
import { Body, Controller, Inject, Post } from "@nestjs/common";
|
|
216
|
+
function createAuthController(serviceToken, options = {}) {
|
|
217
|
+
let AuthControllerHost = class {
|
|
218
|
+
constructor(service) {
|
|
219
|
+
this.service = service;
|
|
220
|
+
}
|
|
221
|
+
register(body) {
|
|
222
|
+
return this.service.register(body);
|
|
223
|
+
}
|
|
224
|
+
login(body) {
|
|
225
|
+
return this.service.login(body.email, body.password);
|
|
226
|
+
}
|
|
227
|
+
refresh(body) {
|
|
228
|
+
return this.service.refresh(body.refreshToken);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
__decorateClass([
|
|
232
|
+
Post("register"),
|
|
233
|
+
__decorateParam(0, Body())
|
|
234
|
+
], AuthControllerHost.prototype, "register", 1);
|
|
235
|
+
__decorateClass([
|
|
236
|
+
Post("login"),
|
|
237
|
+
__decorateParam(0, Body())
|
|
238
|
+
], AuthControllerHost.prototype, "login", 1);
|
|
239
|
+
__decorateClass([
|
|
240
|
+
Post("refresh"),
|
|
241
|
+
__decorateParam(0, Body())
|
|
242
|
+
], AuthControllerHost.prototype, "refresh", 1);
|
|
243
|
+
AuthControllerHost = __decorateClass([
|
|
244
|
+
Controller(options.path ?? "auth"),
|
|
245
|
+
__decorateParam(0, Inject(serviceToken))
|
|
246
|
+
], AuthControllerHost);
|
|
247
|
+
return AuthControllerHost;
|
|
248
|
+
}
|
|
249
|
+
export {
|
|
250
|
+
BaseAuthService,
|
|
251
|
+
CurrentTenant,
|
|
252
|
+
CurrentUser,
|
|
253
|
+
JwtAuthGuard,
|
|
254
|
+
LoginDto,
|
|
255
|
+
ROLES_KEY,
|
|
256
|
+
RefreshDto,
|
|
257
|
+
RegisterDto,
|
|
258
|
+
RequireTenantGuard,
|
|
259
|
+
Roles,
|
|
260
|
+
RolesGuard,
|
|
261
|
+
TokenService,
|
|
262
|
+
createAuthController,
|
|
263
|
+
hashPassword,
|
|
264
|
+
verifyPassword
|
|
265
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type CanActivate, type ExecutionContext } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Opt-in guard for endpoints that are company-only (denies individual/solo
|
|
4
|
+
* accounts, which have no `tenantId`). Use after JwtAuthGuard:
|
|
5
|
+
* `@UseGuards(JwtAuthGuard, RequireTenantGuard)`.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RequireTenantGuard implements CanActivate {
|
|
8
|
+
canActivate(context: ExecutionContext): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type CanActivate, type ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
/**
|
|
4
|
+
* Reads `request.user`, populated by JwtAuthGuard — always use
|
|
5
|
+
* `@UseGuards(JwtAuthGuard, RolesGuard)` in that order.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RolesGuard implements CanActivate {
|
|
8
|
+
private readonly reflector;
|
|
9
|
+
constructor(reflector: Reflector);
|
|
10
|
+
canActivate(context: ExecutionContext): boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AuthenticatedUser } from './authenticated-user.js';
|
|
2
|
+
export declare class TokenService {
|
|
3
|
+
signAccessToken(payload: AuthenticatedUser): string;
|
|
4
|
+
signRefreshToken(payload: AuthenticatedUser): string;
|
|
5
|
+
verifyAccessToken(token: string): AuthenticatedUser;
|
|
6
|
+
verifyRefreshToken(token: string): AuthenticatedUser;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
var _chunkO2ZMI3EKcjs = require('../chunk-O2ZMI3EK.cjs');
|
|
4
|
+
require('../chunk-7FQQDWOZ.cjs');
|
|
5
|
+
require('../chunk-R7BVS6CI.cjs');
|
|
6
|
+
require('../chunk-TJHRABML.cjs');
|
|
7
|
+
require('../chunk-ZA56XBCK.cjs');
|
|
8
|
+
require('../chunk-2REOCMUD.cjs');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
exports.applyNestKitDefaults = _chunkO2ZMI3EKcjs.applyNestKitDefaults;
|
package/dist/bootstrap/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyNestKitDefaults
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-RHNQGTAT.js";
|
|
4
|
+
import "../chunk-Q45IEPWU.js";
|
|
5
|
+
import "../chunk-YFYHLYHN.js";
|
|
4
6
|
import "../chunk-KDAA6GFF.js";
|
|
5
|
-
import "../chunk-EQXYK6AL.js";
|
|
6
7
|
import "../chunk-EBO6UKHL.js";
|
|
7
8
|
import "../chunk-4MGIQFAJ.js";
|
|
8
9
|
export {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
exports.__decorateClass = __decorateClass; exports.__decorateParam = __decorateParam;
|