@vnodes/auth 0.0.3
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 +35 -0
- package/assets/favicon.png +0 -0
- package/dist/auth.controller.d.ts +11 -0
- package/dist/auth.controller.d.ts.map +1 -0
- package/dist/auth.controller.js +52 -0
- package/dist/auth.module.d.ts +3 -0
- package/dist/auth.module.d.ts.map +1 -0
- package/dist/auth.module.js +34 -0
- package/dist/context/context.d.ts +10 -0
- package/dist/context/context.d.ts.map +1 -0
- package/dist/context/context.js +13 -0
- package/dist/dto/access-token.dto.d.ts +5 -0
- package/dist/dto/access-token.dto.d.ts.map +1 -0
- package/dist/dto/access-token.dto.js +12 -0
- package/dist/dto/forgot-password.dto.d.ts +4 -0
- package/dist/dto/forgot-password.dto.d.ts.map +1 -0
- package/dist/dto/forgot-password.dto.js +9 -0
- package/dist/dto/login-with-otp.dto.d.ts +5 -0
- package/dist/dto/login-with-otp.dto.d.ts.map +1 -0
- package/dist/dto/login-with-otp.dto.js +14 -0
- package/dist/dto/login.dto.d.ts +5 -0
- package/dist/dto/login.dto.d.ts.map +1 -0
- package/dist/dto/login.dto.js +14 -0
- package/dist/dto/message.dto.d.ts +5 -0
- package/dist/dto/message.dto.d.ts.map +1 -0
- package/dist/dto/message.dto.js +12 -0
- package/dist/dto/otp-response-dto.d.ts +5 -0
- package/dist/dto/otp-response-dto.d.ts.map +1 -0
- package/dist/dto/otp-response-dto.js +12 -0
- package/dist/dto/update-password.dto.d.ts +4 -0
- package/dist/dto/update-password.dto.d.ts.map +1 -0
- package/dist/dto/update-password.dto.js +9 -0
- package/dist/guards/auth.guard.d.ts +12 -0
- package/dist/guards/auth.guard.d.ts.map +1 -0
- package/dist/guards/auth.guard.js +58 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/services/auth.service.d.ts +37 -0
- package/dist/services/auth.service.d.ts.map +1 -0
- package/dist/services/auth.service.js +64 -0
- package/dist/services/user-manager.d.ts +71 -0
- package/dist/services/user-manager.d.ts.map +1 -0
- package/dist/services/user-manager.js +122 -0
- package/dist/services/user.service.d.ts +20 -0
- package/dist/services/user.service.d.ts.map +1 -0
- package/dist/services/user.service.js +75 -0
- package/dist/types/auth-request.d.ts +8 -0
- package/dist/types/auth-request.d.ts.map +1 -0
- package/dist/types/auth-request.js +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+

|
|
2
|
+

|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="https://vnodes.github.io/vnodes/libs/auth/assets/favicon.png" alt="Logo" width="200" height="200" style="border-radius: 100%"/>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
## @vnodes/auth
|
|
12
|
+
|
|
13
|
+
Nestjs authentication and authorization module
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @vnodes/auth
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 💖 Support My Work
|
|
22
|
+
|
|
23
|
+
If you find my open-source contributions or the **@vnodes/auth** project helpful, consider supporting my work. Your sponsorship helps me maintain these projects and explore new enterprise patterns.
|
|
24
|
+
|
|
25
|
+
[](https://cash.app/$puqlib)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🤝 Connect with Me
|
|
30
|
+
|
|
31
|
+
<p align="left">
|
|
32
|
+
<a href="mailto:robert.brightline+vnodes-auth@gmail.com">
|
|
33
|
+
<img src="https://img.shields.io/badge/Email-D14836?style=for-the-badge&logo=gmail&logoColor=white" />
|
|
34
|
+
</a>
|
|
35
|
+
</p>
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ForgotPasswordDto } from './dto/forgot-password.dto.js';
|
|
2
|
+
import { LoginDto } from './dto/login.dto.js';
|
|
3
|
+
import { AuthService } from './services/auth.service.js';
|
|
4
|
+
export declare class AuthController {
|
|
5
|
+
protected readonly authService: AuthService;
|
|
6
|
+
constructor(authService: AuthService);
|
|
7
|
+
login(body: LoginDto): Promise<import("./index.js").AccessTokenDto>;
|
|
8
|
+
logout(accessToken: string): import("./index.js").MessageDto;
|
|
9
|
+
forgotPassword(body: ForgotPasswordDto): import("./index.js").MessageDto;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=auth.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../src/auth.controller.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,qBAEa,cAAc;IACX,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW;gBAAxB,WAAW,EAAE,WAAW;IAIvD,KAAK,CAAS,IAAI,EAAE,QAAQ;IAK5B,MAAM,CAAgB,WAAW,EAAE,MAAM;IAMzC,cAAc,CAAS,IAAI,EAAE,iBAAiB;CAGjD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { __decorate, __metadata, __param } from "tslib";
|
|
2
|
+
import { Body, Controller, Post } from '@nestjs/common';
|
|
3
|
+
import { Throttle } from '@nestjs/throttler';
|
|
4
|
+
import { Public } from '@vnodes/metadata';
|
|
5
|
+
import { AccessToken } from './context/context.js';
|
|
6
|
+
import { ForgotPasswordDto } from './dto/forgot-password.dto.js';
|
|
7
|
+
import { LoginDto } from './dto/login.dto.js';
|
|
8
|
+
import { AuthService } from './services/auth.service.js';
|
|
9
|
+
let AuthController = class AuthController {
|
|
10
|
+
authService;
|
|
11
|
+
constructor(authService) {
|
|
12
|
+
this.authService = authService;
|
|
13
|
+
}
|
|
14
|
+
login(body) {
|
|
15
|
+
return this.authService.login(body);
|
|
16
|
+
}
|
|
17
|
+
logout(accessToken) {
|
|
18
|
+
return this.authService.logout(accessToken);
|
|
19
|
+
}
|
|
20
|
+
forgotPassword(body) {
|
|
21
|
+
return this.authService.forgotPassword(body);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
__decorate([
|
|
25
|
+
Public(),
|
|
26
|
+
Post('login'),
|
|
27
|
+
__param(0, Body()),
|
|
28
|
+
__metadata("design:type", Function),
|
|
29
|
+
__metadata("design:paramtypes", [LoginDto]),
|
|
30
|
+
__metadata("design:returntype", void 0)
|
|
31
|
+
], AuthController.prototype, "login", null);
|
|
32
|
+
__decorate([
|
|
33
|
+
Post('logout'),
|
|
34
|
+
__param(0, AccessToken()),
|
|
35
|
+
__metadata("design:type", Function),
|
|
36
|
+
__metadata("design:paramtypes", [String]),
|
|
37
|
+
__metadata("design:returntype", void 0)
|
|
38
|
+
], AuthController.prototype, "logout", null);
|
|
39
|
+
__decorate([
|
|
40
|
+
Public(),
|
|
41
|
+
Post('forgot-password'),
|
|
42
|
+
__param(0, Body()),
|
|
43
|
+
__metadata("design:type", Function),
|
|
44
|
+
__metadata("design:paramtypes", [ForgotPasswordDto]),
|
|
45
|
+
__metadata("design:returntype", void 0)
|
|
46
|
+
], AuthController.prototype, "forgotPassword", null);
|
|
47
|
+
AuthController = __decorate([
|
|
48
|
+
Throttle({ default: { limit: 6, ttl: 30_000 } }),
|
|
49
|
+
Controller('auth'),
|
|
50
|
+
__metadata("design:paramtypes", [AuthService])
|
|
51
|
+
], AuthController);
|
|
52
|
+
export { AuthController };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.module.d.ts","sourceRoot":"","sources":["../src/auth.module.ts"],"names":[],"mappings":"AAQA,qBAqBa,UAAU;CAAG"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { Module } from '@nestjs/common';
|
|
3
|
+
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
4
|
+
import { EventEmitterModule } from '@nestjs/event-emitter';
|
|
5
|
+
import { JwtModule } from '@nestjs/jwt';
|
|
6
|
+
import { AuthController } from './auth.controller.js';
|
|
7
|
+
import { AuthService } from './services/auth.service.js';
|
|
8
|
+
import { UserService } from './services/user.service.js';
|
|
9
|
+
let AuthModule = class AuthModule {
|
|
10
|
+
};
|
|
11
|
+
AuthModule = __decorate([
|
|
12
|
+
Module({
|
|
13
|
+
imports: [
|
|
14
|
+
EventEmitterModule,
|
|
15
|
+
JwtModule.registerAsync({
|
|
16
|
+
imports: [ConfigModule],
|
|
17
|
+
inject: [ConfigService],
|
|
18
|
+
useFactory(config) {
|
|
19
|
+
const secret = config.getOrThrow('JWT_SECRET');
|
|
20
|
+
const expiresIn = config.getOrThrow('JWT_EXPIRES_IN');
|
|
21
|
+
return {
|
|
22
|
+
secret,
|
|
23
|
+
signOptions: {
|
|
24
|
+
expiresIn,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
}),
|
|
29
|
+
],
|
|
30
|
+
controllers: [AuthController],
|
|
31
|
+
providers: [UserService, AuthService],
|
|
32
|
+
})
|
|
33
|
+
], AuthModule);
|
|
34
|
+
export { AuthModule };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { User } from '../services/user-manager.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get the user info {@link UserInfo} of the current session from the request
|
|
4
|
+
*/
|
|
5
|
+
export declare const UserInfo: (...dataOrPipes: (User | import("@nestjs/common").PipeTransform<any, any> | import("@nestjs/common").Type<import("@nestjs/common").PipeTransform<any, any>>)[]) => ParameterDecorator;
|
|
6
|
+
/**
|
|
7
|
+
* Get the access token of the current session from the request
|
|
8
|
+
*/
|
|
9
|
+
export declare const AccessToken: (...dataOrPipes: (string | import("@nestjs/common").PipeTransform<any, any> | import("@nestjs/common").Type<import("@nestjs/common").PipeTransform<any, any>>)[]) => ParameterDecorator;
|
|
10
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context/context.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AAGnD;;GAEG;AACH,eAAO,MAAM,QAAQ,uLAEnB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,yLAEtB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createParamDecorator } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Get the user info {@link UserInfo} of the current session from the request
|
|
4
|
+
*/
|
|
5
|
+
export const UserInfo = createParamDecorator((_, context) => {
|
|
6
|
+
return context.switchToHttp().getRequest().user;
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* Get the access token of the current session from the request
|
|
10
|
+
*/
|
|
11
|
+
export const AccessToken = createParamDecorator((_, context) => {
|
|
12
|
+
return context.switchToHttp().getRequest().accessToken;
|
|
13
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"access-token.dto.d.ts","sourceRoot":"","sources":["../../src/dto/access-token.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,cAAc;IACf,KAAK,EAAE,MAAM,CAAC;gBAEV,GAAG,EAAE,cAAc;CAGlC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class AccessTokenDto {
|
|
4
|
+
token;
|
|
5
|
+
constructor(dto) {
|
|
6
|
+
Object.assign(this, dto);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
__decorate([
|
|
10
|
+
Prop(),
|
|
11
|
+
__metadata("design:type", String)
|
|
12
|
+
], AccessTokenDto.prototype, "token", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgot-password.dto.d.ts","sourceRoot":"","sources":["../../src/dto/forgot-password.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,iBAAiB;IACiB,QAAQ,EAAE,MAAM,CAAC;CAC/D"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class ForgotPasswordDto {
|
|
4
|
+
username;
|
|
5
|
+
}
|
|
6
|
+
__decorate([
|
|
7
|
+
Prop({ required: true, format: 'email' }),
|
|
8
|
+
__metadata("design:type", String)
|
|
9
|
+
], ForgotPasswordDto.prototype, "username", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-with-otp.dto.d.ts","sourceRoot":"","sources":["../../src/dto/login-with-otp.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,eAAe;IACmB,QAAQ,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACvD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class LoginWithOtpDto {
|
|
4
|
+
username;
|
|
5
|
+
otp;
|
|
6
|
+
}
|
|
7
|
+
__decorate([
|
|
8
|
+
Prop({ required: true, format: 'email' }),
|
|
9
|
+
__metadata("design:type", String)
|
|
10
|
+
], LoginWithOtpDto.prototype, "username", void 0);
|
|
11
|
+
__decorate([
|
|
12
|
+
Prop({ required: true, minLength: 6 }),
|
|
13
|
+
__metadata("design:type", String)
|
|
14
|
+
], LoginWithOtpDto.prototype, "otp", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.dto.d.ts","sourceRoot":"","sources":["../../src/dto/login.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAQ;IAC0B,QAAQ,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class LoginDto {
|
|
4
|
+
username;
|
|
5
|
+
password;
|
|
6
|
+
}
|
|
7
|
+
__decorate([
|
|
8
|
+
Prop({ required: true, format: 'email' }),
|
|
9
|
+
__metadata("design:type", String)
|
|
10
|
+
], LoginDto.prototype, "username", void 0);
|
|
11
|
+
__decorate([
|
|
12
|
+
Prop({ required: true, format: 'password' }),
|
|
13
|
+
__metadata("design:type", String)
|
|
14
|
+
], LoginDto.prototype, "password", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.dto.d.ts","sourceRoot":"","sources":["../../src/dto/message.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,UAAU;IACX,OAAO,EAAE,MAAM,CAAC;gBAEZ,IAAI,EAAE,UAAU;CAG/B"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class MessageDto {
|
|
4
|
+
message;
|
|
5
|
+
constructor(data) {
|
|
6
|
+
Object.assign(this, data);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
__decorate([
|
|
10
|
+
Prop(),
|
|
11
|
+
__metadata("design:type", String)
|
|
12
|
+
], MessageDto.prototype, "message", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"otp-response-dto.d.ts","sourceRoot":"","sources":["../../src/dto/otp-response-dto.ts"],"names":[],"mappings":"AAEA,qBAAa,cAAc;IACf,GAAG,EAAE,MAAM,CAAC;gBACR,IAAI,EAAE,cAAc;CAGnC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class OtpResponseDto {
|
|
4
|
+
otp;
|
|
5
|
+
constructor(data) {
|
|
6
|
+
Object.assign(this, data);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
__decorate([
|
|
10
|
+
Prop(),
|
|
11
|
+
__metadata("design:type", String)
|
|
12
|
+
], OtpResponseDto.prototype, "otp", void 0);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-password.dto.d.ts","sourceRoot":"","sources":["../../src/dto/update-password.dto.ts"],"names":[],"mappings":"AAEA,qBAAa,iBAAiB;IACoB,QAAQ,EAAE,MAAM,CAAC;CAClE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Prop } from '@vnodes/property';
|
|
3
|
+
export class UpdatePasswordDto {
|
|
4
|
+
password;
|
|
5
|
+
}
|
|
6
|
+
__decorate([
|
|
7
|
+
Prop({ required: true, format: 'password' }),
|
|
8
|
+
__metadata("design:type", String)
|
|
9
|
+
], UpdatePasswordDto.prototype, "password", void 0);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CanActivate, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
import { UserService } from '../services/user.service.js';
|
|
4
|
+
import { AuthRequest } from '../types/auth-request.js';
|
|
5
|
+
export declare class AuthGuard implements CanActivate {
|
|
6
|
+
protected readonly reflector: Reflector;
|
|
7
|
+
protected readonly userService: UserService;
|
|
8
|
+
constructor(reflector: Reflector, userService: UserService);
|
|
9
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
10
|
+
extractToken(request: AuthRequest): string;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=auth.guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.guard.d.ts","sourceRoot":"","sources":["../../src/guards/auth.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAqC,MAAM,gBAAgB,CAAC;AAClG,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAEvD,qBACa,SAAU,YAAW,WAAW;IAErC,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS;IACvC,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW;gBADxB,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW;IAGzC,WAAW,CAAC,OAAO,EAAE,gBAAgB;IAqC3C,YAAY,CAAC,OAAO,EAAE,WAAW;CAYpC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
|
3
|
+
import { Reflector } from '@nestjs/core';
|
|
4
|
+
import { getPermissions, getRoles, isPublic } from '@vnodes/metadata';
|
|
5
|
+
import { UserService } from '../services/user.service.js';
|
|
6
|
+
let AuthGuard = class AuthGuard {
|
|
7
|
+
reflector;
|
|
8
|
+
userService;
|
|
9
|
+
constructor(reflector, userService) {
|
|
10
|
+
this.reflector = reflector;
|
|
11
|
+
this.userService = userService;
|
|
12
|
+
}
|
|
13
|
+
async canActivate(context) {
|
|
14
|
+
if (isPublic(this.reflector, context)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
const permissions = getPermissions(this.reflector, context);
|
|
18
|
+
const roles = getRoles(this.reflector, context);
|
|
19
|
+
const requiredPolicy = ((permissions || roles) && permissions.length > 0) || roles.length > 0;
|
|
20
|
+
if (!requiredPolicy) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
const authRequest = context.switchToHttp().getRequest();
|
|
24
|
+
const token = this.extractToken(authRequest);
|
|
25
|
+
const user = await this.userService.findByToken(token);
|
|
26
|
+
authRequest.user = user.user;
|
|
27
|
+
if (user.isAdmin()) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (permissions.length > 0) {
|
|
31
|
+
if (!user.hasPermissions(permissions)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (roles.length > 0) {
|
|
36
|
+
if (!user.hasRoles(roles)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
extractToken(request) {
|
|
43
|
+
const rawToken = request.headers.authorization;
|
|
44
|
+
if (!rawToken) {
|
|
45
|
+
throw new UnauthorizedException('No token');
|
|
46
|
+
}
|
|
47
|
+
const [type, token] = rawToken.split(' ');
|
|
48
|
+
if (type === 'Bearer' && token)
|
|
49
|
+
return token;
|
|
50
|
+
throw new UnauthorizedException('Invalid token ');
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
AuthGuard = __decorate([
|
|
54
|
+
Injectable(),
|
|
55
|
+
__metadata("design:paramtypes", [Reflector,
|
|
56
|
+
UserService])
|
|
57
|
+
], AuthGuard);
|
|
58
|
+
export { AuthGuard };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from './auth.controller.js';
|
|
2
|
+
export * from './auth.module.js';
|
|
3
|
+
export * from './context/context.js';
|
|
4
|
+
export * from './dto/access-token.dto.js';
|
|
5
|
+
export * from './dto/forgot-password.dto.js';
|
|
6
|
+
export * from './dto/login.dto.js';
|
|
7
|
+
export * from './dto/login-with-otp.dto.js';
|
|
8
|
+
export * from './dto/message.dto.js';
|
|
9
|
+
export * from './dto/otp-response-dto.js';
|
|
10
|
+
export * from './dto/update-password.dto.js';
|
|
11
|
+
export * from './guards/auth.guard.js';
|
|
12
|
+
export * from './services/auth.service.js';
|
|
13
|
+
export * from './services/user.service.js';
|
|
14
|
+
export * from './services/user-manager.js';
|
|
15
|
+
export * from './types/auth-request.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,oBAAoB,CAAC;AACnC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// @index(['./**/*.ts', '!./**/*.spec.ts', '!./**/{main,serve,index}.ts', '!./**/prisma', '!./**/generated'], f => `export * from '${f.path}.js'`)
|
|
2
|
+
export * from './auth.controller.js';
|
|
3
|
+
export * from './auth.module.js';
|
|
4
|
+
export * from './context/context.js';
|
|
5
|
+
export * from './dto/access-token.dto.js';
|
|
6
|
+
export * from './dto/forgot-password.dto.js';
|
|
7
|
+
export * from './dto/login.dto.js';
|
|
8
|
+
export * from './dto/login-with-otp.dto.js';
|
|
9
|
+
export * from './dto/message.dto.js';
|
|
10
|
+
export * from './dto/otp-response-dto.js';
|
|
11
|
+
export * from './dto/update-password.dto.js';
|
|
12
|
+
export * from './guards/auth.guard.js';
|
|
13
|
+
export * from './services/auth.service.js';
|
|
14
|
+
export * from './services/user.service.js';
|
|
15
|
+
export * from './services/user-manager.js';
|
|
16
|
+
export * from './types/auth-request.js';
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
2
|
+
import { AccessTokenDto } from '../dto/access-token.dto.js';
|
|
3
|
+
import { ForgotPasswordDto } from '../dto/forgot-password.dto.js';
|
|
4
|
+
import { LoginDto } from '../dto/login.dto.js';
|
|
5
|
+
import { LoginWithOtpDto } from '../dto/login-with-otp.dto.js';
|
|
6
|
+
import { MessageDto } from '../dto/message.dto.js';
|
|
7
|
+
import { UserService } from './user.service.js';
|
|
8
|
+
export declare class AuthService {
|
|
9
|
+
protected readonly userService: UserService;
|
|
10
|
+
protected readonly eventEmitter: EventEmitter2;
|
|
11
|
+
constructor(userService: UserService, eventEmitter: EventEmitter2);
|
|
12
|
+
/**
|
|
13
|
+
* Login with credentials (find user by username and compare the passed with hashed password)
|
|
14
|
+
* @param body -- {@link LoginDto}
|
|
15
|
+
* @returns -- {@link AccessTokenDto}
|
|
16
|
+
*/
|
|
17
|
+
login(body: LoginDto): Promise<AccessTokenDto>;
|
|
18
|
+
/**
|
|
19
|
+
* Login with otp code (generated and sent to the user via email or sms)
|
|
20
|
+
* @param body -- {@link LoginWithOtpDto}
|
|
21
|
+
* @returns -- {@link AccessTokenDto}
|
|
22
|
+
*/
|
|
23
|
+
loginWithOtp(body: LoginWithOtpDto): Promise<AccessTokenDto>;
|
|
24
|
+
/**
|
|
25
|
+
* Logout from the current sesison (delete the session token from token hash map)
|
|
26
|
+
* @param token acesss token
|
|
27
|
+
* @returns -- {@link MessageDto}
|
|
28
|
+
*/
|
|
29
|
+
logout(token: string): MessageDto;
|
|
30
|
+
/**
|
|
31
|
+
* Create a otp code and emit "email.otp" event with payload of {@link OtpResponseDto}
|
|
32
|
+
* @param body -- {@link ForgotPasswordDto}
|
|
33
|
+
* @returns -- {@link MessageDto}
|
|
34
|
+
*/
|
|
35
|
+
forgotPassword(body: ForgotPasswordDto): MessageDto;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=auth.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../src/services/auth.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,qBACa,WAAW;IAEhB,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW;IAC3C,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,aAAa;gBAD3B,WAAW,EAAE,WAAW,EACxB,YAAY,EAAE,aAAa;IAGlD;;;;OAIG;IACG,KAAK,CAAC,IAAI,EAAE,QAAQ;IAQ1B;;;;OAIG;IACG,YAAY,CAAC,IAAI,EAAE,eAAe;IAQxC;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM;IAKpB;;;;OAIG;IACH,cAAc,CAAC,IAAI,EAAE,iBAAiB;CAKzC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { Injectable } from '@nestjs/common';
|
|
3
|
+
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
4
|
+
import { AccessTokenDto } from '../dto/access-token.dto.js';
|
|
5
|
+
import { MessageDto } from '../dto/message.dto.js';
|
|
6
|
+
import { OtpResponseDto } from '../dto/otp-response-dto.js';
|
|
7
|
+
import { UserService } from './user.service.js';
|
|
8
|
+
let AuthService = class AuthService {
|
|
9
|
+
userService;
|
|
10
|
+
eventEmitter;
|
|
11
|
+
constructor(userService, eventEmitter) {
|
|
12
|
+
this.userService = userService;
|
|
13
|
+
this.eventEmitter = eventEmitter;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Login with credentials (find user by username and compare the passed with hashed password)
|
|
17
|
+
* @param body -- {@link LoginDto}
|
|
18
|
+
* @returns -- {@link AccessTokenDto}
|
|
19
|
+
*/
|
|
20
|
+
async login(body) {
|
|
21
|
+
const user = this.userService.findByUsername(body.username);
|
|
22
|
+
await user.comparePassword(body.password);
|
|
23
|
+
const token = await user.signToken();
|
|
24
|
+
this.userService.updateToken(token, user.user.username);
|
|
25
|
+
return new AccessTokenDto({ token });
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Login with otp code (generated and sent to the user via email or sms)
|
|
29
|
+
* @param body -- {@link LoginWithOtpDto}
|
|
30
|
+
* @returns -- {@link AccessTokenDto}
|
|
31
|
+
*/
|
|
32
|
+
async loginWithOtp(body) {
|
|
33
|
+
this.userService.compareOtp(body.username, body.otp);
|
|
34
|
+
this.userService.deleteOtp(body.username);
|
|
35
|
+
const user = this.userService.findByUsername(body.username);
|
|
36
|
+
const token = await user.signToken();
|
|
37
|
+
return new AccessTokenDto({ token });
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Logout from the current sesison (delete the session token from token hash map)
|
|
41
|
+
* @param token acesss token
|
|
42
|
+
* @returns -- {@link MessageDto}
|
|
43
|
+
*/
|
|
44
|
+
logout(token) {
|
|
45
|
+
this.userService.deleteToken(token);
|
|
46
|
+
return new MessageDto({ message: 'Bye for now' });
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a otp code and emit "email.otp" event with payload of {@link OtpResponseDto}
|
|
50
|
+
* @param body -- {@link ForgotPasswordDto}
|
|
51
|
+
* @returns -- {@link MessageDto}
|
|
52
|
+
*/
|
|
53
|
+
forgotPassword(body) {
|
|
54
|
+
const otp = this.userService.createOtp(body.username);
|
|
55
|
+
this.eventEmitter.emit('email.otp', new OtpResponseDto({ otp }));
|
|
56
|
+
return new MessageDto({ message: 'We sent the otp to your email' });
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
AuthService = __decorate([
|
|
60
|
+
Injectable(),
|
|
61
|
+
__metadata("design:paramtypes", [UserService,
|
|
62
|
+
EventEmitter2])
|
|
63
|
+
], AuthService);
|
|
64
|
+
export { AuthService };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { JwtService } from '@nestjs/jwt';
|
|
2
|
+
export declare class JwtPayload {
|
|
3
|
+
sub: number;
|
|
4
|
+
username: string;
|
|
5
|
+
version: string;
|
|
6
|
+
}
|
|
7
|
+
export declare class User {
|
|
8
|
+
id: number;
|
|
9
|
+
version: string;
|
|
10
|
+
username: string;
|
|
11
|
+
password: string;
|
|
12
|
+
permissions?: string[];
|
|
13
|
+
roles?: string[];
|
|
14
|
+
constructor(user: User);
|
|
15
|
+
}
|
|
16
|
+
export declare class UserManager {
|
|
17
|
+
protected readonly userData: User;
|
|
18
|
+
protected readonly jwt: JwtService;
|
|
19
|
+
constructor(userData: User, jwt: JwtService);
|
|
20
|
+
/**
|
|
21
|
+
* Get the user data
|
|
22
|
+
*/
|
|
23
|
+
get user(): User;
|
|
24
|
+
/**
|
|
25
|
+
* Get the set of user permissions
|
|
26
|
+
*/
|
|
27
|
+
get permisisons(): Set<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Get the set of user roles
|
|
30
|
+
*/
|
|
31
|
+
get roles(): Set<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Get the user version
|
|
34
|
+
*/
|
|
35
|
+
get version(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Check the user has the "admin" role
|
|
38
|
+
*/
|
|
39
|
+
isAdmin(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Check the user has all {@link requiredPermissions} or throw {@link ForbiddenException}
|
|
42
|
+
*/
|
|
43
|
+
hasPermissions(requiredPermissions: string[]): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Check the user has one of the {@link requiredRoles} or throw {@link ForbiddenException}
|
|
46
|
+
*/
|
|
47
|
+
hasRoles(requiredRoles: string[]): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Create the jwt payload object {@link JwtPayload}
|
|
50
|
+
* @returns -- {@link JwtPayload}
|
|
51
|
+
*/
|
|
52
|
+
toJwtPayload(): JwtPayload;
|
|
53
|
+
/**
|
|
54
|
+
* Compare the plain password with the hashed password
|
|
55
|
+
* @param password plain password
|
|
56
|
+
* @returns boolean or throw {@link UnauthorizedException}
|
|
57
|
+
*/
|
|
58
|
+
comparePassword(password: string): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Sign the jwt token
|
|
61
|
+
* @returns jwt token
|
|
62
|
+
*/
|
|
63
|
+
signToken(): Promise<string>;
|
|
64
|
+
/**
|
|
65
|
+
* Verify jwt {@link token}
|
|
66
|
+
* @param token jwt token
|
|
67
|
+
* @returns string or throw {@link UnauthorizedException} that indicated invalid or old versioned token
|
|
68
|
+
*/
|
|
69
|
+
verifyToken(token: string): Promise<JwtPayload>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=user-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user-manager.d.ts","sourceRoot":"","sources":["../../src/services/user-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGzC,qBAAa,UAAU;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,IAAI;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;gBAEL,IAAI,EAAE,IAAI;CAWzB;AAED,qBAAa,WAAW;IAEhB,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI;IACjC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU;gBADf,QAAQ,EAAE,IAAI,EACd,GAAG,EAAE,UAAU;IAGtC;;OAEG;IACH,IAAI,IAAI,IAAI,IAAI,CAEf;IAED;;OAEG;IACH,IAAI,WAAW,gBAEd;IAED;;OAEG;IACH,IAAI,KAAK,gBAER;IAED;;OAEG;IACH,IAAI,OAAO,WAEV;IAED;;OAEG;IACH,OAAO;IAIP;;OAEG;IACH,cAAc,CAAC,mBAAmB,EAAE,MAAM,EAAE;IAO5C;;OAEG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE;IAOhC;;;OAGG;IACH,YAAY,IAAI,UAAU;IAQ1B;;;;OAIG;IACG,eAAe,CAAC,QAAQ,EAAE,MAAM;IAOtC;;;OAGG;IACG,SAAS;IAKf;;;;OAIG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM;CASlC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { ForbiddenException, UnauthorizedException } from '@nestjs/common';
|
|
2
|
+
import { compare } from '@vnodes/crypto';
|
|
3
|
+
export class JwtPayload {
|
|
4
|
+
sub;
|
|
5
|
+
username;
|
|
6
|
+
version;
|
|
7
|
+
}
|
|
8
|
+
export class User {
|
|
9
|
+
id;
|
|
10
|
+
version;
|
|
11
|
+
username;
|
|
12
|
+
password;
|
|
13
|
+
permissions;
|
|
14
|
+
roles;
|
|
15
|
+
constructor(user) {
|
|
16
|
+
Object.assign(this, user);
|
|
17
|
+
if (user.permissions && user.permissions?.length > 0) {
|
|
18
|
+
this.permissions = user.permissions;
|
|
19
|
+
}
|
|
20
|
+
if (user.roles && user.roles?.length > 0) {
|
|
21
|
+
this.roles = user.roles;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export class UserManager {
|
|
26
|
+
userData;
|
|
27
|
+
jwt;
|
|
28
|
+
constructor(userData, jwt) {
|
|
29
|
+
this.userData = userData;
|
|
30
|
+
this.jwt = jwt;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get the user data
|
|
34
|
+
*/
|
|
35
|
+
get user() {
|
|
36
|
+
return new User(this.userData);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get the set of user permissions
|
|
40
|
+
*/
|
|
41
|
+
get permisisons() {
|
|
42
|
+
return new Set(this.userData.permissions ?? []);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the set of user roles
|
|
46
|
+
*/
|
|
47
|
+
get roles() {
|
|
48
|
+
return new Set(this.userData.roles ?? []);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get the user version
|
|
52
|
+
*/
|
|
53
|
+
get version() {
|
|
54
|
+
return this.userData.version;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check the user has the "admin" role
|
|
58
|
+
*/
|
|
59
|
+
isAdmin() {
|
|
60
|
+
return this.roles.has('admin');
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Check the user has all {@link requiredPermissions} or throw {@link ForbiddenException}
|
|
64
|
+
*/
|
|
65
|
+
hasPermissions(requiredPermissions) {
|
|
66
|
+
if (requiredPermissions.every((permission) => this.permisisons.has(permission))) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
throw new ForbiddenException('Insufficient permissions');
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check the user has one of the {@link requiredRoles} or throw {@link ForbiddenException}
|
|
73
|
+
*/
|
|
74
|
+
hasRoles(requiredRoles) {
|
|
75
|
+
if (requiredRoles.some((role) => this.roles.has(role))) {
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
throw new ForbiddenException('Insufficient role');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create the jwt payload object {@link JwtPayload}
|
|
82
|
+
* @returns -- {@link JwtPayload}
|
|
83
|
+
*/
|
|
84
|
+
toJwtPayload() {
|
|
85
|
+
return {
|
|
86
|
+
sub: this.userData.id,
|
|
87
|
+
username: this.userData.username,
|
|
88
|
+
version: this.userData.version,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Compare the plain password with the hashed password
|
|
93
|
+
* @param password plain password
|
|
94
|
+
* @returns boolean or throw {@link UnauthorizedException}
|
|
95
|
+
*/
|
|
96
|
+
async comparePassword(password) {
|
|
97
|
+
if (await compare(password, this.userData.password)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
throw new UnauthorizedException(`Wrong password`);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Sign the jwt token
|
|
104
|
+
* @returns jwt token
|
|
105
|
+
*/
|
|
106
|
+
async signToken() {
|
|
107
|
+
const token = await this.jwt.signAsync(this.toJwtPayload());
|
|
108
|
+
return token;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Verify jwt {@link token}
|
|
112
|
+
* @param token jwt token
|
|
113
|
+
* @returns string or throw {@link UnauthorizedException} that indicated invalid or old versioned token
|
|
114
|
+
*/
|
|
115
|
+
async verifyToken(token) {
|
|
116
|
+
const jwtPayload = await this.jwt.verifyAsync(token);
|
|
117
|
+
if (jwtPayload.version === this.version) {
|
|
118
|
+
return jwtPayload;
|
|
119
|
+
}
|
|
120
|
+
throw new UnauthorizedException(`Invalid jwt version`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { JwtService } from '@nestjs/jwt';
|
|
2
|
+
import { User, UserManager } from './user-manager.js';
|
|
3
|
+
export declare class UserService {
|
|
4
|
+
protected readonly jwt: JwtService;
|
|
5
|
+
protected readonly usernameMap: Map<string, User>;
|
|
6
|
+
protected readonly tokenUsernameMap: Map<string, string>;
|
|
7
|
+
protected readonly usernameOtpMap: Map<string, string>;
|
|
8
|
+
constructor(jwt: JwtService);
|
|
9
|
+
update(user: User): void;
|
|
10
|
+
deleteByUsername(username: string): void;
|
|
11
|
+
load(users: User[]): void;
|
|
12
|
+
findByUsername(username: string): UserManager;
|
|
13
|
+
findByToken(token: string): UserManager;
|
|
14
|
+
deleteToken(token: string): boolean;
|
|
15
|
+
updateToken(token: string, username: string): void;
|
|
16
|
+
createOtp(username: string): string;
|
|
17
|
+
compareOtp(username: string, otp: string): boolean;
|
|
18
|
+
deleteOtp(username: string): void;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=user.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"user.service.d.ts","sourceRoot":"","sources":["../../src/services/user.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEtD,qBACa,WAAW;IAKY,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU;IAJlE,SAAS,CAAC,QAAQ,CAAC,WAAW,oBAA2B;IACzD,SAAS,CAAC,QAAQ,CAAC,gBAAgB,sBAA6B;IAChE,SAAS,CAAC,QAAQ,CAAC,cAAc,sBAA6B;gBAEX,GAAG,EAAE,UAAU;IAElE,MAAM,CAAC,IAAI,EAAE,IAAI;IAIjB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;IAIjC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;IAOlB,cAAc,CAAC,QAAQ,EAAE,MAAM;IAQ/B,WAAW,CAAC,KAAK,EAAE,MAAM;IASzB,WAAW,CAAC,KAAK,EAAE,MAAM;IAOzB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAI3C,SAAS,CAAC,QAAQ,EAAE,MAAM;IAM1B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM;IAYxC,SAAS,CAAC,QAAQ,EAAE,MAAM;CAG7B"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { __decorate, __metadata, __param } from "tslib";
|
|
2
|
+
import { Inject, Injectable, NotFoundException, UnauthorizedException } from '@nestjs/common';
|
|
3
|
+
import { JwtService } from '@nestjs/jwt';
|
|
4
|
+
import { otp } from '@vnodes/crypto';
|
|
5
|
+
import { UserManager } from './user-manager.js';
|
|
6
|
+
let UserService = class UserService {
|
|
7
|
+
jwt;
|
|
8
|
+
usernameMap = new Map();
|
|
9
|
+
tokenUsernameMap = new Map();
|
|
10
|
+
usernameOtpMap = new Map();
|
|
11
|
+
constructor(jwt) {
|
|
12
|
+
this.jwt = jwt;
|
|
13
|
+
}
|
|
14
|
+
update(user) {
|
|
15
|
+
this.usernameMap.set(user.username, user);
|
|
16
|
+
}
|
|
17
|
+
deleteByUsername(username) {
|
|
18
|
+
this.usernameMap.delete(username);
|
|
19
|
+
}
|
|
20
|
+
load(users) {
|
|
21
|
+
this.usernameMap.clear();
|
|
22
|
+
for (const user of users) {
|
|
23
|
+
this.usernameMap.set(user.username, user);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
findByUsername(username) {
|
|
27
|
+
const foundUser = this.usernameMap.get(username);
|
|
28
|
+
if (foundUser) {
|
|
29
|
+
return new UserManager(foundUser, this.jwt);
|
|
30
|
+
}
|
|
31
|
+
throw new NotFoundException(`The user ${username} not found`);
|
|
32
|
+
}
|
|
33
|
+
findByToken(token) {
|
|
34
|
+
const username = this.tokenUsernameMap.get(token);
|
|
35
|
+
if (username) {
|
|
36
|
+
return this.findByUsername(username);
|
|
37
|
+
}
|
|
38
|
+
throw new UnauthorizedException(`User not found by token`);
|
|
39
|
+
}
|
|
40
|
+
deleteToken(token) {
|
|
41
|
+
if (this.tokenUsernameMap.delete(token)) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
throw new NotFoundException('Token not found');
|
|
45
|
+
}
|
|
46
|
+
updateToken(token, username) {
|
|
47
|
+
this.tokenUsernameMap.set(token, username);
|
|
48
|
+
}
|
|
49
|
+
createOtp(username) {
|
|
50
|
+
const otpValue = otp();
|
|
51
|
+
this.usernameOtpMap.set(username, otpValue);
|
|
52
|
+
return otpValue;
|
|
53
|
+
}
|
|
54
|
+
compareOtp(username, otp) {
|
|
55
|
+
const foundOtp = this.usernameOtpMap.get(username);
|
|
56
|
+
if (foundOtp) {
|
|
57
|
+
if (foundOtp === otp) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
throw new UnauthorizedException(`Wrong otp`);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw new UnauthorizedException('Otp not found');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
deleteOtp(username) {
|
|
67
|
+
this.usernameOtpMap.delete(username);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
UserService = __decorate([
|
|
71
|
+
Injectable(),
|
|
72
|
+
__param(0, Inject(JwtService)),
|
|
73
|
+
__metadata("design:paramtypes", [JwtService])
|
|
74
|
+
], UserService);
|
|
75
|
+
export { UserService };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-request.d.ts","sourceRoot":"","sources":["../../src/types/auth-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAC;AACnD,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC;AAC1C,MAAM,MAAM,WAAW,GAAG;IACtB,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;CACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vnodes/auth",
|
|
3
|
+
"description": "Nestjs authentication and authorization module",
|
|
4
|
+
"homepage": "https://vnodes.github.io/vnodes/libs/auth",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public",
|
|
7
|
+
"tag": "latest"
|
|
8
|
+
},
|
|
9
|
+
"author": {
|
|
10
|
+
"email": "robert.brightline+vnodes-auth@gmail.com",
|
|
11
|
+
"name": "Robert Brightline",
|
|
12
|
+
"url": "https://vnodes.github.io/vnodes/libs/auth"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [],
|
|
15
|
+
"icon": "https://vnodes.github.io/vnodes/libs/auth/assets/favicon.png",
|
|
16
|
+
"funding": [
|
|
17
|
+
{
|
|
18
|
+
"type": "cashapp",
|
|
19
|
+
"url": "https://cash.app/$puqlib"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"version": "0.0.3",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
"./package.json": "./package.json",
|
|
29
|
+
".": {
|
|
30
|
+
"@vnodes/source": "./src/index.ts",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"assets",
|
|
38
|
+
"dist",
|
|
39
|
+
"!**/*.tsbuildinfo"
|
|
40
|
+
],
|
|
41
|
+
"nx": {
|
|
42
|
+
"sourceRoot": "libs/auth/src",
|
|
43
|
+
"targets": {
|
|
44
|
+
"build": {},
|
|
45
|
+
"lint": {},
|
|
46
|
+
"test": {},
|
|
47
|
+
"doc": {}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@swc/helpers": "~0.5.11"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@nestjs/testing": "^11.1.13"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"@nestjs/common": "^11.1.14",
|
|
58
|
+
"@nestjs/config": "^4.0.3",
|
|
59
|
+
"@nestjs/core": "^11.1.14",
|
|
60
|
+
"@nestjs/event-emitter": "^3.0.1",
|
|
61
|
+
"@nestjs/jwt": "^11.0.2",
|
|
62
|
+
"@nestjs/swagger": "^11.2.6",
|
|
63
|
+
"@nestjs/throttler": "^6.5.0",
|
|
64
|
+
"@vnodes/crypto": "0.0.3",
|
|
65
|
+
"@vnodes/property": "0.0.3",
|
|
66
|
+
"@vnodes/metadata": "0.0.3"
|
|
67
|
+
}
|
|
68
|
+
}
|