5htp-core 0.1.2 → 0.2.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.
Files changed (127) hide show
  1. package/changelog.md +5 -0
  2. package/doc/TODO.md +71 -0
  3. package/package.json +5 -4
  4. package/src/client/{App.tsx → app/component.tsx} +15 -8
  5. package/src/client/app/index.ts +128 -0
  6. package/src/client/app/service.ts +34 -0
  7. package/src/client/app.tsconfig.json +0 -4
  8. package/src/client/assets/css/medias.less +14 -0
  9. package/src/client/components/Card/index.tsx +2 -2
  10. package/src/client/components/Dialog/Manager.tsx +39 -12
  11. package/src/client/components/Form/index.tsx +1 -1
  12. package/src/client/components/button.tsx +2 -2
  13. package/src/client/components/containers/Popover/index.tsx +1 -1
  14. package/src/client/components/data/spintext/index.tsx +1 -1
  15. package/src/client/components/dropdown/index.tsx +1 -1
  16. package/src/client/components/index.ts +8 -0
  17. package/src/client/components/input/BaseV2/index.tsx +1 -1
  18. package/src/client/components/input/UploadImage/index.tsx +1 -1
  19. package/src/client/hooks/index.ts +5 -0
  20. package/src/client/hooks/useState/index.tsx +2 -2
  21. package/src/client/hooks.ts +22 -0
  22. package/src/client/index.ts +5 -0
  23. package/src/client/pages/_layout/landing/index.tsx +0 -2
  24. package/src/client/pages/_messages/400.tsx +2 -2
  25. package/src/client/pages/_messages/401.tsx +2 -2
  26. package/src/client/pages/_messages/403.tsx +2 -2
  27. package/src/client/pages/_messages/404.tsx +2 -2
  28. package/src/client/pages/_messages/500.tsx +2 -2
  29. package/src/client/pages/bug.tsx +1 -1
  30. package/src/client/pages/useHeader.tsx +1 -1
  31. package/src/client/{context/captcha.ts → services/captcha/index.ts} +0 -0
  32. package/src/client/services/metrics/index.ts +37 -0
  33. package/src/client/{router → services/router/components}/Link.tsx +1 -1
  34. package/src/client/services/router/components/Page.tsx +59 -0
  35. package/src/client/{router/component.tsx → services/router/components/router.tsx} +43 -74
  36. package/src/client/services/router/index.tsx +448 -0
  37. package/src/client/services/router/request/api.ts +229 -0
  38. package/src/client/{router → services/router}/request/history.ts +0 -0
  39. package/src/client/services/router/request/index.ts +52 -0
  40. package/src/client/services/router/response/index.tsx +107 -0
  41. package/src/client/services/router/response/page.ts +95 -0
  42. package/src/client/{context/socket.ts → services/socket/index.ts} +2 -2
  43. package/src/client/utils/dom.ts +1 -1
  44. package/src/common/app/index.ts +9 -0
  45. package/src/common/data/chaines/index.ts +9 -6
  46. package/src/common/data/input/validate.ts +3 -166
  47. package/src/common/data/objets.ts +25 -0
  48. package/src/common/data/tableaux.ts +8 -0
  49. package/src/common/errors/index.ts +3 -1
  50. package/src/common/router/index.ts +67 -88
  51. package/src/common/router/layouts.ts +50 -0
  52. package/src/common/router/register.ts +62 -0
  53. package/src/common/router/request/api.ts +72 -0
  54. package/src/common/router/request/index.ts +31 -0
  55. package/src/common/router/{response.ts → response/index.ts} +9 -13
  56. package/src/common/router/response/page.ts +40 -56
  57. package/src/common/validation/index.ts +3 -0
  58. package/src/common/validation/schema.ts +184 -0
  59. package/src/common/validation/validator.ts +88 -0
  60. package/src/common/validation/validators.ts +313 -0
  61. package/src/server/app/config.ts +9 -27
  62. package/src/server/app/index.ts +81 -124
  63. package/src/server/app/service.ts +98 -0
  64. package/src/server/app.tsconfig.json +0 -8
  65. package/src/server/error/index.ts +13 -0
  66. package/src/server/index.ts +5 -0
  67. package/src/server/patch.ts +0 -6
  68. package/src/server/{data/Cache.ts → services/cache/index.ts} +79 -47
  69. package/src/server/services/console/bugReporter.ts +26 -16
  70. package/src/server/services/console/index.ts +59 -51
  71. package/src/server/services/cron/index.ts +12 -26
  72. package/src/server/services/database/bucket.ts +40 -0
  73. package/src/server/services/database/connection.ts +206 -75
  74. package/src/server/services/database/datatypes.ts +63 -40
  75. package/src/server/services/database/index.ts +295 -272
  76. package/src/server/services/database/metas.ts +246 -135
  77. package/src/server/services/database/stats.ts +151 -126
  78. package/src/server/services/email/index.ts +28 -52
  79. package/src/server/services/{router/request/services → metrics}/detect.ts +8 -10
  80. package/src/server/services/{router/request/services/tracking.ts → metrics/index.ts} +68 -45
  81. package/src/server/services/{http → router/http}/index.ts +28 -70
  82. package/src/server/services/{http → router/http}/multipart.ts +0 -0
  83. package/src/server/services/{http → router/http}/session.ts.old +0 -0
  84. package/src/server/services/router/index.ts +273 -203
  85. package/src/server/services/router/request/api.ts +73 -0
  86. package/src/server/services/router/request/index.ts +16 -97
  87. package/src/server/services/router/request/service.ts +21 -0
  88. package/src/server/services/router/response/index.ts +125 -64
  89. package/src/server/services/router/response/{filter → mask}/Filter.ts +0 -0
  90. package/src/server/services/router/response/{filter → mask}/index.ts +0 -2
  91. package/src/server/services/router/response/{filter → mask}/selecteurs.ts +0 -0
  92. package/src/server/services/router/response/page/document.tsx +194 -0
  93. package/src/server/services/router/response/page/index.tsx +157 -0
  94. package/src/server/{libs/pages → services/router/response/page}/schemaGenerator.ts +0 -0
  95. package/src/server/services/router/service.ts +48 -0
  96. package/src/server/services/schema/index.ts +47 -0
  97. package/src/server/services/schema/request.ts +55 -0
  98. package/src/server/services/schema/router.ts +33 -0
  99. package/src/server/services/socket/index.ts +38 -43
  100. package/src/server/services/socket/scope.ts +6 -4
  101. package/src/server/services/users/index.ts +203 -0
  102. package/src/server/services/{auth/base.ts → users/old.ts} +28 -112
  103. package/src/server/services/users/router/index.ts +72 -0
  104. package/src/server/services/users/router/request.ts +49 -0
  105. package/src/types/aliases.d.ts +43 -2
  106. package/templates/composant.tsx +1 -1
  107. package/templates/modal.tsx +1 -1
  108. package/templates/page.tsx +1 -1
  109. package/tsconfig.common.json +0 -4
  110. package/src/client/context/api.ts +0 -92
  111. package/src/client/context/index.ts +0 -246
  112. package/src/client/index.tsx +0 -129
  113. package/src/client/router/index.ts +0 -286
  114. package/src/client/router/request/index.ts +0 -106
  115. package/src/client/router/response/index.ts +0 -38
  116. package/src/client/router/route.ts +0 -75
  117. package/src/common/data/input/validators/basic.ts +0 -299
  118. package/src/common/data/input/validators/build.ts +0 -63
  119. package/src/common/router/request.ts +0 -83
  120. package/src/server/data/ApiClient.ts +0 -119
  121. package/src/server/data/input.ts +0 -41
  122. package/src/server/libs/pages/document.static.tsx +0 -41
  123. package/src/server/libs/pages/document.tsx +0 -203
  124. package/src/server/libs/pages/render.tsx +0 -90
  125. package/src/server/routes/auth.ts +0 -151
  126. package/src/server/services/redis/index.ts +0 -71
  127. package/src/server/services/router/request/services/auth.ts +0 -177
@@ -7,7 +7,7 @@ import ws from 'ws';
7
7
  import type { IncomingMessage } from 'http';
8
8
 
9
9
  // Core
10
- import AuthService from '@server/services/router/request/services/auth';
10
+ import type SocketService from '.';
11
11
  import context from '@server/context';
12
12
 
13
13
  /*----------------------------------
@@ -33,7 +33,7 @@ const activityDelay = 10 * 1000; // Clearn broken connections veery 10s
33
33
  /*----------------------------------
34
34
  - SCOPE
35
35
  ----------------------------------*/
36
- export default class SocketScope {
36
+ export default class SocketScope<TUser extends {}> {
37
37
 
38
38
  private connectEvent?: TConnectCallback;
39
39
  private disconnectEvent?: TConnectCallback;
@@ -41,7 +41,9 @@ export default class SocketScope {
41
41
  public users: { [username: string]: WebSocket[] } = {}
42
42
 
43
43
  public constructor(
44
- public path: string
44
+ public path: string,
45
+ private socket: SocketService<TUser>,
46
+ private app = socket.app
45
47
  ) {
46
48
 
47
49
  }
@@ -74,7 +76,7 @@ export default class SocketScope {
74
76
  context.run({ channelType: 'socket', channelId: this.path }, async () => {
75
77
 
76
78
  // Auth
77
- const username = await AuthService.decode(req);
79
+ const username = await this.socket.config.users.decode(req);
78
80
  if (!username) {
79
81
  console.log(`Rejecting connection on ${this.path} for client ${socket.ip} (${socket.id})}: Not authenticated`);
80
82
  socket.close(4004, "auth");
@@ -0,0 +1,203 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import jwt from 'jsonwebtoken';
7
+ import type express from 'express';
8
+ import type http from 'http';
9
+
10
+ // Core
11
+ import Application from '@server/app';
12
+ import Service from '@server/app/service';
13
+ import {
14
+ default as Router, Request as ServerRequest,
15
+ } from '@server/services/router';
16
+ import { InputError, AuthRequired, Forbidden } from '@common/errors';
17
+
18
+ /*----------------------------------
19
+ - TYPES
20
+ ----------------------------------*/
21
+
22
+ export type TUserRole = typeof UserRoles[number]
23
+
24
+ export type THttpRequest = express.Request | http.IncomingMessage;
25
+
26
+ /*----------------------------------
27
+ - CONFIG
28
+ ----------------------------------*/
29
+
30
+ const LogPrefix = '[auth]'
31
+
32
+ export const UserRoles = ['USER', 'ADMIN', 'TEST', 'DEV'] as const
33
+
34
+ /*----------------------------------
35
+ - SERVICE CONVIG
36
+ ----------------------------------*/
37
+
38
+ export type TConfig = {
39
+ debug: boolean,
40
+ logoutUrl: string,
41
+ jwt: {
42
+ // 2048 bits
43
+ key: string,
44
+ expiration: string,
45
+ },
46
+ google?: {
47
+ web: {
48
+ clientId: string,
49
+ secret: string,
50
+ },
51
+ android: {
52
+ clientId: string
53
+ }
54
+ }
55
+ }
56
+
57
+ export type THooks = {
58
+
59
+ }
60
+
61
+ /*----------------------------------
62
+ - SERVICE
63
+ ----------------------------------*/
64
+ export default abstract class UsersManagementService<
65
+ TUser extends {},
66
+ TApplication extends Application,
67
+ TJwtSession extends {} = {},
68
+ TRequest extends ServerRequest<Router> = ServerRequest<Router>,
69
+ > extends Service<TConfig, THooks, TApplication> {
70
+
71
+ public async register() {
72
+
73
+ }
74
+
75
+ public async start() {
76
+
77
+ }
78
+
79
+ public abstract login( ...args: any[] ): Promise<{ user: TUser, token: string }>;
80
+ public abstract decodeSession( jwt: TJwtSession, req: THttpRequest ): Promise<TUser>;
81
+
82
+ protected abstract displayName(user: TUser): string;
83
+ protected abstract displaySessionName(session: TJwtSession): string;
84
+
85
+ public async decode( req: THttpRequest, withData: true ): Promise<TUser | null>;
86
+ public async decode( req: THttpRequest, withData?: false ): Promise<TJwtSession | null>;
87
+ public async decode( req: THttpRequest, withData: boolean = false ): Promise<TJwtSession | TUser | null> {
88
+
89
+ this.config.debug && console.log(LogPrefix, 'Decode:', { cookie: req.cookies['authorization'] });
90
+
91
+ let token: string | undefined;
92
+ if (('cookies' in req) && typeof req.cookies['authorization'] === 'string')
93
+ token = req.cookies['authorization'];
94
+ // Desktop app webview do not support cookie config, so wwe retrieve it from headers
95
+ else if (typeof req.headers['authorization'] === 'string')
96
+ token = req.headers['authorization'];
97
+
98
+ if (token === undefined)
99
+ return this.unauthorized(req);
100
+
101
+ let session: TJwtSession;
102
+ try {
103
+ session = jwt.verify(token, this.config.jwt.key, {
104
+ maxAge: this.config.jwt.expiration
105
+ });
106
+ } catch (error) {
107
+ console.warn(LogPrefix, "Failed to decode jwt token:", token);
108
+ return this.unauthorized(req);
109
+ }
110
+
111
+ // Return email only
112
+ const sessionName = this.displaySessionName(session);
113
+ if (!withData) {
114
+ this.config.debug && console.log(LogPrefix, `Auth user ${sessionName} successfull. Return email only`);
115
+ return session;
116
+ }
117
+
118
+ // Deserialize full user data
119
+ this.config.debug && console.log(LogPrefix, `Deserialize user ${sessionName}`);
120
+ const user = await this.decodeSession(session, req);
121
+ this.config.debug && console.log(LogPrefix, `Deserialized user ${sessionName}:`, user);
122
+
123
+ return user;
124
+ }
125
+
126
+ public unauthorized( req: THttpRequest ) {
127
+
128
+ if ('res' in req) {
129
+ // If use auth failed, we remove the jwt token so we avoid to trigger the same auth error in the next request
130
+ console.warn(LogPrefix, "Auth failed: remove authorization cookie");
131
+ req.res?.clearCookie('authorization');
132
+ }
133
+
134
+ return null;
135
+ }
136
+
137
+ protected createSession( session: TJwtSession, request: TRequest ): string {
138
+
139
+ this.config.debug && console.info(LogPrefix, `Creating new session:`, session);
140
+
141
+ const token = jwt.sign(session, this.config.jwt.key);
142
+
143
+ this.config.debug && console.info(LogPrefix, `Generated JWT token for session:` + token);
144
+
145
+ request.res.cookie('authorization', token);
146
+
147
+ return token;
148
+ }
149
+
150
+ public logout( request: TRequest ) {
151
+
152
+ const user = request.user;
153
+ if (!user) return;
154
+
155
+ this.config.debug && console.info(LogPrefix, `Logout ${this.displayName(user)}`);
156
+ request.res.clearCookie('authorization');
157
+ }
158
+
159
+ public check( request: TRequest, role: TUserRole, motivation?: string): TUser;
160
+ public check( request: TRequest, role: false, motivation?: string): null;
161
+ public check( request: TRequest, role: TUserRole | boolean = 'USER', motivation?: string): TUser | null {
162
+
163
+ const user = request.user;
164
+
165
+ this.config.debug && console.warn(LogPrefix, `Check auth, role = ${role}. Current user =`, user);
166
+
167
+ if (user === undefined) {
168
+
169
+ throw new Error(`request.user has not been decoded.`);
170
+
171
+ // Shortcut: { auth: true } <=> { auth: 'USER' }
172
+ } else if (role === true) {
173
+
174
+ role = 'USER';
175
+
176
+ // No auth needed
177
+ } else if (role === false) {
178
+
179
+ return user;
180
+
181
+ // Not connected
182
+ } else if (user === null) {
183
+
184
+ this.config.debug && console.warn(LogPrefix, "Refusé pour anonyme (" + request.ip + ")");
185
+ throw new AuthRequired(motivation);
186
+
187
+ // Insufficient permissions
188
+ } else if (!user.roles.includes(role)) {
189
+
190
+ console.warn(LogPrefix, "Refusé: " + role + " pour " + this.displayName(user) + " (" + (user.roles ? user.roles.join(', ') : 'role inconnu') + ")");
191
+
192
+ throw new Forbidden("You do not have sufficient permissions to access this resource.");
193
+
194
+ } else {
195
+
196
+ console.warn(LogPrefix, "Autorisé " + role + " pour " + this.displayName(user) + " (" + user.roles.join(', ') + ")");
197
+
198
+ }
199
+
200
+ return user;
201
+ }
202
+
203
+ }
@@ -1,28 +1,8 @@
1
- /*----------------------------------
2
- - DEPENDANCES
3
- ----------------------------------*/
4
1
 
5
- // Npm
6
2
  import md5 from 'md5';
7
3
  import { OAuth2Client, LoginTicket } from 'google-auth-library';
8
4
 
9
- // Core libs
10
- import { Forbidden } from '@common/errors';
11
5
 
12
- // App Libs
13
- import { IP } from '@server/models';
14
- import app, { $ } from '@server/app';
15
-
16
- // Serbices
17
- import '@server/services/database';
18
-
19
- /*----------------------------------
20
- - TYPES
21
- ----------------------------------*/
22
-
23
- import type ServerRequest from '@server/services/router/request';
24
-
25
- export type TUserRole = typeof UserRoles[number]
26
6
 
27
7
  type AuthResponse = {
28
8
  token: string,
@@ -30,90 +10,26 @@ type AuthResponse = {
30
10
  user: User
31
11
  }
32
12
 
33
- /*----------------------------------
34
- - CONFIG
35
- ----------------------------------*/
36
-
37
- const config = app.config.auth;
38
-
39
- const LogPrefix = '[auth]'
40
-
41
- export const UserRoles = ['USER', 'ADMIN', 'TEST', 'DEV'] as const
42
-
43
- /*----------------------------------
44
- - SERVICE CONVIG
45
- ----------------------------------*/
46
-
47
- export type AuthConfig = {
48
- debug: boolean,
49
- logoutUrl: string,
50
- jwt: {
51
- // 2048 bits
52
- key: string,
53
- expiration: string,
54
- },
55
- google?: {
56
- web: {
57
- clientId: string,
58
- secret: string,
59
- },
60
- android: {
61
- clientId: string
62
- }
63
- }
64
- }
65
-
66
- declare global {
67
- namespace Core {
68
-
69
- interface Services {
70
- auth: UserAuthBase
71
- }
72
-
73
- namespace Config {
74
- interface Services {
75
- auth: AuthConfig
76
- }
77
- }
78
- }
79
- }
13
+ export default class {
80
14
 
81
- /*----------------------------------
82
- - SERVICE
83
- ----------------------------------*/
84
- export default abstract class UserAuthBase {
85
15
 
86
- public abstract getData( where: string ): Promise<User> ;
87
- public abstract SsrMask: string;
16
+ public async start() {
88
17
 
89
- public abstract beforeSignup(user: User): Promise< void >;
90
- public abstract afterSignup(user: User): Promise<{ redirect: string }>;
91
-
92
- private googleClient = app.config.auth.google
93
- ? new OAuth2Client(
94
- app.config.auth.google.web.clientId, // Google Client ID
95
- app.config.auth.google.web.secret, // Private key
96
- "https://" + app.env.domain + "/auth/google/response" // Redirect url
97
- )
98
- : undefined;
18
+ // Google auth client
19
+ if (this.config.google) {
99
20
 
100
- public async load() {
21
+ const httpConfig = this.app.http.publicUrl;
101
22
 
23
+ this.googleClient = new OAuth2Client(
24
+ this.config.google.web.clientId, // Google Client ID
25
+ this.config.google.web.secret, // Private key
26
+ httpConfig + "/auth/google/response" // Redirect url
27
+ );
28
+ }
102
29
  }
103
30
 
104
- public async FromEmail(
105
- email: string,
106
- request: ServerRequest,
107
- userInfo: Partial<User> = {}
108
- ) {
109
-
110
- const { token, user } = await this.Auth(email, request, false, userInfo);
111
-
112
- return await request.response.json(
113
- { token, user },
114
- `token user( ` + this.SsrMask + ` )`
115
- )
116
- }
31
+
32
+ private googleClient: OAuth2Client | undefined;
117
33
 
118
34
  public async FromGoogle(request: ServerRequest): Promise<string> {
119
35
 
@@ -145,7 +61,8 @@ export default abstract class UserAuthBase {
145
61
  request: ServerRequest,
146
62
  ): Promise<AuthResponse> {
147
63
 
148
- if (!this.googleClient)
64
+ const googleConfig = this.config.google;
65
+ if (!this.googleClient || !googleConfig)
149
66
  throw new Forbidden(`Authentication method disabled.`);
150
67
 
151
68
  if (codeOrToken === undefined)
@@ -156,15 +73,15 @@ export default abstract class UserAuthBase {
156
73
  return this.GoogleResponse('token', r.tokens.id_token, request);
157
74
  }
158
75
 
159
- config.debug && console.log(LogPrefix, "Auth via google", app.config.auth.google);
76
+ this.config.debug && console.log(LogPrefix, "Auth via google", googleConfig);
160
77
 
161
78
  let ticket: LoginTicket;
162
79
  try {
163
80
  ticket = await this.googleClient.verifyIdToken({
164
81
  idToken: codeOrToken,
165
82
  audience: [
166
- app.config.auth.google.web.clientId,
167
- app.config.auth.google.android.clientId,
83
+ googleConfig.web.clientId,
84
+ googleConfig.android.clientId,
168
85
  ]
169
86
  });
170
87
  } catch (error) {
@@ -198,7 +115,7 @@ export default abstract class UserAuthBase {
198
115
  userInfo: Partial<User> = {}
199
116
  ): Promise<AuthResponse> {
200
117
 
201
- let user = await this.getData('email = ' + $.sql.esc(email));
118
+ let user = await this.getData('email = ' + this.sql.esc(email));
202
119
  let ip: IP;
203
120
  let redirect: string;
204
121
  if (!user) { // Signup
@@ -225,7 +142,7 @@ export default abstract class UserAuthBase {
225
142
 
226
143
  }
227
144
 
228
- /*await $.sql`
145
+ /*await this.sql`
229
146
  INSERT INTO UserLogin SET
230
147
  user = ${user.email},
231
148
  date = NOW(),
@@ -244,7 +161,7 @@ export default abstract class UserAuthBase {
244
161
  let username = email.split('@')[0];
245
162
 
246
163
  // Prefix username if alreasy existing
247
- const duplicates = await $.sql`
164
+ const duplicates = await this.sql`
248
165
  FROM User
249
166
  WHERE name REGEXP CONCAT('^', ${username}, '[0-9]*$');
250
167
  `.count();
@@ -268,12 +185,12 @@ export default abstract class UserAuthBase {
268
185
  // Referrer
269
186
  if (user.referrer !== undefined) {
270
187
 
271
- const refExists = await $.sql`FROM User WHERE name = ${user.referrer}`.exists();
188
+ const refExists = await this.sql`FROM User WHERE name = ${user.referrer}`.exists();
272
189
  if (!refExists)
273
190
  user.referrer = undefined;
274
191
  else {
275
192
 
276
- await $.sql.upsert('UserStats', {
193
+ await this.sql.upsert('UserStats', {
277
194
  user: user.referrer,
278
195
  date: new Date,
279
196
  refSignups: 1
@@ -284,8 +201,8 @@ export default abstract class UserAuthBase {
284
201
  }
285
202
 
286
203
  // Create user
287
- await $.sql.insert('User', user);
288
- await $.sql.update('logs.IP', { user_name: username }, { address: request.ip });
204
+ await this.sql.insert('User', user);
205
+ await this.sql.update('logs.IP', { user_name: username }, { address: request.ip });
289
206
 
290
207
  // Hook
291
208
  let redirect: string = '/';
@@ -296,7 +213,7 @@ export default abstract class UserAuthBase {
296
213
  // remove user.emailHash
297
214
 
298
215
  // Notif email
299
- await $.email.send({
216
+ await this.email.send({
300
217
  to: app.identity.author.email,
301
218
  subject: app.identity.name + ": New User",
302
219
  html: JSON.stringify(user)
@@ -335,7 +252,7 @@ export default abstract class UserAuthBase {
335
252
  return;
336
253
 
337
254
  // Check if user exists
338
- const referrerExists = await $.sql`FROM User WHERE name = ${referrer}`.count();
255
+ const referrerExists = await this.sql`FROM User WHERE name = ${referrer}`.count();
339
256
  if (referrerExists === 0)
340
257
  return;
341
258
 
@@ -347,7 +264,7 @@ export default abstract class UserAuthBase {
347
264
  response.cookie('r', referrer);
348
265
 
349
266
  // Count the clic
350
- await $.sql.upsert('UserStats', {
267
+ await this.sql.upsert('UserStats', {
351
268
  user: referrer,
352
269
  date: new Date,
353
270
  refClics: 1
@@ -357,5 +274,4 @@ export default abstract class UserAuthBase {
357
274
  }
358
275
 
359
276
  }
360
-
361
277
  }
@@ -0,0 +1,72 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+
7
+ // Core
8
+ import type Application from '@server/app';
9
+
10
+ import {
11
+ default as Router, Request as ServerRequest, TRoute,
12
+ RouterService
13
+ } from '@server/services/router';
14
+
15
+ // Specific
16
+ import type { default as UsersService, TUserRole } from '..';
17
+ import UsersRequestService from './request';
18
+
19
+ /*----------------------------------
20
+ - TYPES
21
+ ----------------------------------*/
22
+
23
+
24
+ /*----------------------------------
25
+ - CONFIG
26
+ ----------------------------------*/
27
+
28
+ const LogPrefix = '[router][auth]';
29
+
30
+ /*----------------------------------
31
+ - SERVICE
32
+ ----------------------------------*/
33
+ export default class AuthenticationRouterService<
34
+ TUser extends {} = {},
35
+ TRequest extends ServerRequest<Router> = ServerRequest<Router>,
36
+ > extends RouterService {
37
+
38
+ public constructor(
39
+ public users: UsersService<TUser, Application>,
40
+ public config = users.config
41
+ ) {
42
+
43
+ super();
44
+
45
+ }
46
+
47
+ public async register() {
48
+
49
+ // Decode current user
50
+ this.router.on('request', async (request: TRequest) => {
51
+
52
+ // TODO: Typings. (context.user ?)
53
+ const decoded = await this.users.decode( request.req, true);
54
+
55
+ console.log("DECODED", decoded);
56
+
57
+ request.user = decoded || null;
58
+ })
59
+
60
+ // Check route permissions
61
+ this.router.on('resolved', async (route: TRoute, request: TRequest) => {
62
+
63
+ if (route.options.auth !== undefined)
64
+ // TODO: How to pas the router type to router config ? Circular rfeerence ?
65
+ this.users.check(request, route.options.auth);
66
+ })
67
+ }
68
+
69
+ public requestService( request: TRequest ): UsersRequestService<TUser> {
70
+ return new UsersRequestService( request, this );
71
+ }
72
+ }
@@ -0,0 +1,49 @@
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
4
+
5
+ // Npm
6
+ import jwt from 'jsonwebtoken';
7
+
8
+ // Core
9
+ import type { default as Router, Request as ServerRequest } from '@server/services/router';
10
+ import RequestService from '@server/services/router/request/service';
11
+ import { InputError, AuthRequired, Forbidden } from '@common/errors';
12
+
13
+ // Specific
14
+ import type AuthenticationRouterService from '.';
15
+ import type { default as UsersManagementService, TUserRole } from '..';
16
+
17
+ /*----------------------------------
18
+ - TYPES
19
+ ----------------------------------*/
20
+
21
+ /*----------------------------------
22
+ - MODULE
23
+ ----------------------------------*/
24
+ export default class UsersRequestService<
25
+ TUser extends {}
26
+ > extends RequestService {
27
+
28
+ public constructor(
29
+ request: ServerRequest<Router>,
30
+ public auth: AuthenticationRouterService,
31
+ public users = auth.users,
32
+ ) {
33
+ super(request);
34
+ }
35
+
36
+ public login( email: string ) {
37
+ return this.users.login( this.request, email );
38
+ }
39
+
40
+ public logout() {
41
+ return this.users.logout( this.request );
42
+ }
43
+
44
+ public check( role: TUserRole, motivation?: string): TUser;
45
+ public check( role: false, motivation?: string): null;
46
+ public check( role: TUserRole | boolean = 'USER', motivation?: string): TUser | null {
47
+ return this.users.check( this.request, role, motivation );
48
+ }
49
+ }
@@ -1,13 +1,54 @@
1
+ declare module "@/client/pages/\*\*/_layout/index.tsx" {
2
+ const Layout: import("../common/router/layouts").ImportedLayouts;
3
+ export = LayoutsList
4
+ }
5
+
1
6
  declare module "@/client/pages/\*.tsx" {
2
- const value: import("../client/router").TRoutesLoaders;
7
+ const value: import("../client/services/router").TRoutesLoaders;
3
8
  export = value;
4
9
  }
10
+
5
11
  declare module "@client/pages/\*.tsx" {
6
- const value: import("../client/router").TRoutesLoaders;
12
+ const value: import("../client/services/router").TRoutesLoaders;
7
13
  export = value;
8
14
  }
9
15
 
10
16
  declare module "@/server/services/auth" {
11
17
  const UserAuthService: import("../server/services/auth/base").default;
12
18
  export = UserAuthService;
19
+ }
20
+
21
+ declare module "@/server" {
22
+ const ServerApplicationClass: import("../server/app").default;
23
+ export = InstanceType<ServerApplicationClass>;
24
+ }
25
+
26
+ declare module "@/client" {
27
+ const ClientApplicationClass: import("../client/app").default;
28
+ export = InstanceType<ClientApplicationClass>;
29
+ }
30
+
31
+ declare module "@/client/context" {
32
+
33
+ const Test: true;
34
+
35
+ const ClientRouter: import('../client/services/router').default;
36
+ const ServerRouter: import('../server/services/router').default;
37
+
38
+ const TServerRouterRequestContext: import('../server/services/router/response').TRouterContext;
39
+ const TClientRouterRequestContext: import('../client/services/router/response').TRouterContext;
40
+
41
+ export const ClientContext = (
42
+ // TO Fix: TClientRouterRequestContext is unable to get the right type of CrossPathClient["router"]
43
+ // (it gets ClientApplication instead of CrossPathClient)
44
+ TClientRouterRequestContext<ClientRouter, ClientRouter["app"]>
45
+ |
46
+ TServerRouterRequestContext<ServerRouter>
47
+ )
48
+
49
+ export const ReactClientContext: preact.Context<ClientContext>;
50
+
51
+ const useContext: () => ClientContext;
52
+
53
+ export = useContext;
13
54
  }
@@ -8,7 +8,7 @@
8
8
  import React from 'react';
9
9
 
10
10
  // Core libs
11
- import useContext from '@client/context';
11
+ import useContext from '@/client/context';
12
12
 
13
13
  // Core components
14
14
  import Button from '@client/components/button';
@@ -8,7 +8,7 @@
8
8
  import React from 'react';
9
9
 
10
10
  // Cre libs
11
- import useContext from '@client/context';
11
+ import useContext from '@/client/context';
12
12
 
13
13
  // Core components
14
14
  import Card, { Props as CardProps } from '@client/components/Dialog/card';
@@ -9,7 +9,7 @@ import React from 'react';
9
9
 
10
10
  // Core
11
11
  import route from '@router';
12
- import { useState } from '@client/context';
12
+ import { useState } from '@/client/context';
13
13
 
14
14
  // Core components
15
15
  import Button from '@client/components/button';