@smartsoft001/auth-domain 1.1.91 → 2.68.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/.eslintrc.json +26 -0
- package/README.md +161 -2
- package/jest.config.ts +26 -0
- package/package.json +3 -32
- package/project.json +44 -0
- package/src/index.ts +9 -0
- package/src/lib/entities/user.entity.ts +34 -0
- package/src/lib/feature-create-token/interfaces.ts +51 -0
- package/src/lib/feature-create-token/token-payload.provider.ts +17 -0
- package/src/lib/feature-create-token/token-user.provider.ts +14 -0
- package/src/lib/feature-create-token/token-validation.provider.ts +13 -0
- package/src/lib/feature-create-token/token.config.ts +8 -0
- package/src/lib/feature-create-token/token.factory.spec.ts +193 -0
- package/src/lib/feature-create-token/token.factory.ts +199 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +10 -0
- package/tsconfig.spec.json +20 -0
- package/src/index.d.ts +0 -6
- package/src/index.js +0 -15
- package/src/index.js.map +0 -1
- package/src/lib/entities/index.js +0 -5
- package/src/lib/entities/index.js.map +0 -1
- package/src/lib/entities/user.entity.d.ts +0 -13
- package/src/lib/entities/user.entity.js +0 -47
- package/src/lib/entities/user.entity.js.map +0 -1
- package/src/lib/feature-create-token/index.js +0 -10
- package/src/lib/feature-create-token/index.js.map +0 -1
- package/src/lib/feature-create-token/interfaces.d.ts +0 -39
- package/src/lib/feature-create-token/interfaces.js +0 -3
- package/src/lib/feature-create-token/interfaces.js.map +0 -1
- package/src/lib/feature-create-token/token-payload.provider.d.ts +0 -11
- package/src/lib/feature-create-token/token-payload.provider.js +0 -8
- package/src/lib/feature-create-token/token-payload.provider.js.map +0 -1
- package/src/lib/feature-create-token/token-user.provider.d.ts +0 -7
- package/src/lib/feature-create-token/token-user.provider.js +0 -8
- package/src/lib/feature-create-token/token-user.provider.js.map +0 -1
- package/src/lib/feature-create-token/token-validation.provider.d.ts +0 -10
- package/src/lib/feature-create-token/token-validation.provider.js +0 -8
- package/src/lib/feature-create-token/token-validation.provider.js.map +0 -1
- package/src/lib/feature-create-token/token.config.d.ts +0 -5
- package/src/lib/feature-create-token/token.config.js +0 -14
- package/src/lib/feature-create-token/token.config.js.map +0 -1
- package/src/lib/feature-create-token/token.factory.d.ts +0 -39
- package/src/lib/feature-create-token/token.factory.js +0 -158
- package/src/lib/feature-create-token/token.factory.js.map +0 -1
- package/test-setup.js +0 -1
- package/test-setup.js.map +0 -1
- /package/src/lib/entities/{index.d.ts → index.ts} +0 -0
- /package/src/lib/feature-create-token/{index.d.ts → index.ts} +0 -0
- /package/{test-setup.d.ts → test-setup.ts} +0 -0
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": ["../../../.eslintrc.json"],
|
|
3
|
+
"ignorePatterns": ["!**/*"],
|
|
4
|
+
"rules": {
|
|
5
|
+
"import/order": "off"
|
|
6
|
+
},
|
|
7
|
+
"overrides": [
|
|
8
|
+
{
|
|
9
|
+
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
|
10
|
+
"rules": {}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"files": ["*.ts", "*.tsx"],
|
|
14
|
+
"rules": {}
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"files": ["*.js", "*.jsx"],
|
|
18
|
+
"rules": {}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"files": "package.json",
|
|
22
|
+
"parser": "jsonc-eslint-parser",
|
|
23
|
+
"rules": {}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
}
|
package/README.md
CHANGED
|
@@ -1,6 +1,165 @@
|
|
|
1
|
-
# auth-domain
|
|
1
|
+
# @smartsoft001/auth-domain
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
`npm i @smartsoft001/auth-domain`
|
|
6
|
+
|
|
7
|
+
## Token Factory
|
|
8
|
+
|
|
9
|
+
### create
|
|
10
|
+
Creates a new authentication token based on the provided credentials and grant type.
|
|
11
|
+
|
|
12
|
+
<table>
|
|
13
|
+
<thead>
|
|
14
|
+
<tr>
|
|
15
|
+
<td>Param</td>
|
|
16
|
+
<td>Description</td>
|
|
17
|
+
</tr>
|
|
18
|
+
</thead>
|
|
19
|
+
<tr>
|
|
20
|
+
<td>options.request: IAuthTokenRequest</td>
|
|
21
|
+
<td>The authentication request containing credentials and grant type.</td>
|
|
22
|
+
</tr>
|
|
23
|
+
<tr>
|
|
24
|
+
<td>options.httpReq?: Request</td>
|
|
25
|
+
<td>Optional HTTP request object for context.</td>
|
|
26
|
+
</tr>
|
|
27
|
+
<tr>
|
|
28
|
+
<td>options.payloadProvider?: ITokenPayloadProvider</td>
|
|
29
|
+
<td>Optional provider for customizing JWT payload.</td>
|
|
30
|
+
</tr>
|
|
31
|
+
<tr>
|
|
32
|
+
<td>options.validationProvider?: ITokenValidationProvider</td>
|
|
33
|
+
<td>Optional provider for custom validation rules.</td>
|
|
34
|
+
</tr>
|
|
35
|
+
<tr>
|
|
36
|
+
<td>options.userProvider?: ITokenUserProvider</td>
|
|
37
|
+
<td>Optional provider for custom user retrieval.</td>
|
|
38
|
+
</tr>
|
|
39
|
+
</table>
|
|
40
|
+
|
|
41
|
+
## Interfaces
|
|
42
|
+
|
|
43
|
+
### IAuthTokenRequest
|
|
44
|
+
|
|
45
|
+
<table>
|
|
46
|
+
<thead>
|
|
47
|
+
<tr>
|
|
48
|
+
<td>Property</td>
|
|
49
|
+
<td>Description</td>
|
|
50
|
+
</tr>
|
|
51
|
+
</thead>
|
|
52
|
+
<tr>
|
|
53
|
+
<td>grant_type</td>
|
|
54
|
+
<td>"password" | "refresh_token" | "fb" | "google"</td>
|
|
55
|
+
</tr>
|
|
56
|
+
<tr>
|
|
57
|
+
<td>username?</td>
|
|
58
|
+
<td>Required for password grant type</td>
|
|
59
|
+
</tr>
|
|
60
|
+
<tr>
|
|
61
|
+
<td>password?</td>
|
|
62
|
+
<td>Required for password grant type</td>
|
|
63
|
+
</tr>
|
|
64
|
+
<tr>
|
|
65
|
+
<td>refresh_token?</td>
|
|
66
|
+
<td>Required for refresh_token grant type</td>
|
|
67
|
+
</tr>
|
|
68
|
+
<tr>
|
|
69
|
+
<td>fb_token?</td>
|
|
70
|
+
<td>Required for fb grant type</td>
|
|
71
|
+
</tr>
|
|
72
|
+
<tr>
|
|
73
|
+
<td>google_token?</td>
|
|
74
|
+
<td>Required for google grant type</td>
|
|
75
|
+
</tr>
|
|
76
|
+
<tr>
|
|
77
|
+
<td>scope?</td>
|
|
78
|
+
<td>Optional scope for the token</td>
|
|
79
|
+
</tr>
|
|
80
|
+
<tr>
|
|
81
|
+
<td>client_id?</td>
|
|
82
|
+
<td>Required for password, fb, and google grant types</td>
|
|
83
|
+
</tr>
|
|
84
|
+
</table>
|
|
85
|
+
|
|
86
|
+
### IAuthToken
|
|
87
|
+
|
|
88
|
+
<table>
|
|
89
|
+
<thead>
|
|
90
|
+
<tr>
|
|
91
|
+
<td>Property</td>
|
|
92
|
+
<td>Description</td>
|
|
93
|
+
</tr>
|
|
94
|
+
</thead>
|
|
95
|
+
<tr>
|
|
96
|
+
<td>access_token</td>
|
|
97
|
+
<td>JWT token for authentication</td>
|
|
98
|
+
</tr>
|
|
99
|
+
<tr>
|
|
100
|
+
<td>refresh_token</td>
|
|
101
|
+
<td>Token for obtaining new access tokens</td>
|
|
102
|
+
</tr>
|
|
103
|
+
<tr>
|
|
104
|
+
<td>expired_in</td>
|
|
105
|
+
<td>Token expiration time in seconds</td>
|
|
106
|
+
</tr>
|
|
107
|
+
<tr>
|
|
108
|
+
<td>token_type</td>
|
|
109
|
+
<td>Always 'bearer'</td>
|
|
110
|
+
</tr>
|
|
111
|
+
<tr>
|
|
112
|
+
<td>username?</td>
|
|
113
|
+
<td>Optional username of authenticated user</td>
|
|
114
|
+
</tr>
|
|
115
|
+
</table>
|
|
116
|
+
|
|
117
|
+
## Providers
|
|
118
|
+
|
|
119
|
+
### ITokenPayloadProvider
|
|
120
|
+
|
|
121
|
+
<table>
|
|
122
|
+
<thead>
|
|
123
|
+
<tr>
|
|
124
|
+
<td>Method</td>
|
|
125
|
+
<td>Description</td>
|
|
126
|
+
</tr>
|
|
127
|
+
</thead>
|
|
128
|
+
<tr>
|
|
129
|
+
<td>change(basePayload, data)</td>
|
|
130
|
+
<td>Modifies the JWT payload before token creation</td>
|
|
131
|
+
</tr>
|
|
132
|
+
</table>
|
|
133
|
+
|
|
134
|
+
### ITokenValidationProvider
|
|
135
|
+
|
|
136
|
+
<table>
|
|
137
|
+
<thead>
|
|
138
|
+
<tr>
|
|
139
|
+
<td>Method</td>
|
|
140
|
+
<td>Description</td>
|
|
141
|
+
</tr>
|
|
142
|
+
</thead>
|
|
143
|
+
<tr>
|
|
144
|
+
<td>check(data)</td>
|
|
145
|
+
<td>Performs custom validation during token creation</td>
|
|
146
|
+
</tr>
|
|
147
|
+
</table>
|
|
148
|
+
|
|
149
|
+
### ITokenUserProvider
|
|
150
|
+
|
|
151
|
+
<table>
|
|
152
|
+
<thead>
|
|
153
|
+
<tr>
|
|
154
|
+
<td>Method</td>
|
|
155
|
+
<td>Description</td>
|
|
156
|
+
</tr>
|
|
157
|
+
</thead>
|
|
158
|
+
<tr>
|
|
159
|
+
<td>get(query, request, httpReq?)</td>
|
|
160
|
+
<td>Custom logic for user retrieval during authentication</td>
|
|
161
|
+
</tr>
|
|
162
|
+
</table>
|
|
4
163
|
|
|
5
164
|
## Running unit tests
|
|
6
165
|
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
export default {
|
|
3
|
+
displayName: 'auth-domain',
|
|
4
|
+
preset: '../../../jest.preset.js',
|
|
5
|
+
testEnvironment: 'node',
|
|
6
|
+
transform: {
|
|
7
|
+
'^.+\\.[tj]sx?$': [
|
|
8
|
+
'ts-jest',
|
|
9
|
+
{
|
|
10
|
+
tsConfig: '<rootDir>/tsconfig.spec.json',
|
|
11
|
+
},
|
|
12
|
+
],
|
|
13
|
+
},
|
|
14
|
+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
|
15
|
+
coverageDirectory: '../../../coverage/packages/auth/domain',
|
|
16
|
+
/* TODO: Update to latest Jest snapshotFormat
|
|
17
|
+
* By default Nx has kept the older style of Jest Snapshot formats
|
|
18
|
+
* to prevent breaking of any existing tests with snapshots.
|
|
19
|
+
* It's recommend you update to the latest format.
|
|
20
|
+
* You can do this by removing snapshotFormat property
|
|
21
|
+
* and running tests with --update-snapshot flag.
|
|
22
|
+
* Example: From within the project directory, run "nx test --update-snapshot"
|
|
23
|
+
* More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format
|
|
24
|
+
*/
|
|
25
|
+
snapshotFormat: { escapeString: true, printBasicPrototype: true },
|
|
26
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartsoft001/auth-domain",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Utils
|
|
3
|
+
"version": "2.68.0",
|
|
4
|
+
"description": "Utils for authorization",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/emiljuchnikowski/smartsoft.git"
|
|
@@ -11,34 +11,5 @@
|
|
|
11
11
|
"oauth",
|
|
12
12
|
"angular",
|
|
13
13
|
"nestjs"
|
|
14
|
-
]
|
|
15
|
-
"dependencies": {
|
|
16
|
-
"@angular/common": "16.1.3",
|
|
17
|
-
"@angular/core": "16.1.3",
|
|
18
|
-
"@angular/platform-browser-dynamic": "16.1.3",
|
|
19
|
-
"@nestjs/axios": "3.0.0",
|
|
20
|
-
"@nestjs/common": "^10.0.5",
|
|
21
|
-
"@nestjs/jwt": "^10.1.0",
|
|
22
|
-
"@nestjs/typeorm": "^10.0.0",
|
|
23
|
-
"express": "4.18.2",
|
|
24
|
-
"flatted": "^3.2.4",
|
|
25
|
-
"guid-typescript": "1.0.9",
|
|
26
|
-
"lodash": "^4.17.20",
|
|
27
|
-
"md5": "2.3.0",
|
|
28
|
-
"reflect-metadata": "0.1.13",
|
|
29
|
-
"rxjs": "7.8.1",
|
|
30
|
-
"typeorm": "0.3.17"
|
|
31
|
-
},
|
|
32
|
-
"peerDependencies": {
|
|
33
|
-
"@smartsoft001/domain-core": "1.1.91",
|
|
34
|
-
"@smartsoft001/fb": "1.1.91",
|
|
35
|
-
"@smartsoft001/google": "1.1.91",
|
|
36
|
-
"@smartsoft001/models": "1.1.91",
|
|
37
|
-
"@smartsoft001/users": "1.1.91",
|
|
38
|
-
"@smartsoft001/utils": "1.1.91",
|
|
39
|
-
"util": "0.12.5",
|
|
40
|
-
"tslib": "2.5.3"
|
|
41
|
-
},
|
|
42
|
-
"main": "./src/index.js",
|
|
43
|
-
"types": "./src/index.d.ts"
|
|
14
|
+
]
|
|
44
15
|
}
|
package/project.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "auth-domain",
|
|
3
|
+
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "packages/auth/domain/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"targets": {
|
|
7
|
+
"lint": {
|
|
8
|
+
"executor": "@nx/eslint:lint",
|
|
9
|
+
"outputs": ["{options.outputFile}"],
|
|
10
|
+
"options": {
|
|
11
|
+
"lintFilePatterns": [
|
|
12
|
+
"packages/auth/domain/**/*.{ts,tsx,js,jsx}",
|
|
13
|
+
"packages/auth/domain/package.json"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"test": {
|
|
18
|
+
"executor": "@nx/jest:jest",
|
|
19
|
+
"outputs": ["{workspaceRoot}/coverage/packages/auth/domain"],
|
|
20
|
+
"options": {
|
|
21
|
+
"jestConfig": "packages/auth/domain/jest.config.ts"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"build": {
|
|
25
|
+
"executor": "@nx/esbuild:esbuild",
|
|
26
|
+
"outputs": ["{options.outputPath}"],
|
|
27
|
+
"options": {
|
|
28
|
+
"outputPath": "dist/packages/auth/domain",
|
|
29
|
+
"tsConfig": "packages/auth/domain/tsconfig.lib.json",
|
|
30
|
+
"packageJson": "packages/auth/domain/package.json",
|
|
31
|
+
"main": "packages/auth/domain/src/index.ts",
|
|
32
|
+
"assets": ["packages/auth/domain/*.md"]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"deploy": {
|
|
36
|
+
"executor": "ngx-deploy-npm:deploy",
|
|
37
|
+
"options": {
|
|
38
|
+
"access": "public",
|
|
39
|
+
"distFolderPath": "dist/packages/auth/domain"
|
|
40
|
+
},
|
|
41
|
+
"dependsOn": ["build"]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { User } from './lib/entities/user.entity';
|
|
2
|
+
import { TokenFactory } from './lib/feature-create-token/token.factory';
|
|
3
|
+
|
|
4
|
+
export * from './lib/entities';
|
|
5
|
+
export * from './lib/feature-create-token';
|
|
6
|
+
|
|
7
|
+
export const DOMAIN_SERVICES = [TokenFactory];
|
|
8
|
+
|
|
9
|
+
export const ENTITIES = [User];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
import { IEntity } from '@smartsoft001/domain-core';
|
|
3
|
+
import { IUser, IUserCredentials } from '@smartsoft001/users';
|
|
4
|
+
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
|
5
|
+
|
|
6
|
+
@Entity('users')
|
|
7
|
+
export class User implements IEntity<string>, IUser, IUserCredentials {
|
|
8
|
+
@PrimaryGeneratedColumn()
|
|
9
|
+
id: string;
|
|
10
|
+
|
|
11
|
+
@Column('permissions')
|
|
12
|
+
permissions: Array<string>;
|
|
13
|
+
|
|
14
|
+
@Column('username')
|
|
15
|
+
username: string;
|
|
16
|
+
|
|
17
|
+
@Column('password')
|
|
18
|
+
password: string;
|
|
19
|
+
|
|
20
|
+
@Column('disabled')
|
|
21
|
+
disabled: boolean;
|
|
22
|
+
|
|
23
|
+
@Column('lastLoginDate')
|
|
24
|
+
lastLoginDate: Date;
|
|
25
|
+
|
|
26
|
+
@Column('authRefreshToken')
|
|
27
|
+
authRefreshToken: string;
|
|
28
|
+
|
|
29
|
+
@Column('facebookUserId')
|
|
30
|
+
facebookUserId?: string;
|
|
31
|
+
|
|
32
|
+
@Column('googleUserId')
|
|
33
|
+
googleUserId?: string;
|
|
34
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { IUserCredentials } from '@smartsoft001/users';
|
|
2
|
+
|
|
3
|
+
export type IAuthTokenRequest =
|
|
4
|
+
| IAuthTokenRequestPassword
|
|
5
|
+
| IAuthTokenRequestRefreshToken
|
|
6
|
+
| IAuthTokenRequestCustom
|
|
7
|
+
| IAuthTokenRequestFb
|
|
8
|
+
| IAuthTokenRequestGoogle;
|
|
9
|
+
|
|
10
|
+
export interface IAuthTokenRequestFb extends IUserCredentials {
|
|
11
|
+
grant_type: 'fb';
|
|
12
|
+
fb_token: string;
|
|
13
|
+
fb_user_id?: string;
|
|
14
|
+
scope?: string;
|
|
15
|
+
client_id: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface IAuthTokenRequestGoogle extends IUserCredentials {
|
|
19
|
+
grant_type: 'google';
|
|
20
|
+
google_token: string;
|
|
21
|
+
google_user_id?: string;
|
|
22
|
+
scope?: string;
|
|
23
|
+
client_id: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface IAuthTokenRequestPassword extends IUserCredentials {
|
|
27
|
+
grant_type: 'password';
|
|
28
|
+
username: string;
|
|
29
|
+
password: string;
|
|
30
|
+
scope?: string;
|
|
31
|
+
client_id: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface IAuthTokenRequestRefreshToken {
|
|
35
|
+
grant_type: 'refresh_token';
|
|
36
|
+
refresh_token: string;
|
|
37
|
+
scope?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface IAuthToken {
|
|
41
|
+
access_token: string;
|
|
42
|
+
refresh_token: string;
|
|
43
|
+
expired_in: number;
|
|
44
|
+
token_type: 'bearer';
|
|
45
|
+
username?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface IAuthTokenRequestCustom {
|
|
49
|
+
grant_type: string;
|
|
50
|
+
[key: string]: string;
|
|
51
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
import { IAuthTokenRequest } from './interfaces';
|
|
4
|
+
import { User } from '../entities/user.entity';
|
|
5
|
+
|
|
6
|
+
export const AUTH_TOKEN_PAYLOAD_PROVIDER = 'AUTH_TOKEN_PAYLOAD_PROVIDER';
|
|
7
|
+
|
|
8
|
+
export abstract class ITokenPayloadProvider {
|
|
9
|
+
abstract change(
|
|
10
|
+
basePayload,
|
|
11
|
+
data: {
|
|
12
|
+
request?: IAuthTokenRequest;
|
|
13
|
+
user?: User;
|
|
14
|
+
httpReq?: Request;
|
|
15
|
+
},
|
|
16
|
+
): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
import { IAuthTokenRequest } from './interfaces';
|
|
4
|
+
import { User } from '../entities/user.entity';
|
|
5
|
+
|
|
6
|
+
export const AUTH_TOKEN_USER_PROVIDER = 'AUTH_TOKEN_USER_PROVIDER';
|
|
7
|
+
|
|
8
|
+
export abstract class ITokenUserProvider {
|
|
9
|
+
abstract get(
|
|
10
|
+
baseQuery: Partial<User>,
|
|
11
|
+
request: IAuthTokenRequest,
|
|
12
|
+
httpReq?: Request,
|
|
13
|
+
): Promise<User>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { IAuthTokenRequest } from './interfaces';
|
|
2
|
+
import { User } from '../entities/user.entity';
|
|
3
|
+
|
|
4
|
+
export const AUTH_TOKEN_VALIDATION_PROVIDER = 'AUTH_TOKEN_VALIDATION_PROVIDER';
|
|
5
|
+
|
|
6
|
+
export abstract class ITokenValidationProvider {
|
|
7
|
+
abstract replace?: boolean;
|
|
8
|
+
|
|
9
|
+
abstract check(data: {
|
|
10
|
+
request?: IAuthTokenRequest;
|
|
11
|
+
user?: User;
|
|
12
|
+
}): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { JwtService } from '@nestjs/jwt';
|
|
2
|
+
import { Test } from '@nestjs/testing';
|
|
3
|
+
import { getRepositoryToken } from '@nestjs/typeorm';
|
|
4
|
+
import { DomainValidationError } from '@smartsoft001/domain-core';
|
|
5
|
+
import { FbService } from '@smartsoft001/fb';
|
|
6
|
+
import { GoogleService } from '@smartsoft001/google';
|
|
7
|
+
import { PasswordService } from '@smartsoft001/utils';
|
|
8
|
+
import { Repository } from 'typeorm';
|
|
9
|
+
|
|
10
|
+
import { User } from '../entities';
|
|
11
|
+
import { TokenConfig } from './token.config';
|
|
12
|
+
import { TokenFactory } from './token.factory';
|
|
13
|
+
|
|
14
|
+
describe('auth-domain: TokenFactory', () => {
|
|
15
|
+
let tokenFactory: TokenFactory;
|
|
16
|
+
let repository: Repository<User>;
|
|
17
|
+
let jwtService: JwtService;
|
|
18
|
+
let fbService: FbService;
|
|
19
|
+
let googleService: GoogleService;
|
|
20
|
+
|
|
21
|
+
beforeEach(async () => {
|
|
22
|
+
const module = await Test.createTestingModule({
|
|
23
|
+
providers: [
|
|
24
|
+
TokenFactory,
|
|
25
|
+
{
|
|
26
|
+
provide: TokenConfig,
|
|
27
|
+
useValue: {
|
|
28
|
+
expiredIn: 3600,
|
|
29
|
+
clients: ['test-client'],
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
provide: getRepositoryToken(User),
|
|
34
|
+
useValue: {
|
|
35
|
+
findOne: jest.fn(),
|
|
36
|
+
update: jest.fn(),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
provide: JwtService,
|
|
41
|
+
useValue: {
|
|
42
|
+
sign: jest.fn(),
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
provide: FbService,
|
|
47
|
+
useValue: {
|
|
48
|
+
getUserId: jest.fn(),
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
provide: GoogleService,
|
|
53
|
+
useValue: {
|
|
54
|
+
getUserId: jest.fn(),
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
}).compile();
|
|
59
|
+
|
|
60
|
+
tokenFactory = module.get<TokenFactory>(TokenFactory);
|
|
61
|
+
repository = module.get<Repository<User>>(getRepositoryToken(User));
|
|
62
|
+
jwtService = module.get<JwtService>(JwtService);
|
|
63
|
+
fbService = module.get<FbService>(FbService);
|
|
64
|
+
googleService = module.get<GoogleService>(GoogleService);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('getQuery', () => {
|
|
68
|
+
it('should return query for password grant type', () => {
|
|
69
|
+
const query = TokenFactory.getQuery({
|
|
70
|
+
grant_type: 'password',
|
|
71
|
+
username: 'test',
|
|
72
|
+
});
|
|
73
|
+
expect(query).toEqual({ username: 'test' });
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should return query for refresh_token grant type', () => {
|
|
77
|
+
const query = TokenFactory.getQuery({
|
|
78
|
+
grant_type: 'refresh_token',
|
|
79
|
+
refresh_token: 'token',
|
|
80
|
+
});
|
|
81
|
+
expect(query).toEqual({ authRefreshToken: 'token' });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should return query for fb grant type', () => {
|
|
85
|
+
const query = TokenFactory.getQuery({
|
|
86
|
+
grant_type: 'fb',
|
|
87
|
+
fb_user_id: 'fb123',
|
|
88
|
+
});
|
|
89
|
+
expect(query).toEqual({ facebookUserId: 'fb123' });
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should return query for google grant type', () => {
|
|
93
|
+
const query = TokenFactory.getQuery({
|
|
94
|
+
grant_type: 'google',
|
|
95
|
+
google_user_id: 'g123',
|
|
96
|
+
});
|
|
97
|
+
expect(query).toEqual({ googleUserId: 'g123' });
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should throw error for invalid grant type', () => {
|
|
101
|
+
expect(() => TokenFactory.getQuery({ grant_type: 'invalid' })).toThrow(
|
|
102
|
+
DomainValidationError,
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('checkDisabled', () => {
|
|
108
|
+
it('should throw error when user is disabled', () => {
|
|
109
|
+
const user = { disabled: true } as User;
|
|
110
|
+
expect(() => TokenFactory.checkDisabled(user)).toThrow(
|
|
111
|
+
DomainValidationError,
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('create', () => {
|
|
117
|
+
beforeEach(() => {
|
|
118
|
+
jest.spyOn(PasswordService, 'compare').mockResolvedValue(true);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should create token for valid password credentials', async () => {
|
|
122
|
+
const user = { username: 'test', permissions: ['read'] };
|
|
123
|
+
(repository.findOne as jest.Mock).mockResolvedValue(user);
|
|
124
|
+
(jwtService.sign as jest.Mock).mockReturnValue('signed-token');
|
|
125
|
+
|
|
126
|
+
const result = await tokenFactory.create({
|
|
127
|
+
request: {
|
|
128
|
+
grant_type: 'password',
|
|
129
|
+
username: 'test',
|
|
130
|
+
password: 'test',
|
|
131
|
+
client_id: 'test-client',
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
expect(result.token_type).toBe('bearer');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should create token for valid fb credentials', async () => {
|
|
139
|
+
const user = { username: 'fb-user', permissions: ['read'] };
|
|
140
|
+
(fbService.getUserId as jest.Mock).mockResolvedValue('fb123');
|
|
141
|
+
(repository.findOne as jest.Mock).mockResolvedValue(user);
|
|
142
|
+
(jwtService.sign as jest.Mock).mockReturnValue('signed-token');
|
|
143
|
+
|
|
144
|
+
const result = await tokenFactory.create({
|
|
145
|
+
request: {
|
|
146
|
+
grant_type: 'fb',
|
|
147
|
+
fb_token: 'token',
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
expect(result.token_type).toBe('bearer');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should create token for valid google credentials', async () => {
|
|
155
|
+
const user = { username: 'google-user', permissions: ['read'] };
|
|
156
|
+
(googleService.getUserId as jest.Mock).mockResolvedValue('g123');
|
|
157
|
+
(repository.findOne as jest.Mock).mockResolvedValue(user);
|
|
158
|
+
(jwtService.sign as jest.Mock).mockReturnValue('signed-token');
|
|
159
|
+
|
|
160
|
+
const result = await tokenFactory.create({
|
|
161
|
+
request: {
|
|
162
|
+
grant_type: 'google',
|
|
163
|
+
google_token: 'token',
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
expect(result.token_type).toBe('bearer');
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('should throw error for invalid request', async () => {
|
|
171
|
+
await expect(
|
|
172
|
+
tokenFactory.create({
|
|
173
|
+
request: {} as any,
|
|
174
|
+
}),
|
|
175
|
+
).rejects.toThrow(DomainValidationError);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it('should throw error when user is not found', async () => {
|
|
179
|
+
(repository.findOne as jest.Mock).mockResolvedValue(null);
|
|
180
|
+
|
|
181
|
+
await expect(
|
|
182
|
+
tokenFactory.create({
|
|
183
|
+
request: {
|
|
184
|
+
grant_type: 'password',
|
|
185
|
+
username: 'test',
|
|
186
|
+
password: 'test',
|
|
187
|
+
client_id: 'test-client',
|
|
188
|
+
},
|
|
189
|
+
}),
|
|
190
|
+
).rejects.toThrow(DomainValidationError);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
});
|