prostgles-server 4.2.140 → 4.2.142

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 (40) hide show
  1. package/dist/Auth/AuthHandler.d.ts +12 -11
  2. package/dist/Auth/AuthHandler.d.ts.map +1 -1
  3. package/dist/Auth/AuthHandler.js +30 -40
  4. package/dist/Auth/AuthHandler.js.map +1 -1
  5. package/dist/Auth/AuthTypes.d.ts +7 -18
  6. package/dist/Auth/AuthTypes.d.ts.map +1 -1
  7. package/dist/Auth/authInit.d.ts +1 -1
  8. package/dist/Auth/authInit.d.ts.map +1 -1
  9. package/dist/Auth/authInit.js +9 -5
  10. package/dist/Auth/authInit.js.map +1 -1
  11. package/dist/Auth/authInitRoutes.d.ts +3 -0
  12. package/dist/Auth/authInitRoutes.d.ts.map +1 -0
  13. package/dist/Auth/authInitRoutes.js +153 -0
  14. package/dist/Auth/authInitRoutes.js.map +1 -0
  15. package/dist/Auth/setAuthProviders.d.ts +6 -0
  16. package/dist/Auth/setAuthProviders.d.ts.map +1 -0
  17. package/dist/Auth/setAuthProviders.js +90 -0
  18. package/dist/Auth/setAuthProviders.js.map +1 -0
  19. package/dist/Auth/setAuthSignup.d.ts +3 -2
  20. package/dist/Auth/setAuthSignup.d.ts.map +1 -1
  21. package/dist/Auth/setAuthSignup.js +15 -12
  22. package/dist/Auth/setAuthSignup.js.map +1 -1
  23. package/dist/Auth/setupAuthRoutes.d.ts +3 -0
  24. package/dist/Auth/setupAuthRoutes.d.ts.map +1 -0
  25. package/dist/Auth/setupAuthRoutes.js +154 -0
  26. package/dist/Auth/setupAuthRoutes.js.map +1 -0
  27. package/lib/Auth/AuthHandler.ts +31 -47
  28. package/lib/Auth/AuthTypes.ts +8 -22
  29. package/lib/Auth/{setAuthSignup.ts → setAuthProviders.ts} +10 -7
  30. package/lib/Auth/setupAuthRoutes.ts +169 -0
  31. package/package.json +1 -1
  32. package/tests/client/hooks.spec.ts +8 -3
  33. package/tests/client/index.ts +2 -0
  34. package/tests/client/package-lock.json +4 -4
  35. package/tests/client/package.json +1 -1
  36. package/tests/clientOnlyQueries.spec.ts +8 -0
  37. package/tests/server/index.ts +9 -1
  38. package/tests/server/package-lock.json +8 -7
  39. package/tests/server/publishTypeCheck.ts +2 -1
  40. package/lib/Auth/authInit.ts +0 -166
@@ -1,16 +1,18 @@
1
1
  import { Auth } from './AuthTypes';
2
- import passport from "passport";
2
+ /** For some reason normal import is undefined */
3
+ const passport = require("passport") as typeof import("passport");
3
4
  import { Strategy as GoogleStrategy } from "passport-google-oauth20";
4
5
  import { Strategy as GitHubStrategy } from "passport-github2";
5
6
  import { Strategy as MicrosoftStrategy } from "passport-microsoft";
6
7
  import { Strategy as FacebookStrategy } from "passport-facebook";
7
8
  import { AuthSocketSchema, getKeys, isDefined, isEmpty } from "prostgles-types";
9
+ import { AUTH_ROUTES_AND_PARAMS, AuthHandler } from "./AuthHandler";
8
10
 
9
- export const setAuthSignup = ({ registrations, app }: Required<Auth>["expressConfig"]) => {
11
+ export function setAuthProviders (this: AuthHandler, { registrations, app }: Required<Auth>["expressConfig"]) {
10
12
  if(!registrations) return;
11
13
  const { email, onRegister, websiteUrl, ...providers } = registrations;
12
14
  if(email){
13
- app.post("/signup", async (req, res) => {
15
+ app.post(AUTH_ROUTES_AND_PARAMS.emailSignup, async (req, res) => {
14
16
  const { username, password } = req.body;
15
17
  if(typeof username !== "string" || typeof password !== "string"){
16
18
  res.status(400).json({ msg: "Invalid username or password" });
@@ -53,7 +55,7 @@ export const setAuthSignup = ({ registrations, app }: Required<Auth>["expressCon
53
55
  providerName,
54
56
  }) => {
55
57
 
56
- const callbackPath = `/auth/${providerName}/callback`;
58
+ const callbackPath = `${AUTH_ROUTES_AND_PARAMS.loginWithProvider}/${providerName}/callback`;
57
59
  passport.use(
58
60
  new (strategy as typeof GoogleStrategy)(
59
61
  {
@@ -68,7 +70,7 @@ export const setAuthSignup = ({ registrations, app }: Required<Auth>["expressCon
68
70
  )
69
71
  );
70
72
 
71
- app.get(`/auth/${providerName}`,
73
+ app.get(`${AUTH_ROUTES_AND_PARAMS.loginWithProvider}/${providerName}`,
72
74
  passport.authenticate(providerName, authOpts ?? {})
73
75
  );
74
76
 
@@ -82,7 +84,8 @@ export const setAuthSignup = ({ registrations, app }: Required<Auth>["expressCon
82
84
  });
83
85
  }
84
86
 
85
- export const getProviders = (registrations: Required<Auth>["expressConfig"]["registrations"]): AuthSocketSchema["providers"] | undefined => {
87
+ export function getProviders(this: AuthHandler): AuthSocketSchema["providers"] | undefined {
88
+ const { registrations } = this.opts?.expressConfig ?? {}
86
89
  if(!registrations) return undefined;
87
90
  const {
88
91
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -95,7 +98,7 @@ export const getProviders = (registrations: Required<Auth>["expressConfig"]["reg
95
98
  getKeys(providers).forEach(providerName => {
96
99
  if(providers[providerName]?.clientID){
97
100
  result[providerName] = {
98
- url: `/auth/${providerName}`,
101
+ url: `${AUTH_ROUTES_AND_PARAMS.loginWithProvider}/${providerName}`,
99
102
  }
100
103
  }
101
104
  });
@@ -0,0 +1,169 @@
1
+ import { DBOFullyTyped } from "../DBSchemaBuilder";
2
+ import { AUTH_ROUTES_AND_PARAMS, AuthHandler, getLoginClientInfo, HTTPCODES } from "./AuthHandler";
3
+ import { AuthClientRequest, ExpressReq, ExpressRes } from "./AuthTypes";
4
+ import { setAuthProviders } from "./setAuthProviders";
5
+
6
+ export async function setupAuthRoutes(this: AuthHandler) {
7
+ if (!this.opts) return;
8
+
9
+ const { login, getUser, expressConfig } = this.opts;
10
+
11
+ if (!login) {
12
+ throw "Invalid auth: Provide { sidKeyName: string } ";
13
+ }
14
+
15
+ if ((AUTH_ROUTES_AND_PARAMS.sidKeyName as any) === "sid") {
16
+ throw "sidKeyName cannot be 'sid' due to collision with socket.io";
17
+ }
18
+
19
+ if (!getUser) throw "getUser missing from auth config";
20
+
21
+ if (!expressConfig) {
22
+ return
23
+ }
24
+ const { app, publicRoutes = [], onGetRequestOK, magicLinks, use } = expressConfig;
25
+ if (publicRoutes.find(r => typeof r !== "string" || !r)) {
26
+ throw "Invalid or empty string provided within publicRoutes "
27
+ }
28
+
29
+ setAuthProviders.bind(this)(expressConfig);
30
+
31
+ if(use){
32
+ app.use((req, res, next) => {
33
+ use({
34
+ req,
35
+ res,
36
+ next,
37
+ getUser: () => this.getUser({ httpReq: req }) as any,
38
+ dbo: this.dbo as DBOFullyTyped,
39
+ db: this.db,
40
+ })
41
+ })
42
+ }
43
+
44
+ if (magicLinks) {
45
+ const { check } = magicLinks;
46
+ if (!check) {
47
+ throw "Check must be defined for magicLinks";
48
+ }
49
+
50
+ app.get(AUTH_ROUTES_AND_PARAMS.magicLinksExpressRoute, async (req: ExpressReq, res: ExpressRes) => {
51
+ const { id } = req.params ?? {};
52
+
53
+ if (typeof id !== "string" || !id) {
54
+ res.status(HTTPCODES.BAD_REQUEST).json({ msg: "Invalid magic-link id. Expecting a string" });
55
+ } else {
56
+ try {
57
+ const session = await this.throttledFunc(async () => {
58
+ return check(id, this.dbo as any, this.db, getLoginClientInfo({ httpReq: req }));
59
+ });
60
+ if (!session) {
61
+ res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Invalid magic-link" });
62
+ } else {
63
+ this.setCookieAndGoToReturnURLIFSet(session, { req, res });
64
+ }
65
+
66
+ } catch (e) {
67
+ res.status(HTTPCODES.AUTH_ERROR).json({ msg: e });
68
+ }
69
+ }
70
+ });
71
+ }
72
+
73
+ app.post(AUTH_ROUTES_AND_PARAMS.login, async (req: ExpressReq, res: ExpressRes) => {
74
+ try {
75
+ const start = Date.now();
76
+ const { sid, expires } = await this.loginThrottled(req.body || {}, getLoginClientInfo({ httpReq: req })) || {};
77
+ await this.prostgles.opts.onLog?.({
78
+ type: "auth",
79
+ command: "login",
80
+ duration: Date.now() - start,
81
+ sid,
82
+ socketId: undefined,
83
+ })
84
+ if (sid) {
85
+
86
+ this.setCookieAndGoToReturnURLIFSet({ sid, expires }, { req, res });
87
+
88
+ } else {
89
+ throw ("Internal error: no user or session")
90
+ }
91
+ } catch (err) {
92
+ console.log(err)
93
+ res.status(HTTPCODES.AUTH_ERROR).json({ err });
94
+ }
95
+
96
+ });
97
+
98
+ if (AUTH_ROUTES_AND_PARAMS.logoutGetPath && this.opts.logout) {
99
+ app.get(AUTH_ROUTES_AND_PARAMS.logoutGetPath, async (req: ExpressReq, res: ExpressRes) => {
100
+ const sid = this.validateSid(req?.cookies?.[AUTH_ROUTES_AND_PARAMS.sidKeyName]);
101
+ if (sid) {
102
+ try {
103
+ await this.throttledFunc(() => {
104
+ return this.opts!.logout!(req?.cookies?.[AUTH_ROUTES_AND_PARAMS.sidKeyName], this.dbo as any, this.db);
105
+ })
106
+ } catch (err) {
107
+ console.error(err);
108
+ }
109
+ }
110
+ res.redirect("/")
111
+ });
112
+ }
113
+
114
+ if (Array.isArray(publicRoutes)) {
115
+
116
+ /* Redirect if not logged in and requesting non public content */
117
+ app.get(AUTH_ROUTES_AND_PARAMS.catchAll, async (req: ExpressReq, res: ExpressRes, next) => {
118
+
119
+ const clientReq: AuthClientRequest = { httpReq: req };
120
+ const getUser = this.getUser;
121
+ if(this.prostgles.restApi){
122
+ if(Object.values(this.prostgles.restApi.routes).some(restRoute => this.matchesRoute(restRoute.split("/:")[0], req.path))){
123
+ next();
124
+ return;
125
+ }
126
+ }
127
+ try {
128
+ const returnURL = this.getReturnUrl(req);
129
+
130
+ if(this.matchesRoute(AUTH_ROUTES_AND_PARAMS.loginWithProvider, req.path)){
131
+ next();
132
+ return;
133
+ }
134
+ /**
135
+ * Requesting a User route
136
+ */
137
+ if (this.isUserRoute(req.path)) {
138
+
139
+ /* Check auth. Redirect to login if unauthorized */
140
+ const u = await getUser(clientReq);
141
+ if (!u) {
142
+ res.redirect(`${AUTH_ROUTES_AND_PARAMS.login}?returnURL=${encodeURIComponent(req.originalUrl)}`);
143
+ return;
144
+ }
145
+
146
+ /* If authorized and going to returnUrl then redirect. Otherwise serve file */
147
+ } else if (returnURL && (await getUser(clientReq))) {
148
+
149
+ res.redirect(returnURL);
150
+ return;
151
+
152
+ /** If Logged in and requesting login then redirect to main page */
153
+ } else if (this.matchesRoute(AUTH_ROUTES_AND_PARAMS.login, req.path) && (await getUser(clientReq))) {
154
+
155
+ res.redirect("/");
156
+ return;
157
+ }
158
+
159
+ onGetRequestOK?.(req, res, { getUser: () => getUser(clientReq), dbo: this.dbo as DBOFullyTyped, db: this.db })
160
+
161
+ } catch (error) {
162
+ console.error(error);
163
+ const errorMessage = typeof error === "string" ? error : error instanceof Error ? error.message : "";
164
+ res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Something went wrong when processing your request" + (errorMessage? (": " + errorMessage) : "") });
165
+ }
166
+
167
+ });
168
+ }
169
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "4.2.140",
3
+ "version": "4.2.142",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -147,10 +147,15 @@ export const clientHooks = async (db: DBHandlerClient, getSocketOptions: (watchS
147
147
  expectedRerenders: 3
148
148
  });
149
149
  assert.equal(results.length, 3);
150
- assert.deepStrictEqual(results.slice(0, 2), [
151
- { data: undefined, isLoading: true, error: undefined },
150
+ assert.deepStrictEqual(
151
+ results[0],
152
+ { data: undefined, isLoading: true, error: undefined }
153
+ );
154
+ /** This fails from time to time */
155
+ assert.deepStrictEqual(
156
+ results[1],
152
157
  { data: [], error: undefined, isLoading: false },
153
- ]);
158
+ );
154
159
  const lastData = results.at(-1)?.data;
155
160
  assert.equal(lastData.length, 1);
156
161
  const lastDataItem = lastData[0];
@@ -106,10 +106,12 @@ try {
106
106
  onReady: async (db, methods, tableSchema, auth, isReconnect) => {
107
107
  log(`TEST_NAME: ${TEST_NAME} Started`)
108
108
  try {
109
+ //@ts-ignore
109
110
  if(typeof window !== "undefined"){
110
111
  const onLog = (...args: any[]) => {
111
112
  socket.emit("log", args.map(v => typeof v === "object"? JSON.stringify(v) : v).join(" "));
112
113
  }
114
+ //@ts-ignore
113
115
  window.onerror = function myErrorHandler(errorMsg, url, lineNumber) {
114
116
  console.error("Error occured: " + errorMsg);
115
117
  stopTest({ err: errorMsg });
@@ -10,7 +10,7 @@
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "@types/node": "^20.9.2",
13
- "prostgles-client": "^4.0.146",
13
+ "prostgles-client": "^4.0.147",
14
14
  "prostgles-types": "^4.0.51",
15
15
  "socket.io-client": "^4.7.5"
16
16
  },
@@ -3006,9 +3006,9 @@
3006
3006
  }
3007
3007
  },
3008
3008
  "node_modules/prostgles-client": {
3009
- "version": "4.0.146",
3010
- "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.146.tgz",
3011
- "integrity": "sha512-Xpy+mhnIERPly8GXNMvrkcJzDXbqlNMDhW+f+K2PqTceyQPxRVZGeFckWuguHXIy8NYB6qPPXa+nhQaHnag6Hw==",
3009
+ "version": "4.0.147",
3010
+ "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.147.tgz",
3011
+ "integrity": "sha512-oMBqHDFbMrI8WoJmHFT4SKygfxLcVqhuaNwRIgFQAgRKc90El99ftzFz7Bn8LYMnqVPjgOrlL6zY3jSH7dwtqA==",
3012
3012
  "license": "MIT",
3013
3013
  "dependencies": {
3014
3014
  "i": "^0.3.7",
@@ -13,7 +13,7 @@
13
13
  "license": "ISC",
14
14
  "dependencies": {
15
15
  "@types/node": "^20.9.2",
16
- "prostgles-client": "^4.0.146",
16
+ "prostgles-client": "^4.0.147",
17
17
  "prostgles-types": "^4.0.51",
18
18
  "socket.io-client": "^4.7.5"
19
19
  },
@@ -8,6 +8,12 @@ export const clientOnlyQueries = async (db: DBHandlerClient, auth: AuthHandler,
8
8
 
9
9
  await describe("Client only queries", async (t) => {
10
10
 
11
+ // await test("Social auth redirect routes work", async ( ) => {
12
+ // assert.equal(!!auth.login.withProvider.github, true);
13
+ // const response = await fetch("http://localhost:3001/auth/github");
14
+ // assert.equal(response.status, 302);
15
+ // });
16
+
11
17
  await test("SQL Stream more than 1k records", async ( ) => {
12
18
  const expectedRowCount = 2e3;
13
19
  await tryRunP("", async (resolve, reject) => {
@@ -266,6 +272,7 @@ export const clientOnlyQueries = async (db: DBHandlerClient, auth: AuthHandler,
266
272
 
267
273
  await test("SQL Stream table fields are the same as on default request", async ( ) => {
268
274
  await tryRunP("", async (resolve, reject) => {
275
+ await db.sql!("TRUNCATE planes RESTART IDENTITY CASCADE;", {});
269
276
  await db.sql!("INSERT INTO planes (last_updated) VALUES (56789);", {});
270
277
  const res = await db.sql!("SELECT * FROM planes", {}, { returnType: "stream" });
271
278
  const listener = async (packet: SocketSQLStreamPacket) => {
@@ -417,6 +424,7 @@ export const clientOnlyQueries = async (db: DBHandlerClient, auth: AuthHandler,
417
424
  const start = Date.now();
418
425
 
419
426
  await db.planes.delete!();
427
+ await db.sql!("TRUNCATE planes RESTART IDENTITY CASCADE;", {});
420
428
  let inserts = new Array(100).fill(null).map((d, i) => ({ id: i, flight_number: `FN${i}`, x: Math.random(), y: i }));
421
429
  await db.planes.insert!(inserts);
422
430
 
@@ -197,6 +197,14 @@ function dd(){
197
197
  log(req.originalUrl)
198
198
  res.sendFile(path.join(__dirname, '../../index.html'));
199
199
  },
200
+ registrations: {
201
+ websiteUrl: "http://localhost:3001",
202
+ github: {
203
+ clientID: "GITHUB_CLIENT_ID",
204
+ clientSecret: "GITHUB"
205
+ },
206
+ onRegister: console.log
207
+ },
200
208
  }
201
209
  },
202
210
  publishMethods: async (params) => {
@@ -239,7 +247,7 @@ function dd(){
239
247
  ],
240
248
  onReady: async ({ dbo, db }) => {
241
249
  log("prostgles onReady");
242
-
250
+
243
251
  try {
244
252
 
245
253
  if(isClientTest){
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "../..": {
23
23
  "name": "prostgles-server",
24
- "version": "4.2.139",
24
+ "version": "4.2.141",
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
27
  "body-parser": "^1.20.3",
@@ -216,10 +216,11 @@
216
216
  }
217
217
  },
218
218
  "node_modules/cross-spawn": {
219
- "version": "7.0.3",
220
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
221
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
219
+ "version": "7.0.6",
220
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
221
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
222
222
  "dev": true,
223
+ "license": "MIT",
223
224
  "dependencies": {
224
225
  "path-key": "^3.1.0",
225
226
  "shebang-command": "^2.0.0",
@@ -1396,9 +1397,9 @@
1396
1397
  }
1397
1398
  },
1398
1399
  "cross-spawn": {
1399
- "version": "7.0.3",
1400
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
1401
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
1400
+ "version": "7.0.6",
1401
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
1402
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
1402
1403
  "dev": true,
1403
1404
  "requires": {
1404
1405
  "path-key": "^3.1.0",
@@ -34,7 +34,8 @@ export const testPublishTypes = () => {
34
34
  },
35
35
  items3: "*"
36
36
  };
37
- const p123: PublishFullyTyped<DBSchemaGenerated> = p11;
37
+ const p123: PublishFullyTyped<DBSchemaGenerated> = p11;
38
+ //@ts-ignore
38
39
  const p1234: PublishFullyTyped = p1;
39
40
 
40
41
  const p12: PublishFullyTyped = "*";
@@ -1,166 +0,0 @@
1
- import { DBOFullyTyped } from "../DBSchemaBuilder";
2
- import { AuthHandler, getLoginClientInfo, HTTPCODES } from "./AuthHandler";
3
- import { AuthClientRequest, ExpressReq, ExpressRes } from "./AuthTypes";
4
- import { setAuthSignup } from "./setAuthSignup";
5
-
6
- export async function authInit(this: AuthHandler) {
7
- if (!this.opts) return;
8
-
9
- this.opts.sidKeyName = this.opts.sidKeyName || "session_id";
10
- const { sidKeyName, login, getUser, expressConfig } = this.opts;
11
- this.sidKeyName = this.opts.sidKeyName;
12
-
13
- if (typeof sidKeyName !== "string" && !login) {
14
- throw "Invalid auth: Provide { sidKeyName: string } ";
15
- }
16
- /**
17
- * Why ??? Collision with socket.io ???
18
- */
19
- if (this.sidKeyName === "sid") throw "sidKeyName cannot be 'sid' please provide another name.";
20
-
21
- if (!getUser) throw "getUser missing from auth config";
22
-
23
- if (expressConfig) {
24
- const { app, publicRoutes = [], onGetRequestOK, magicLinks, use } = expressConfig;
25
- if (publicRoutes.find(r => typeof r !== "string" || !r)) {
26
- throw "Invalid or empty string provided within publicRoutes "
27
- }
28
-
29
- setAuthSignup(expressConfig);
30
-
31
- if(use){
32
- app.use((req, res, next) => {
33
- use({
34
- req,
35
- res,
36
- next,
37
- getUser: () => this.getUser({ httpReq: req }) as any,
38
- dbo: this.dbo as DBOFullyTyped,
39
- db: this.db,
40
- })
41
- })
42
- }
43
-
44
- if (magicLinks && this.routes.magicLinks) {
45
- const { check } = magicLinks;
46
- if (!check) throw "Check must be defined for magicLinks";
47
-
48
- app.get(this.routes.magicLinks?.expressRoute, async (req: ExpressReq, res: ExpressRes) => {
49
- const { id } = req.params ?? {};
50
-
51
- if (typeof id !== "string" || !id) {
52
- res.status(HTTPCODES.BAD_REQUEST).json({ msg: "Invalid magic-link id. Expecting a string" });
53
- } else {
54
- try {
55
- const session = await this.throttledFunc(async () => {
56
- return check(id, this.dbo as any, this.db, getLoginClientInfo({ httpReq: req }));
57
- });
58
- if (!session) {
59
- res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Invalid magic-link" });
60
- } else {
61
- this.setCookieAndGoToReturnURLIFSet(session, { req, res });
62
- }
63
-
64
- } catch (e) {
65
- res.status(HTTPCODES.AUTH_ERROR).json({ msg: e });
66
- }
67
- }
68
- });
69
- }
70
-
71
- const loginRoute = this.routes?.login;
72
- if (loginRoute) {
73
- app.post(loginRoute, async (req: ExpressReq, res: ExpressRes) => {
74
- try {
75
- const start = Date.now();
76
- const { sid, expires } = await this.loginThrottled(req.body || {}, getLoginClientInfo({ httpReq: req })) || {};
77
- await this.prostgles.opts.onLog?.({
78
- type: "auth",
79
- command: "login",
80
- duration: Date.now() - start,
81
- sid,
82
- socketId: undefined,
83
- })
84
- if (sid) {
85
-
86
- this.setCookieAndGoToReturnURLIFSet({ sid, expires }, { req, res });
87
-
88
- } else {
89
- throw ("Internal error: no user or session")
90
- }
91
- } catch (err) {
92
- console.log(err)
93
- res.status(HTTPCODES.AUTH_ERROR).json({ err });
94
- }
95
-
96
- });
97
-
98
- if (this.routes.logoutGetPath && this.opts.logout) {
99
- app.get(this.routes.logoutGetPath, async (req: ExpressReq, res: ExpressRes) => {
100
- const sid = this.validateSid(req?.cookies?.[sidKeyName]);
101
- if (sid) {
102
- try {
103
- await this.throttledFunc(() => {
104
- return this.opts!.logout!(req?.cookies?.[sidKeyName], this.dbo as any, this.db);
105
- })
106
- } catch (err) {
107
- console.error(err);
108
- }
109
- }
110
- res.redirect("/")
111
- });
112
- }
113
-
114
- if (Array.isArray(publicRoutes)) {
115
-
116
- /* Redirect if not logged in and requesting non public content */
117
- app.get(this.routes.catchAll, async (req: ExpressReq, res: ExpressRes, next) => {
118
- const clientReq: AuthClientRequest = { httpReq: req }
119
- const getUser = this.getUser;
120
- if(this.prostgles.restApi){
121
- if(Object.values(this.prostgles.restApi.routes).some(restRoute => this.matchesRoute(restRoute.split("/:")[0], req.path))){
122
- next();
123
- return;
124
- }
125
- }
126
- try {
127
- const returnURL = this.getReturnUrl(req);
128
-
129
- /**
130
- * Requesting a User route
131
- */
132
- if (this.isUserRoute(req.path)) {
133
-
134
- /* Check auth. Redirect to login if unauthorized */
135
- const u = await getUser(clientReq);
136
- if (!u) {
137
- res.redirect(`${loginRoute}?returnURL=${encodeURIComponent(req.originalUrl)}`);
138
- return;
139
- }
140
-
141
- /* If authorized and going to returnUrl then redirect. Otherwise serve file */
142
- } else if (returnURL && (await getUser(clientReq))) {
143
-
144
- res.redirect(returnURL);
145
- return;
146
-
147
- /** If Logged in and requesting login then redirect to main page */
148
- } else if (this.matchesRoute(loginRoute, req.path) && (await getUser(clientReq))) {
149
-
150
- res.redirect("/");
151
- return;
152
- }
153
-
154
- onGetRequestOK?.(req, res, { getUser: () => getUser(clientReq), dbo: this.dbo as DBOFullyTyped, db: this.db })
155
-
156
- } catch (error) {
157
- console.error(error);
158
- const errorMessage = typeof error === "string" ? error : error instanceof Error ? error.message : "";
159
- res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Something went wrong when processing your request" + (errorMessage? (": " + errorMessage) : "") });
160
- }
161
-
162
- });
163
- }
164
- }
165
- }
166
- }