proteum 1.0.2 → 2.0.0-1
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/AGENTS.md +101 -0
- package/agents/codex/AGENTS.md +95 -0
- package/agents/codex/CODING_STYLE.md +71 -0
- package/agents/codex/agents.md.zip +0 -0
- package/agents/codex/client/AGENTS.md +102 -0
- package/agents/codex/client/pages/AGENTS.md +35 -0
- package/agents/codex/server/routes/AGENTS.md +12 -0
- package/agents/codex/server/services/AGENTS.md +137 -0
- package/agents/codex/tests/AGENTS.md +8 -0
- package/cli/app/config.ts +13 -11
- package/cli/app/index.ts +74 -82
- package/cli/bin.js +1 -1
- package/cli/commands/build.ts +51 -14
- package/cli/commands/check.ts +19 -0
- package/cli/commands/deploy/app.ts +4 -8
- package/cli/commands/deploy/web.ts +16 -20
- package/cli/commands/dev.ts +189 -64
- package/cli/commands/devEvents.ts +106 -0
- package/cli/commands/init.ts +63 -57
- package/cli/commands/lint.ts +21 -0
- package/cli/commands/refresh.ts +18 -0
- package/cli/commands/typecheck.ts +18 -0
- package/cli/compiler/client/identite.ts +80 -53
- package/cli/compiler/client/index.ts +139 -213
- package/cli/compiler/common/bundleAnalysis.ts +94 -0
- package/cli/compiler/common/clientManifest.ts +67 -0
- package/cli/compiler/common/controllers.ts +288 -0
- package/cli/compiler/common/files/autres.ts +7 -18
- package/cli/compiler/common/files/images.ts +40 -37
- package/cli/compiler/common/files/style.ts +11 -22
- package/cli/compiler/common/generatedRouteModules.ts +368 -0
- package/cli/compiler/common/index.ts +31 -65
- package/cli/compiler/common/loaders/forbid-ssr-import.js +13 -0
- package/cli/compiler/common/rspackAliases.ts +13 -0
- package/cli/compiler/common/scripts.ts +37 -0
- package/cli/compiler/index.ts +781 -230
- package/cli/compiler/server/index.ts +59 -75
- package/cli/compiler/writeIfChanged.ts +21 -0
- package/cli/index.ts +71 -72
- package/cli/paths.ts +51 -57
- package/cli/print.ts +17 -11
- package/cli/tsconfig.json +5 -4
- package/cli/utils/agents.ts +100 -0
- package/cli/utils/check.ts +71 -0
- package/cli/utils/index.ts +1 -3
- package/cli/utils/keyboard.ts +8 -25
- package/cli/utils/runProcess.ts +30 -0
- package/client/app/component.tsx +29 -29
- package/client/app/index.ts +36 -57
- package/client/app/service.ts +7 -12
- package/client/app.tsconfig.json +2 -2
- package/client/components/Dialog/Manager.ssr.tsx +40 -0
- package/client/components/Dialog/Manager.tsx +119 -150
- package/client/components/Dialog/status.tsx +3 -3
- package/client/components/index.ts +1 -1
- package/client/components/types.d.ts +1 -3
- package/client/dev/hmr.ts +65 -0
- package/client/global.d.ts +2 -2
- package/client/hooks.ts +6 -9
- package/client/index.ts +2 -1
- package/client/islands/index.ts +7 -0
- package/client/islands/useDeferredModule.ts +199 -0
- package/client/pages/_layout/index.tsx +4 -12
- package/client/pages/useHeader.tsx +14 -21
- package/client/router.ts +27 -0
- package/client/services/router/components/Link.tsx +34 -27
- package/client/services/router/components/Page.tsx +6 -14
- package/client/services/router/components/router.ssr.tsx +36 -0
- package/client/services/router/components/router.tsx +63 -83
- package/client/services/router/index.tsx +185 -220
- package/client/services/router/request/api.ts +97 -119
- package/client/services/router/request/history.ts +2 -2
- package/client/services/router/request/index.ts +13 -12
- package/client/services/router/request/multipart.ts +72 -62
- package/client/services/router/response/index.tsx +68 -61
- package/client/services/router/response/page.ts +28 -32
- package/client/utils/dom.ts +17 -33
- package/common/app/index.ts +3 -3
- package/common/data/chaines/index.ts +22 -23
- package/common/data/dates.ts +35 -70
- package/common/data/markdown.ts +42 -39
- package/common/dev/serverHotReload.ts +26 -0
- package/common/errors/index.tsx +110 -142
- package/common/router/contracts.ts +29 -0
- package/common/router/index.ts +89 -108
- package/common/router/layouts.ts +34 -47
- package/common/router/pageSetup.ts +50 -0
- package/common/router/register.ts +53 -24
- package/common/router/request/api.ts +30 -36
- package/common/router/request/index.ts +2 -8
- package/common/router/response/index.ts +8 -15
- package/common/router/response/page.ts +70 -58
- package/common/utils.ts +1 -1
- package/doc/TODO.md +1 -1
- package/eslint.js +62 -0
- package/package.json +14 -49
- package/prettier.config.cjs +9 -0
- package/scripts/cleanup-generated-controllers.ts +62 -0
- package/scripts/fix-reference-app-typing.ts +490 -0
- package/scripts/refactor-client-app-imports.ts +244 -0
- package/scripts/refactor-client-pages.ts +587 -0
- package/scripts/refactor-server-controllers.ts +470 -0
- package/scripts/refactor-server-runtime-aliases.ts +360 -0
- package/scripts/restore-client-app-import-files.ts +41 -0
- package/scripts/restore-files-from-git-head.ts +20 -0
- package/scripts/update-codex-agents.ts +35 -0
- package/server/app/commands.ts +35 -64
- package/server/app/container/config.ts +48 -59
- package/server/app/container/console/index.ts +202 -248
- package/server/app/container/index.ts +33 -71
- package/server/app/controller/index.ts +61 -0
- package/server/app/index.ts +39 -105
- package/server/app/service/container.ts +41 -42
- package/server/app/service/index.ts +120 -147
- package/server/context.ts +1 -1
- package/server/index.ts +25 -1
- package/server/services/auth/index.ts +75 -115
- package/server/services/auth/router/index.ts +31 -32
- package/server/services/auth/router/request.ts +14 -16
- package/server/services/cron/CronTask.ts +13 -26
- package/server/services/cron/index.ts +14 -36
- package/server/services/disks/driver.ts +40 -58
- package/server/services/disks/drivers/local/index.ts +79 -90
- package/server/services/disks/drivers/s3/index.ts +116 -163
- package/server/services/disks/index.ts +23 -38
- package/server/services/email/index.ts +45 -104
- package/server/services/email/utils.ts +14 -27
- package/server/services/fetch/index.ts +53 -85
- package/server/services/prisma/Facet.ts +39 -91
- package/server/services/prisma/index.ts +74 -110
- package/server/services/router/generatedRuntime.ts +29 -0
- package/server/services/router/http/index.ts +78 -73
- package/server/services/router/http/multipart.ts +19 -42
- package/server/services/router/index.ts +378 -365
- package/server/services/router/request/api.ts +26 -25
- package/server/services/router/request/index.ts +44 -51
- package/server/services/router/request/service.ts +7 -11
- package/server/services/router/request/validation/zod.ts +111 -148
- package/server/services/router/response/index.ts +110 -125
- package/server/services/router/response/mask/Filter.ts +31 -72
- package/server/services/router/response/mask/index.ts +8 -15
- package/server/services/router/response/mask/selecteurs.ts +11 -25
- package/server/services/router/response/page/clientManifest.ts +25 -0
- package/server/services/router/response/page/document.tsx +199 -127
- package/server/services/router/response/page/index.tsx +89 -94
- package/server/services/router/service.ts +13 -15
- package/server/services/schema/index.ts +17 -26
- package/server/services/schema/request.ts +19 -33
- package/server/services/schema/router/index.ts +8 -11
- package/server/services/security/encrypt/aes/index.ts +15 -35
- package/server/utils/slug.ts +29 -35
- package/skills/clean-project-code/SKILL.md +63 -0
- package/skills/clean-project-code/agents/openai.yaml +4 -0
- package/tsconfig.common.json +4 -3
- package/tsconfig.json +4 -1
- package/types/aliases.d.ts +17 -21
- package/types/controller-input.test.ts +48 -0
- package/types/express-extra.d.ts +6 -0
- package/types/global/constants.d.ts +13 -0
- package/types/global/express-extra.d.ts +6 -0
- package/types/global/modules.d.ts +13 -16
- package/types/global/utils.d.ts +17 -49
- package/types/global/vendors.d.ts +62 -0
- package/types/icons.d.ts +65 -1
- package/types/uuid.d.ts +3 -0
- package/types/vendors.d.ts +62 -0
- package/cli/compiler/common/babel/index.ts +0 -170
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +0 -586
- package/cli/compiler/common/babel/routes/imports.ts +0 -127
- package/cli/compiler/common/babel/routes/routes.ts +0 -1130
- package/client/services/captcha/index.ts +0 -67
- package/client/services/socket/index.ts +0 -147
- package/common/data/rte/nodes.ts +0 -83
- package/common/data/stats.ts +0 -90
- package/common/utils/rte.ts +0 -183
- package/server/services/auth/old.ts +0 -277
- package/server/services/cache/commands.ts +0 -41
- package/server/services/cache/index.ts +0 -297
- package/server/services/cache/service.json +0 -6
- package/server/services/socket/index.ts +0 -162
- package/server/services/socket/scope.ts +0 -226
- package/server/services/socket/service.json +0 -6
- package/server/services_old/SocketClient.ts +0 -92
- package/server/services_old/Token.old.ts +0 -97
|
@@ -8,12 +8,9 @@ import type express from 'express';
|
|
|
8
8
|
import type http from 'http';
|
|
9
9
|
|
|
10
10
|
// Core
|
|
11
|
-
import { Application } from '@server/app';
|
|
11
|
+
import type { Application } from '@server/app/index';
|
|
12
12
|
import Service from '@server/app/service';
|
|
13
|
-
import type
|
|
14
|
-
import {
|
|
15
|
-
default as Router, Request as ServerRequest,
|
|
16
|
-
} from '@server/services/router';
|
|
13
|
+
import { type TAnyRouter, Request as ServerRequest } from '@server/services/router';
|
|
17
14
|
import { InputError, AuthRequired, Forbidden } from '@common/errors';
|
|
18
15
|
|
|
19
16
|
/*----------------------------------
|
|
@@ -44,18 +41,12 @@ declare global {
|
|
|
44
41
|
* - If the app does not define a feature catalog, this defaults to `string`.
|
|
45
42
|
* - Otherwise it becomes the string keys of `ProteumAuthFeatureCatalog`.
|
|
46
43
|
*/
|
|
47
|
-
type FeatureKeys =
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
: Extract<keyof ProteumAuthFeatureCatalog, string>
|
|
51
|
-
);
|
|
44
|
+
type FeatureKeys = keyof ProteumAuthFeatureCatalog extends never
|
|
45
|
+
? string
|
|
46
|
+
: Extract<keyof ProteumAuthFeatureCatalog, string>;
|
|
52
47
|
}
|
|
53
48
|
|
|
54
|
-
export type TUserRole = (
|
|
55
|
-
typeof UserRoles[number]
|
|
56
|
-
|
|
|
57
|
-
Extract<keyof ProteumAuthRoleCatalog, string>
|
|
58
|
-
);
|
|
49
|
+
export type TUserRole = (typeof UserRoles)[number] | Extract<keyof ProteumAuthRoleCatalog, string>;
|
|
59
50
|
|
|
60
51
|
export type THttpRequest = express.Request | http.IncomingMessage;
|
|
61
52
|
|
|
@@ -65,40 +56,37 @@ export type TFeatureKey = FeatureKeys;
|
|
|
65
56
|
- CONFIG
|
|
66
57
|
----------------------------------*/
|
|
67
58
|
|
|
68
|
-
const LogPrefix = '[auth]'
|
|
59
|
+
const LogPrefix = '[auth]';
|
|
69
60
|
|
|
70
|
-
export const UserRoles = ['USER', 'ADMIN', 'TEST', 'DEV'] as const
|
|
61
|
+
export const UserRoles = ['USER', 'ADMIN', 'TEST', 'DEV'] as const;
|
|
71
62
|
|
|
72
63
|
/*----------------------------------
|
|
73
64
|
- SERVICE CONVIG
|
|
74
65
|
----------------------------------*/
|
|
75
66
|
|
|
76
67
|
export type TConfig = {
|
|
77
|
-
debug: boolean
|
|
78
|
-
logoutUrl: string
|
|
68
|
+
debug: boolean;
|
|
69
|
+
logoutUrl: string;
|
|
79
70
|
jwt: {
|
|
80
71
|
// 2048 bits
|
|
81
|
-
key: string
|
|
82
|
-
expiration: number
|
|
83
|
-
}
|
|
84
|
-
}
|
|
72
|
+
key: string;
|
|
73
|
+
expiration: number;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
85
76
|
|
|
86
|
-
export type THooks = {
|
|
87
|
-
|
|
88
|
-
}
|
|
77
|
+
export type THooks = {};
|
|
89
78
|
|
|
90
79
|
export type TBasicUser = {
|
|
91
|
-
type: string
|
|
92
|
-
name: string | null
|
|
93
|
-
email: string
|
|
94
|
-
roles: string[]
|
|
95
|
-
|
|
80
|
+
type: string;
|
|
81
|
+
name: string | null;
|
|
82
|
+
email: string;
|
|
83
|
+
roles: string[];
|
|
84
|
+
locale?: string | null;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type TBasicJwtSession = { apiKey: string } | { email: string };
|
|
96
88
|
|
|
97
|
-
|
|
98
|
-
{ apiKey: string }
|
|
99
|
-
|
|
|
100
|
-
{ email: string }
|
|
101
|
-
)
|
|
89
|
+
type TApiKeySession = { apiKey: string; accountType?: string };
|
|
102
90
|
|
|
103
91
|
/*----------------------------------
|
|
104
92
|
- SERVICE
|
|
@@ -109,27 +97,24 @@ export default abstract class AuthService<
|
|
|
109
97
|
TJwtSession extends TBasicJwtSession = TBasicJwtSession,
|
|
110
98
|
TRequest extends ServerRequest<TAnyRouter> = ServerRequest<TAnyRouter>,
|
|
111
99
|
> extends Service<TConfig, THooks, TApplication, TApplication> {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser | null>;
|
|
100
|
+
public login?(request: TRequest, email: string): Promise<unknown>;
|
|
101
|
+
public abstract decodeSession(jwt: TJwtSession, req: THttpRequest): Promise<TUser | null>;
|
|
115
102
|
|
|
116
103
|
// https://beeceptor.com/docs/concepts/authorization-header/#examples
|
|
117
|
-
public async decode(
|
|
118
|
-
public async decode(
|
|
119
|
-
public async decode(
|
|
104
|
+
public async decode(req: THttpRequest, withData: true): Promise<TUser | null>;
|
|
105
|
+
public async decode(req: THttpRequest, withData?: false): Promise<TJwtSession | null>;
|
|
106
|
+
public async decode(req: THttpRequest, withData: boolean = false): Promise<TJwtSession | TUser | null> {
|
|
107
|
+
const requestCookies = 'cookies' in req ? req.cookies : undefined;
|
|
108
|
+
this.config.debug && console.log(LogPrefix, 'Decode:', { cookie: requestCookies?.['authorization'] });
|
|
120
109
|
|
|
121
|
-
this.config.debug && console.log(LogPrefix, 'Decode:', { cookie: req.cookies['authorization'] });
|
|
122
|
-
|
|
123
110
|
// Get auth token
|
|
124
111
|
const authMethod = this.getAuthMethod(req);
|
|
125
|
-
if (authMethod === null)
|
|
126
|
-
return null;
|
|
112
|
+
if (authMethod === null) return null;
|
|
127
113
|
const { tokenType, token } = authMethod;
|
|
128
114
|
|
|
129
115
|
// Get auth session
|
|
130
116
|
const session = this.getAuthSession(tokenType, token);
|
|
131
|
-
if (session === null)
|
|
132
|
-
return null;
|
|
117
|
+
if (session === null) return null;
|
|
133
118
|
|
|
134
119
|
// Return email only
|
|
135
120
|
if (!withData) {
|
|
@@ -140,87 +125,70 @@ export default abstract class AuthService<
|
|
|
140
125
|
// Deserialize full user data
|
|
141
126
|
this.config.debug && console.log(LogPrefix, `Deserialize user`, session);
|
|
142
127
|
const user = await this.decodeSession(session, req);
|
|
143
|
-
if (user === null)
|
|
144
|
-
return null;
|
|
128
|
+
if (user === null) return null;
|
|
145
129
|
|
|
146
130
|
this.config.debug && console.log(LogPrefix, `Deserialized user:`, user.name);
|
|
147
131
|
|
|
148
|
-
return {
|
|
149
|
-
...user,
|
|
150
|
-
_token: token
|
|
151
|
-
};
|
|
132
|
+
return { ...user, _token: token };
|
|
152
133
|
}
|
|
153
134
|
|
|
154
|
-
private getAuthMethod(
|
|
155
|
-
|
|
135
|
+
private getAuthMethod(req: THttpRequest): null | { token: string; tokenType?: string } {
|
|
156
136
|
let token: string | undefined;
|
|
157
137
|
let tokenType: string | undefined;
|
|
158
138
|
if (typeof req.headers['authorization'] === 'string') {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
} else if (('cookies' in req) && typeof req.cookies['authorization'] === 'string') {
|
|
163
|
-
|
|
139
|
+
[tokenType, token] = req.headers['authorization'].split(' ');
|
|
140
|
+
} else if ('cookies' in req && typeof req.cookies['authorization'] === 'string') {
|
|
164
141
|
token = req.cookies['authorization'];
|
|
165
142
|
tokenType = 'Bearer';
|
|
143
|
+
} else return null;
|
|
166
144
|
|
|
167
|
-
|
|
168
|
-
return null;
|
|
169
|
-
|
|
170
|
-
if (token === undefined)
|
|
171
|
-
return null;
|
|
145
|
+
if (token === undefined) return null;
|
|
172
146
|
|
|
173
147
|
return { tokenType, token };
|
|
174
148
|
}
|
|
175
149
|
|
|
176
|
-
private getAuthSession(
|
|
177
|
-
|
|
150
|
+
private getAuthSession(tokenType: string | undefined, token: string): TJwtSession | null {
|
|
178
151
|
let session: TJwtSession;
|
|
179
152
|
|
|
180
153
|
// API Key
|
|
181
154
|
if (tokenType === 'Apikey') {
|
|
182
|
-
|
|
183
155
|
const [accountType] = token.split('-');
|
|
156
|
+
const apiKeySession = { accountType, apiKey: token } satisfies TApiKeySession;
|
|
184
157
|
|
|
185
158
|
this.config.debug && console.log(LogPrefix, `Auth via API Key`, token);
|
|
186
|
-
session =
|
|
159
|
+
session = apiKeySession as TJwtSession & TApiKeySession;
|
|
187
160
|
|
|
188
|
-
|
|
161
|
+
// JWT
|
|
189
162
|
} else if (tokenType === 'Bearer') {
|
|
190
163
|
this.config.debug && console.log(LogPrefix, `Auth via JWT token`, token);
|
|
191
164
|
try {
|
|
192
|
-
session = jwt.verify(token, this.config.jwt.key, {
|
|
193
|
-
maxAge: this.config.jwt.expiration
|
|
194
|
-
});
|
|
165
|
+
session = jwt.verify(token, this.config.jwt.key, {
|
|
166
|
+
maxAge: this.config.jwt.expiration,
|
|
167
|
+
}) as TJwtSession;
|
|
195
168
|
} catch (error) {
|
|
196
|
-
console.warn(LogPrefix,
|
|
169
|
+
console.warn(LogPrefix, 'Failed to decode jwt token:', token);
|
|
197
170
|
return null;
|
|
198
171
|
//throw new Forbidden(`The JWT token provided in the Authorization header is invalid`);
|
|
199
172
|
}
|
|
200
|
-
} else
|
|
201
|
-
|
|
202
|
-
//throw new InputError(`The authorization scheme provided in the Authorization header is unsupported.`);
|
|
173
|
+
} else return null;
|
|
174
|
+
//throw new InputError(`The authorization scheme provided in the Authorization header is unsupported.`);
|
|
203
175
|
|
|
204
176
|
return session;
|
|
205
177
|
}
|
|
206
178
|
|
|
207
|
-
public createSession(
|
|
208
|
-
|
|
179
|
+
public createSession(session: TJwtSession, request2: TRequest): string {
|
|
209
180
|
this.config.debug && console.info(LogPrefix, `Creating new session:`, session);
|
|
210
181
|
|
|
211
182
|
const token = jwt.sign(session, this.config.jwt.key);
|
|
212
183
|
|
|
213
184
|
this.config.debug && console.info(LogPrefix, `Generated JWT token for session:` + token);
|
|
214
185
|
|
|
215
|
-
request2.res.cookie('authorization', token, {
|
|
216
|
-
maxAge: this.config.jwt.expiration,
|
|
217
|
-
});
|
|
186
|
+
request2.res.cookie('authorization', token, { maxAge: this.config.jwt.expiration });
|
|
218
187
|
|
|
219
188
|
return token;
|
|
220
189
|
}
|
|
221
190
|
|
|
222
|
-
public logout(
|
|
223
|
-
|
|
191
|
+
public logout(request: TRequest) {
|
|
224
192
|
const user = request.user;
|
|
225
193
|
if (!user) return;
|
|
226
194
|
|
|
@@ -228,58 +196,50 @@ export default abstract class AuthService<
|
|
|
228
196
|
request.res.clearCookie('authorization');
|
|
229
197
|
}
|
|
230
198
|
|
|
231
|
-
public check(
|
|
232
|
-
request: TRequest,
|
|
233
|
-
role?: TUserRole | false,
|
|
234
|
-
): TUser | null;
|
|
199
|
+
public check(request: TRequest, role?: TUserRole | boolean): TUser | null;
|
|
235
200
|
|
|
236
|
-
public check(
|
|
237
|
-
request: TRequest,
|
|
238
|
-
role: TUserRole | false,
|
|
239
|
-
feature: FeatureKeys,
|
|
240
|
-
action?: string,
|
|
241
|
-
): TUser | null;
|
|
201
|
+
public check(request: TRequest, role: TUserRole | boolean, feature: FeatureKeys, action?: string): TUser | null;
|
|
242
202
|
|
|
243
203
|
public check(
|
|
244
204
|
request: TRequest,
|
|
245
|
-
role: TUserRole |
|
|
205
|
+
role: TUserRole | boolean = 'USER',
|
|
246
206
|
feature?: FeatureKeys,
|
|
247
207
|
action?: string,
|
|
248
208
|
): TUser | null {
|
|
249
|
-
|
|
209
|
+
const normalizedRole = role === true ? 'USER' : role;
|
|
250
210
|
const user = request.user;
|
|
251
211
|
|
|
252
|
-
this.config.debug &&
|
|
212
|
+
this.config.debug &&
|
|
213
|
+
console.warn(LogPrefix, `Check auth, role = ${normalizedRole}. Current user =`, user?.name, feature);
|
|
253
214
|
|
|
254
215
|
if (user === undefined) {
|
|
255
|
-
|
|
256
216
|
throw new Error(`request.user has not been decoded.`);
|
|
257
217
|
|
|
258
|
-
|
|
259
|
-
} else if (
|
|
260
|
-
|
|
218
|
+
// Shoudln't be logged
|
|
219
|
+
} else if (normalizedRole === false) {
|
|
261
220
|
return user as TUser;
|
|
262
221
|
|
|
263
|
-
|
|
222
|
+
// Not connected
|
|
264
223
|
} else if (user === null) {
|
|
265
|
-
|
|
266
|
-
console.warn(LogPrefix, "Refusé pour anonyme (" + request.ip + ")");
|
|
224
|
+
console.warn(LogPrefix, 'Refusé pour anonyme (' + request.ip + ')');
|
|
267
225
|
throw new AuthRequired('Please login to continue', feature as any, action as any);
|
|
268
|
-
|
|
269
|
-
// Insufficient permissions
|
|
270
|
-
} else if (!user.roles.includes(role)) {
|
|
271
|
-
|
|
272
|
-
console.warn(LogPrefix, "Refusé: " + role + " pour " + user.name + " (" + (user.roles || 'role inconnu') + ")");
|
|
273
226
|
|
|
274
|
-
|
|
227
|
+
// Insufficient permissions
|
|
228
|
+
} else if (!user.roles.includes(normalizedRole)) {
|
|
229
|
+
console.warn(
|
|
230
|
+
LogPrefix,
|
|
231
|
+
'Refusé: ' + normalizedRole + ' pour ' + user.name + ' (' + (user.roles || 'role inconnu') + ')',
|
|
232
|
+
);
|
|
275
233
|
|
|
234
|
+
throw new Forbidden('You do not have sufficient permissions to access this resource.');
|
|
276
235
|
} else {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
236
|
+
this.config.debug &&
|
|
237
|
+
console.warn(
|
|
238
|
+
LogPrefix,
|
|
239
|
+
'Autorisé ' + normalizedRole + ' pour ' + user.name + ' (' + user.roles + ')',
|
|
240
|
+
);
|
|
280
241
|
}
|
|
281
242
|
|
|
282
243
|
return user as TUser;
|
|
283
244
|
}
|
|
284
|
-
|
|
285
245
|
}
|
|
@@ -5,12 +5,15 @@
|
|
|
5
5
|
// Npm
|
|
6
6
|
|
|
7
7
|
// Core
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import {
|
|
9
|
+
Request as ServerRequest,
|
|
10
|
+
Response as ServerResponse,
|
|
11
|
+
TAnyRoute,
|
|
12
|
+
RouterService,
|
|
13
|
+
TAnyRouter,
|
|
11
14
|
} from '@server/services/router';
|
|
12
15
|
|
|
13
|
-
import type { Application } from '@server/app';
|
|
16
|
+
import type { Application } from '@server/app/index';
|
|
14
17
|
|
|
15
18
|
import type { TRouterServiceArgs } from '@server/services/router/service';
|
|
16
19
|
|
|
@@ -22,7 +25,6 @@ import UsersRequestService from './request';
|
|
|
22
25
|
- TYPES
|
|
23
26
|
----------------------------------*/
|
|
24
27
|
|
|
25
|
-
|
|
26
28
|
/*----------------------------------
|
|
27
29
|
- CONFIG
|
|
28
30
|
----------------------------------*/
|
|
@@ -34,62 +36,59 @@ const LogPrefix = '[router][auth]';
|
|
|
34
36
|
----------------------------------*/
|
|
35
37
|
export default class AuthenticationRouterService<
|
|
36
38
|
TApplication extends Application = Application,
|
|
37
|
-
TUser extends TBasicUser = TApplication[
|
|
39
|
+
TUser extends TBasicUser = TApplication['app']['userType'],
|
|
38
40
|
TRouter extends TAnyRouter = TAnyRouter,
|
|
39
41
|
TRequest extends ServerRequest<TRouter> = ServerRequest<TRouter>,
|
|
40
|
-
> extends RouterService<
|
|
41
|
-
|
|
42
|
+
> extends RouterService<
|
|
43
|
+
{ users: UsersService<TUser, TApplication> },
|
|
44
|
+
TRouter,
|
|
45
|
+
UsersRequestService<TRouter, TUser, TRequest>
|
|
46
|
+
> {
|
|
42
47
|
/*----------------------------------
|
|
43
48
|
- LIFECYCLE
|
|
44
49
|
----------------------------------*/
|
|
45
50
|
|
|
46
|
-
public users: UsersService<TUser,
|
|
51
|
+
public users: UsersService<TUser, TApplication>;
|
|
47
52
|
|
|
48
|
-
public constructor(
|
|
49
|
-
|
|
53
|
+
public constructor(
|
|
54
|
+
getConfig: TRouterServiceArgs<{ users: UsersService<TUser, TApplication> }, TRouter>[0],
|
|
55
|
+
app: TApplication,
|
|
56
|
+
) {
|
|
57
|
+
super(getConfig, app);
|
|
50
58
|
|
|
51
59
|
this.users = this.config.users;
|
|
52
60
|
}
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
public async ready() {
|
|
56
63
|
// Decode current user
|
|
57
64
|
this.parent.on('request', async (request: TRequest) => {
|
|
58
|
-
|
|
59
65
|
// TODO: Typings. (context.user ?)
|
|
60
|
-
const decoded = await this.users.decode(
|
|
66
|
+
const decoded = await this.users.decode(request.req, true);
|
|
61
67
|
|
|
62
68
|
request.user = decoded || null;
|
|
63
|
-
})
|
|
69
|
+
});
|
|
64
70
|
|
|
65
71
|
// Check route permissions
|
|
66
|
-
this.parent.on('resolved', async (
|
|
67
|
-
route: TAnyRoute,
|
|
68
|
-
request: TRequest,
|
|
69
|
-
response: ServerResponse<TRouter>
|
|
70
|
-
) => {
|
|
71
|
-
|
|
72
|
+
this.parent.on('resolved', async (route: TAnyRoute, request: TRequest, response: ServerResponse<TRouter>) => {
|
|
72
73
|
if (route.options.auth !== undefined) {
|
|
73
|
-
|
|
74
74
|
// Basic auth check
|
|
75
|
-
|
|
75
|
+
const requiredRole = route.options.auth === true ? 'USER' : route.options.auth;
|
|
76
|
+
this.users.check(request, requiredRole as TUserRole | false);
|
|
76
77
|
|
|
77
78
|
// Redirect to logged page
|
|
78
79
|
if (route.options.auth === false && request.user && route.options.redirectLogged)
|
|
79
80
|
response.redirect(route.options.redirectLogged);
|
|
80
81
|
}
|
|
81
|
-
})
|
|
82
|
+
});
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
85
|
+
public async shutdown() {}
|
|
87
86
|
|
|
88
87
|
/*----------------------------------
|
|
89
88
|
- ROUTER SERVICE LIFECYCLE
|
|
90
89
|
----------------------------------*/
|
|
91
90
|
|
|
92
|
-
public requestService(
|
|
93
|
-
return new UsersRequestService(
|
|
94
|
-
}
|
|
95
|
-
}
|
|
91
|
+
public requestService(request: TRequest): UsersRequestService<TRouter, TUser, TRequest> {
|
|
92
|
+
return new UsersRequestService(request, this);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import jwt from 'jsonwebtoken';
|
|
7
7
|
|
|
8
8
|
// Core
|
|
9
|
-
import type {
|
|
9
|
+
import type { Request as ServerRequest, TAnyRouter } from '@server/services/router';
|
|
10
10
|
import RequestService from '@server/services/router/request/service';
|
|
11
11
|
|
|
12
12
|
// Specific
|
|
@@ -25,23 +25,24 @@ import type { TBasicUser } from '@server/services/auth';
|
|
|
25
25
|
----------------------------------*/
|
|
26
26
|
export default class UsersRequestService<
|
|
27
27
|
TRouter extends TAnyRouter,
|
|
28
|
-
TUser extends TBasicUser
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
public constructor(
|
|
32
|
-
request:
|
|
33
|
-
public auth: AuthenticationRouterService,
|
|
28
|
+
TUser extends TBasicUser,
|
|
29
|
+
TRequest extends ServerRequest<TRouter> = ServerRequest<TRouter>,
|
|
30
|
+
> extends RequestService<TRequest> {
|
|
31
|
+
public constructor(
|
|
32
|
+
request: TRequest,
|
|
33
|
+
public auth: AuthenticationRouterService<TRouter['app'], TUser, TRouter, TRequest>,
|
|
34
34
|
public users = auth.users,
|
|
35
35
|
) {
|
|
36
36
|
super(request);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
public login(
|
|
40
|
-
|
|
39
|
+
public login(email: string) {
|
|
40
|
+
if (!this.users.login) throw new Error('The current auth service does not implement login().');
|
|
41
|
+
return this.users.login(this.request, email);
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
public logout() {
|
|
44
|
-
return this.users.logout(
|
|
45
|
+
return this.users.logout(this.request);
|
|
45
46
|
}
|
|
46
47
|
|
|
47
48
|
public check(): TUser;
|
|
@@ -55,11 +56,8 @@ export default class UsersRequestService<
|
|
|
55
56
|
|
|
56
57
|
public check(role: false, feature: FeatureKeys, action?: string): null;
|
|
57
58
|
|
|
58
|
-
public check(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
action?: string
|
|
62
|
-
) {
|
|
63
|
-
return this.users.check( this.request, role, feature, action ) as any;
|
|
59
|
+
public check(role: TUserRole | false = 'USER', feature?: FeatureKeys | null, action?: string) {
|
|
60
|
+
if (feature === null || feature === undefined) return this.users.check(this.request, role);
|
|
61
|
+
return this.users.check(this.request, role, feature, action);
|
|
64
62
|
}
|
|
65
63
|
}
|
|
@@ -12,14 +12,13 @@ import cronParser, { CronExpression } from 'cron-parser';
|
|
|
12
12
|
import type CronManager from '.';
|
|
13
13
|
|
|
14
14
|
export type TFrequence = string | Date;
|
|
15
|
-
export type TRunner = () => Promise<any
|
|
15
|
+
export type TRunner = () => Promise<any>;
|
|
16
16
|
|
|
17
17
|
/*----------------------------------
|
|
18
18
|
- CLASS
|
|
19
19
|
----------------------------------*/
|
|
20
20
|
export default class CronTask {
|
|
21
|
-
|
|
22
|
-
public cron?: CronExpression
|
|
21
|
+
public cron?: CronExpression;
|
|
23
22
|
public nextInvocation?: Date;
|
|
24
23
|
|
|
25
24
|
public constructor(
|
|
@@ -27,60 +26,48 @@ export default class CronTask {
|
|
|
27
26
|
public nom: string,
|
|
28
27
|
next: TFrequence,
|
|
29
28
|
public runner: TRunner,
|
|
30
|
-
public autoexec?: boolean
|
|
29
|
+
public autoexec?: boolean,
|
|
31
30
|
) {
|
|
32
|
-
|
|
33
31
|
this.manager.config.debug && console.info(`[cron][${this.nom}] Enregistrement de la tâche`);
|
|
34
32
|
|
|
35
33
|
this.schedule(next);
|
|
36
|
-
|
|
37
34
|
}
|
|
38
35
|
|
|
39
36
|
public schedule(next: TFrequence) {
|
|
40
|
-
|
|
41
37
|
this.cron = undefined;
|
|
42
38
|
|
|
43
39
|
// Cron expression
|
|
44
40
|
if (typeof next === 'string') {
|
|
45
|
-
|
|
46
41
|
this.cron = cronParser.parseExpression(next);
|
|
47
42
|
this.nextInvocation = this.cron.next().toDate();
|
|
48
43
|
|
|
49
|
-
this.manager.config.debug &&
|
|
44
|
+
this.manager.config.debug &&
|
|
50
45
|
console.info(`[cron][${this.nom}] Planifié pour ${this.nextInvocation.toISOString()} via cron ${next}`);
|
|
51
46
|
|
|
52
47
|
// Date
|
|
53
48
|
} else {
|
|
54
|
-
|
|
55
49
|
this.nextInvocation = next;
|
|
56
|
-
this.manager.config.debug &&
|
|
50
|
+
this.manager.config.debug &&
|
|
57
51
|
console.info(`[cron][${this.nom}] Planifié pour ${this.nextInvocation.toISOString()} via date`);
|
|
58
|
-
|
|
59
52
|
}
|
|
60
53
|
}
|
|
61
54
|
|
|
62
55
|
public scheduleNext() {
|
|
63
|
-
|
|
64
56
|
// Prochaine invocation
|
|
65
|
-
if (this.cron !== undefined)
|
|
66
|
-
|
|
67
|
-
else
|
|
68
|
-
this.nextInvocation = undefined;
|
|
57
|
+
if (this.cron !== undefined) this.nextInvocation = this.cron.next().toDate();
|
|
58
|
+
else this.nextInvocation = undefined;
|
|
69
59
|
}
|
|
70
60
|
|
|
71
61
|
public run(now: boolean = false) {
|
|
72
|
-
|
|
73
62
|
// Update invocation date
|
|
74
|
-
const maintenant = new Date
|
|
75
|
-
const runnable = this.nextInvocation !== undefined && this.nextInvocation.valueOf() <= maintenant.valueOf()
|
|
76
|
-
if (runnable)
|
|
77
|
-
|
|
78
|
-
else if (now === false)
|
|
79
|
-
return;
|
|
63
|
+
const maintenant = new Date();
|
|
64
|
+
const runnable = this.nextInvocation !== undefined && this.nextInvocation.valueOf() <= maintenant.valueOf();
|
|
65
|
+
if (runnable) this.scheduleNext();
|
|
66
|
+
else if (now === false) return;
|
|
80
67
|
|
|
81
68
|
// Execution
|
|
82
69
|
this.runner().then(() => {
|
|
83
70
|
this.manager.config.debug && console.info(`Task runned.`);
|
|
84
|
-
})
|
|
71
|
+
});
|
|
85
72
|
}
|
|
86
|
-
}
|
|
73
|
+
}
|