dauth-md-node 1.0.1 → 2.0.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 +8 -8
- package/dist/index.d.mts +64 -0
- package/dist/index.d.ts +64 -43
- package/dist/index.js +168 -5
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +135 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +31 -27
- package/src/api/dauth.api.ts +18 -12
- package/src/api/utils/config.ts +6 -1
- package/src/cache.ts +51 -0
- package/src/index.ts +79 -56
- package/dist/api/dauth.api.d.ts +0 -4
- package/dist/api/utils/config.d.ts +0 -3
- package/dist/dauth-md-node.cjs.development.js +0 -453
- package/dist/dauth-md-node.cjs.development.js.map +0 -1
- package/dist/dauth-md-node.cjs.production.min.js +0 -2
- package/dist/dauth-md-node.cjs.production.min.js.map +0 -1
- package/dist/dauth-md-node.esm.js +0 -450
- package/dist/dauth-md-node.esm.js.map +0 -1
package/src/api/dauth.api.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import { getServerBasePath } from './utils/config';
|
|
2
|
-
const fetch = require('node-fetch');
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
interface GetUserResponse {
|
|
4
|
+
response: { status: number };
|
|
5
|
+
data: { user?: any; message?: string };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export async function getUser(
|
|
9
|
+
token: string,
|
|
10
|
+
domainName: string
|
|
11
|
+
): Promise<GetUserResponse> {
|
|
12
12
|
const response = await fetch(
|
|
13
13
|
`${getServerBasePath()}/app/${domainName}/user`,
|
|
14
|
-
|
|
14
|
+
{
|
|
15
|
+
method: 'GET',
|
|
16
|
+
headers: {
|
|
17
|
+
Authorization: token,
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
},
|
|
20
|
+
}
|
|
15
21
|
);
|
|
16
|
-
const data = await response.json();
|
|
17
|
-
return { response, data };
|
|
22
|
+
const data = (await response.json()) as GetUserResponse['data'];
|
|
23
|
+
return { response: { status: response.status }, data };
|
|
18
24
|
}
|
package/src/api/utils/config.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
export const apiVersion = 'v1';
|
|
2
2
|
export const serverDomain = 'dauth.ovh';
|
|
3
3
|
|
|
4
|
-
export function getServerBasePath() {
|
|
4
|
+
export function getServerBasePath(): string {
|
|
5
|
+
if (process.env.DAUTH_URL) {
|
|
6
|
+
const base = process.env.DAUTH_URL.replace(/\/+$/, '');
|
|
7
|
+
return `${base}/api/${apiVersion}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
const isLocalhost = process.env.NODE_ENV === 'development';
|
|
6
11
|
const serverPort = 4012;
|
|
7
12
|
const serverLocalUrl = `http://localhost:${serverPort}/api/${apiVersion}`;
|
package/src/cache.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { IDauthUser } from './index';
|
|
2
|
+
|
|
3
|
+
interface CacheEntry {
|
|
4
|
+
user: IDauthUser;
|
|
5
|
+
expiresAt: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface CacheOptions {
|
|
9
|
+
ttlMs: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class UserCache {
|
|
13
|
+
private store = new Map<string, CacheEntry>();
|
|
14
|
+
private ttlMs: number;
|
|
15
|
+
|
|
16
|
+
constructor(options: CacheOptions) {
|
|
17
|
+
this.ttlMs = options.ttlMs;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get(token: string): IDauthUser | undefined {
|
|
21
|
+
const entry = this.store.get(token);
|
|
22
|
+
if (!entry) return undefined;
|
|
23
|
+
|
|
24
|
+
if (Date.now() > entry.expiresAt) {
|
|
25
|
+
this.store.delete(token);
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return entry.user;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
set(token: string, user: IDauthUser): void {
|
|
33
|
+
if (this.store.size > 1000) {
|
|
34
|
+
this.sweep();
|
|
35
|
+
}
|
|
36
|
+
this.store.set(token, { user, expiresAt: Date.now() + this.ttlMs });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
clear(): void {
|
|
40
|
+
this.store.clear();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private sweep(): void {
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
for (const [key, entry] of this.store) {
|
|
46
|
+
if (now > entry.expiresAt) {
|
|
47
|
+
this.store.delete(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Request,
|
|
3
|
-
NextFunction,
|
|
4
|
-
Response as ExpressResponse,
|
|
5
|
-
Handler,
|
|
6
|
-
} from 'express';
|
|
1
|
+
import { Request, NextFunction, Response as ExpressResponse } from 'express';
|
|
7
2
|
import jwt from 'jsonwebtoken';
|
|
8
3
|
import { getUser } from './api/dauth.api';
|
|
4
|
+
import { UserCache } from './cache';
|
|
5
|
+
import type { CacheOptions } from './cache';
|
|
9
6
|
|
|
10
7
|
export interface IDauthUser {
|
|
11
8
|
_id: string;
|
|
@@ -22,6 +19,9 @@ export interface IDauthUser {
|
|
|
22
19
|
role: string;
|
|
23
20
|
telPrefix: string;
|
|
24
21
|
telSuffix: string;
|
|
22
|
+
birthDate?: string;
|
|
23
|
+
country?: string;
|
|
24
|
+
metadata?: Record<string, unknown>;
|
|
25
25
|
createdAt: Date;
|
|
26
26
|
updatedAt: Date;
|
|
27
27
|
lastLogin: Date;
|
|
@@ -38,76 +38,99 @@ export interface IRequestDauth extends Request {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
export interface DauthOptions {
|
|
42
|
+
domainName: string;
|
|
43
|
+
tsk: string;
|
|
44
|
+
cache?: CacheOptions;
|
|
45
|
+
}
|
|
46
|
+
|
|
41
47
|
interface TCustomResponse extends ExpressResponse {
|
|
42
|
-
status(code: number):
|
|
43
|
-
send(body?:
|
|
48
|
+
status(code: number): this;
|
|
49
|
+
send(body?: unknown): this;
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}: {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return (
|
|
52
|
+
export { UserCache };
|
|
53
|
+
export type { CacheOptions };
|
|
54
|
+
|
|
55
|
+
export const dauth = ({ domainName, tsk, cache }: DauthOptions) => {
|
|
56
|
+
const userCache = cache ? new UserCache(cache) : null;
|
|
57
|
+
|
|
58
|
+
return async (
|
|
54
59
|
req: IRequestDauth,
|
|
55
60
|
res: TCustomResponse,
|
|
56
61
|
next: NextFunction
|
|
57
|
-
)
|
|
62
|
+
) => {
|
|
58
63
|
if (!req.headers.authorization) {
|
|
59
64
|
return res
|
|
60
65
|
.status(403)
|
|
61
66
|
.send({ status: 'token-not-found', message: 'Token not found' });
|
|
62
67
|
}
|
|
68
|
+
|
|
63
69
|
const token = req.headers.authorization.replace(/['"]+/g, '');
|
|
70
|
+
|
|
64
71
|
try {
|
|
65
|
-
jwt.verify(token, tsk
|
|
66
|
-
return getUser(token, domainName)
|
|
67
|
-
.then((getUserFetch: any) => {
|
|
68
|
-
if (getUserFetch.response.status === 404) {
|
|
69
|
-
return res.status(404).send({
|
|
70
|
-
status: 'user-not-found',
|
|
71
|
-
message: getUserFetch.data.message ?? 'User does not exist',
|
|
72
|
-
});
|
|
73
|
-
} else if (getUserFetch.response.status === 500) {
|
|
74
|
-
return res.status(500).send({
|
|
75
|
-
status: 'error',
|
|
76
|
-
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
77
|
-
});
|
|
78
|
-
} else if (getUserFetch.response.status === 200) {
|
|
79
|
-
req.user = getUserFetch.data.user;
|
|
80
|
-
return next();
|
|
81
|
-
} else {
|
|
82
|
-
return res.status(501).send({
|
|
83
|
-
status: 'request-error',
|
|
84
|
-
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
.catch((error: any) => {
|
|
89
|
-
return res.status(500).send({
|
|
90
|
-
status: 'server-error',
|
|
91
|
-
message: error.message ?? 'Dauth server error',
|
|
92
|
-
});
|
|
93
|
-
});
|
|
72
|
+
jwt.verify(token, tsk);
|
|
94
73
|
} catch (error) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
74
|
+
const message =
|
|
75
|
+
error instanceof Error ? error.message : 'Token invalid';
|
|
76
|
+
|
|
77
|
+
if (message === 'jwt expired') {
|
|
78
|
+
return res
|
|
79
|
+
.status(401)
|
|
80
|
+
.send({ status: 'token-expired', message: 'jwt expired' });
|
|
100
81
|
}
|
|
101
|
-
if (
|
|
82
|
+
if (message === 'invalid signature') {
|
|
102
83
|
return res.status(401).send({
|
|
103
84
|
status: 'tsk-not-invalid',
|
|
104
|
-
message:
|
|
85
|
+
message:
|
|
86
|
+
'The TSK variable in the backend middleware is not valid',
|
|
105
87
|
});
|
|
106
88
|
}
|
|
107
|
-
return res
|
|
108
|
-
status
|
|
109
|
-
|
|
89
|
+
return res
|
|
90
|
+
.status(401)
|
|
91
|
+
.send({ status: 'token-invalid', message });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (userCache) {
|
|
95
|
+
const cachedUser = userCache.get(token);
|
|
96
|
+
if (cachedUser) {
|
|
97
|
+
req.user = cachedUser;
|
|
98
|
+
return next();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const getUserFetch = await getUser(token, domainName);
|
|
104
|
+
|
|
105
|
+
if (getUserFetch.response.status === 404) {
|
|
106
|
+
return res.status(404).send({
|
|
107
|
+
status: 'user-not-found',
|
|
108
|
+
message: getUserFetch.data.message ?? 'User does not exist',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (getUserFetch.response.status === 500) {
|
|
112
|
+
return res.status(500).send({
|
|
113
|
+
status: 'error',
|
|
114
|
+
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
if (getUserFetch.response.status === 200) {
|
|
118
|
+
req.user = getUserFetch.data.user;
|
|
119
|
+
if (userCache) {
|
|
120
|
+
userCache.set(token, req.user);
|
|
121
|
+
}
|
|
122
|
+
return next();
|
|
123
|
+
}
|
|
124
|
+
return res.status(501).send({
|
|
125
|
+
status: 'request-error',
|
|
126
|
+
message: getUserFetch.data.message ?? 'Dauth server error',
|
|
110
127
|
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
const message =
|
|
130
|
+
error instanceof Error ? error.message : 'Dauth server error';
|
|
131
|
+
return res
|
|
132
|
+
.status(500)
|
|
133
|
+
.send({ status: 'server-error', message });
|
|
111
134
|
}
|
|
112
135
|
};
|
|
113
136
|
};
|
package/dist/api/dauth.api.d.ts
DELETED