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.
@@ -1,18 +1,24 @@
1
1
  import { getServerBasePath } from './utils/config';
2
- const fetch = require('node-fetch');
3
2
 
4
- export async function getUser(token: string, domainName: string) {
5
- const params = {
6
- method: 'GET',
7
- headers: {
8
- Authorization: token,
9
- 'Content-Type': 'application/json',
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
- params
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
  }
@@ -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): any;
43
- send(body?: any): any;
48
+ status(code: number): this;
49
+ send(body?: unknown): this;
44
50
  }
45
51
 
46
- export const dauth = ({
47
- domainName,
48
- tsk,
49
- }: {
50
- domainName: string;
51
- tsk: string;
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
- ): Handler | void => {
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 as string);
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
- if (error && error?.message === 'jwt expired') {
96
- return res.status(401).send({
97
- status: 'token-expired',
98
- message: error?.message ?? 'Token expired',
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 (error && error?.message === 'invalid signature') {
82
+ if (message === 'invalid signature') {
102
83
  return res.status(401).send({
103
84
  status: 'tsk-not-invalid',
104
- message: 'The TSK variable in the backend middleware is not valid',
85
+ message:
86
+ 'The TSK variable in the backend middleware is not valid',
105
87
  });
106
88
  }
107
- return res.status(401).send({
108
- status: 'token-invalid',
109
- message: error?.message ?? 'Token invalid',
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
  };
@@ -1,4 +0,0 @@
1
- export declare function getUser(token: string, domainName: string): Promise<{
2
- response: any;
3
- data: any;
4
- }>;
@@ -1,3 +0,0 @@
1
- export declare const apiVersion = "v1";
2
- export declare const serverDomain = "dauth.ovh";
3
- export declare function getServerBasePath(): string;