From e1401b66c780ed47ea7382ac99de3d87260c095a Mon Sep 17 00:00:00 2001 From: prostgles Date: Mon, 25 Nov 2024 11:47:49 +0200 Subject: [PATCH] fix auth providers --- lib/Auth/AuthHandler.ts | 78 ++++---- lib/Auth/AuthTypes.ts | 28 +-- lib/Auth/authInit.ts | 166 ----------------- .../{setAuthSignup.ts => setAuthProviders.ts} | 14 +- lib/Auth/setupAuthRoutes.ts | 169 ++++++++++++++++++ package-lock.json | 4 +- package.json | 2 +- tests/client/hooks.spec.ts | 11 +- tests/client/index.ts | 2 + tests/client/package-lock.json | 8 +- tests/client/package.json | 2 +- tests/clientOnlyQueries.spec.ts | 8 + tests/server/index.ts | 4 +- tests/server/package-lock.json | 15 +- tests/server/publishTypeCheck.ts | 3 +- 15 files changed, 253 insertions(+), 261 deletions(-) delete mode 100644 lib/Auth/authInit.ts rename lib/Auth/{setAuthSignup.ts => setAuthProviders.ts} (82%) create mode 100644 lib/Auth/setupAuthRoutes.ts diff --git a/lib/Auth/AuthHandler.ts b/lib/Auth/AuthHandler.ts index 15b1f539..85d8b184 100644 --- a/lib/Auth/AuthHandler.ts +++ b/lib/Auth/AuthHandler.ts @@ -5,8 +5,8 @@ import { removeExpressRoute } from "../FileManager/FileManager"; import { DB, DBHandlerServer, Prostgles } from "../Prostgles"; import { Auth, AuthClientRequest, AuthResult, BasicSession, ExpressReq, ExpressRes, LoginClientInfo } from "./AuthTypes" import { getSafeReturnURL } from "./getSafeReturnURL"; -import { authInit } from "./authInit"; -import { getProviders } from "./setAuthSignup"; +import { setupAuthRoutes } from "./setupAuthRoutes"; +import { getProviders } from "./setAuthProviders"; export const HTTPCODES = { AUTH_ERROR: 401, @@ -38,48 +38,36 @@ export const getLoginClientInfo = (req: AuthClientRequest): AuthClientRequest & } } +export const AUTH_ROUTES_AND_PARAMS = { + login: "/login", + loginWithProvider: "/auth", + emailSignup: "/register", + returnUrlParamName: "returnURL", + sidKeyName: "session_id", + logoutGetPath: "/logout", + magicLinksRoute: "/magic-link", + magicLinksExpressRoute: "/magic-link/:id", + catchAll: "*", +} as const; + export class AuthHandler { protected prostgles: Prostgles; protected opts?: Auth; dbo: DBHandlerServer; db: DB; - sidKeyName?: string; - - routes: { - login?: string; - returnUrlParamName?: string; - logoutGetPath?: string; - magicLinks?: { - route: string; - expressRoute: string; - } - readonly catchAll: '*'; - } = { - catchAll: "*" - } constructor(prostgles: Prostgles) { this.prostgles = prostgles; this.opts = prostgles.opts.auth as any; - if (prostgles.opts.auth?.expressConfig) { - const { magicLinks, returnUrlParamName, loginRoute, logoutGetPath } = prostgles.opts.auth.expressConfig; - const magicLinksRoute = magicLinks?.route || "/magic-link" - this.routes = { - magicLinks: magicLinks? { - expressRoute: `${magicLinksRoute}/:id`, - route: magicLinksRoute - } : undefined, - returnUrlParamName: returnUrlParamName || "returnURL", - login: loginRoute || "/login", - logoutGetPath: logoutGetPath || "/logout", - catchAll: "*" - } - } if(!prostgles.dbo || !prostgles.db) throw "dbo or db missing"; this.dbo = prostgles.dbo; this.db = prostgles.db; } + get sidKeyName() { + return this.opts?.sidKeyName ?? AUTH_ROUTES_AND_PARAMS.sidKeyName; + } + validateSid = (sid: string | undefined) => { if (!sid) return undefined; if (typeof sid !== "string") throw "sid missing or not a string"; @@ -94,12 +82,11 @@ export class AuthHandler { } isUserRoute = (pathname: string) => { + const { login, logoutGetPath, magicLinksRoute, loginWithProvider } = AUTH_ROUTES_AND_PARAMS; const pubRoutes = [ ...this.opts?.expressConfig?.publicRoutes || [], - ]; - if (this.routes?.login) pubRoutes.push(this.routes.login); - if (this.routes?.logoutGetPath) pubRoutes.push(this.routes.logoutGetPath); - if (this.routes?.magicLinks?.route) pubRoutes.push(this.routes.magicLinks.route); + login, logoutGetPath, magicLinksRoute, loginWithProvider, + ].filter(publicRoute => publicRoute); return !pubRoutes.some(publicRoute => { return this.matchesRoute(publicRoute, pathname); @@ -133,7 +120,6 @@ export class AuthHandler { ...(this.opts?.expressConfig?.cookieOptions || {}) }; const cookieData = sid; - if(!this.sidKeyName || !this.routes?.returnUrlParamName) throw "sidKeyName or returnURL missing" res.cookie(this.sidKeyName, cookieData, cookieOpts); const successURL = this.getReturnUrl(req) || "/"; res.redirect(successURL); @@ -144,8 +130,8 @@ export class AuthHandler { } getUser = async (clientReq: { httpReq: ExpressReq; }): Promise => { - if(!this.sidKeyName || !this.opts?.getUser) { - throw "sidKeyName or this.opts.getUser missing"; + if(!this.opts?.getUser) { + throw "this.opts.getUser missing"; } const sid = clientReq.httpReq?.cookies?.[this.sidKeyName]; if (!sid) return undefined; @@ -160,10 +146,10 @@ export class AuthHandler { return undefined; } - init = authInit.bind(this); + init = setupAuthRoutes.bind(this); getReturnUrl = (req: ExpressReq) => { - const { returnUrlParamName } = this.routes; + const { returnUrlParamName } = AUTH_ROUTES_AND_PARAMS; if (returnUrlParamName && req?.query?.[returnUrlParamName]) { const returnURL = decodeURIComponent(req?.query?.[returnUrlParamName] as string); @@ -174,8 +160,8 @@ export class AuthHandler { destroy = () => { const app = this.opts?.expressConfig?.app; - const { login, logoutGetPath, magicLinks } = this.routes; - removeExpressRoute(app, [login, logoutGetPath, magicLinks?.expressRoute]); + const { login, logoutGetPath, magicLinksExpressRoute, catchAll, loginWithProvider } = AUTH_ROUTES_AND_PARAMS; + removeExpressRoute(app, [login, logoutGetPath, magicLinksExpressRoute, catchAll, loginWithProvider]); } throttledFunc = (func: () => Promise, throttle = 500): Promise => { @@ -246,10 +232,8 @@ export class AuthHandler { getSID(localParams: LocalParams): string | undefined { if (!this.opts) return undefined; - const { sidKeyName } = this.opts; - - if (!sidKeyName || !localParams) return undefined; - + if (!localParams) return undefined; + const { sidKeyName } = this; if (localParams.socket) { const { handshake } = localParams.socket; const querySid = handshake?.auth?.[sidKeyName] || handshake?.query?.[sidKeyName]; @@ -463,8 +447,8 @@ export class AuthHandler { const userData = await this.getClientInfo(clientReq); const auth: AuthSocketSchema = { - providers: getProviders(this.opts?.expressConfig?.registrations), - register: this.opts?.expressConfig?.registrations?.email && { type: this.opts?.expressConfig?.registrations?.email.signupType, url: "/register" }, + providers: getProviders.bind(this)(), + register: this.opts?.expressConfig?.registrations?.email && { type: this.opts?.expressConfig?.registrations?.email.signupType, url: AUTH_ROUTES_AND_PARAMS.emailSignup }, user: userData?.clientUser, loginType: this.opts?.expressConfig?.registrations?.email?.signupType, pathGuard, diff --git a/lib/Auth/AuthTypes.ts b/lib/Auth/AuthTypes.ts index afc7e31e..57cc4c37 100644 --- a/lib/Auth/AuthTypes.ts +++ b/lib/Auth/AuthTypes.ts @@ -154,22 +154,19 @@ export type Auth = { */ responseThrottle?: number; + /** + * Will setup auth routes + * /login + * /logout + * /magic-link/:id + */ expressConfig?: { + /** * Express app instance. If provided Prostgles will attempt to set sidKeyName to user cookie */ app: Express; - /** - * Used in allowing logging in through express. Defaults to /login - */ - loginRoute?: string; - - /** - * Used in allowing logging out through express. Defaults to /logout - */ - logoutGetPath?: string; - /** * Options used in setting the cookie after a successful login */ @@ -202,22 +199,11 @@ export type Auth = { params: AuthRequestParams ) => any; - /** - * Name of get url parameter used in redirecting user after successful login. - * Defaults to "returnURL" - */ - returnUrlParamName?: string; - /** * If defined, will check the magic link id and log in the user and redirect to the returnUrl if set */ magicLinks?: { - /** - * Will default to /magic-link - */ - route?: string; - /** * Used in creating a session/logging in using a magic link */ diff --git a/lib/Auth/authInit.ts b/lib/Auth/authInit.ts deleted file mode 100644 index fe963f1c..00000000 --- a/lib/Auth/authInit.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { DBOFullyTyped } from "../DBSchemaBuilder"; -import { AuthHandler, getLoginClientInfo, HTTPCODES } from "./AuthHandler"; -import { AuthClientRequest, ExpressReq, ExpressRes } from "./AuthTypes"; -import { setAuthSignup } from "./setAuthSignup"; - -export async function authInit(this: AuthHandler) { - if (!this.opts) return; - - this.opts.sidKeyName = this.opts.sidKeyName || "session_id"; - const { sidKeyName, login, getUser, expressConfig } = this.opts; - this.sidKeyName = this.opts.sidKeyName; - - if (typeof sidKeyName !== "string" && !login) { - throw "Invalid auth: Provide { sidKeyName: string } "; - } - /** - * Why ??? Collision with socket.io ??? - */ - if (this.sidKeyName === "sid") throw "sidKeyName cannot be 'sid' please provide another name."; - - if (!getUser) throw "getUser missing from auth config"; - - if (expressConfig) { - const { app, publicRoutes = [], onGetRequestOK, magicLinks, use } = expressConfig; - if (publicRoutes.find(r => typeof r !== "string" || !r)) { - throw "Invalid or empty string provided within publicRoutes " - } - - setAuthSignup(expressConfig); - - if(use){ - app.use((req, res, next) => { - use({ - req, - res, - next, - getUser: () => this.getUser({ httpReq: req }) as any, - dbo: this.dbo as DBOFullyTyped, - db: this.db, - }) - }) - } - - if (magicLinks && this.routes.magicLinks) { - const { check } = magicLinks; - if (!check) throw "Check must be defined for magicLinks"; - - app.get(this.routes.magicLinks?.expressRoute, async (req: ExpressReq, res: ExpressRes) => { - const { id } = req.params ?? {}; - - if (typeof id !== "string" || !id) { - res.status(HTTPCODES.BAD_REQUEST).json({ msg: "Invalid magic-link id. Expecting a string" }); - } else { - try { - const session = await this.throttledFunc(async () => { - return check(id, this.dbo as any, this.db, getLoginClientInfo({ httpReq: req })); - }); - if (!session) { - res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Invalid magic-link" }); - } else { - this.setCookieAndGoToReturnURLIFSet(session, { req, res }); - } - - } catch (e) { - res.status(HTTPCODES.AUTH_ERROR).json({ msg: e }); - } - } - }); - } - - const loginRoute = this.routes?.login; - if (loginRoute) { - app.post(loginRoute, async (req: ExpressReq, res: ExpressRes) => { - try { - const start = Date.now(); - const { sid, expires } = await this.loginThrottled(req.body || {}, getLoginClientInfo({ httpReq: req })) || {}; - await this.prostgles.opts.onLog?.({ - type: "auth", - command: "login", - duration: Date.now() - start, - sid, - socketId: undefined, - }) - if (sid) { - - this.setCookieAndGoToReturnURLIFSet({ sid, expires }, { req, res }); - - } else { - throw ("Internal error: no user or session") - } - } catch (err) { - console.log(err) - res.status(HTTPCODES.AUTH_ERROR).json({ err }); - } - - }); - - if (this.routes.logoutGetPath && this.opts.logout) { - app.get(this.routes.logoutGetPath, async (req: ExpressReq, res: ExpressRes) => { - const sid = this.validateSid(req?.cookies?.[sidKeyName]); - if (sid) { - try { - await this.throttledFunc(() => { - return this.opts!.logout!(req?.cookies?.[sidKeyName], this.dbo as any, this.db); - }) - } catch (err) { - console.error(err); - } - } - res.redirect("/") - }); - } - - if (Array.isArray(publicRoutes)) { - - /* Redirect if not logged in and requesting non public content */ - app.get(this.routes.catchAll, async (req: ExpressReq, res: ExpressRes, next) => { - const clientReq: AuthClientRequest = { httpReq: req } - const getUser = this.getUser; - if(this.prostgles.restApi){ - if(Object.values(this.prostgles.restApi.routes).some(restRoute => this.matchesRoute(restRoute.split("/:")[0], req.path))){ - next(); - return; - } - } - try { - const returnURL = this.getReturnUrl(req); - - /** - * Requesting a User route - */ - if (this.isUserRoute(req.path)) { - - /* Check auth. Redirect to login if unauthorized */ - const u = await getUser(clientReq); - if (!u) { - res.redirect(`${loginRoute}?returnURL=${encodeURIComponent(req.originalUrl)}`); - return; - } - - /* If authorized and going to returnUrl then redirect. Otherwise serve file */ - } else if (returnURL && (await getUser(clientReq))) { - - res.redirect(returnURL); - return; - - /** If Logged in and requesting login then redirect to main page */ - } else if (this.matchesRoute(loginRoute, req.path) && (await getUser(clientReq))) { - - res.redirect("/"); - return; - } - - onGetRequestOK?.(req, res, { getUser: () => getUser(clientReq), dbo: this.dbo as DBOFullyTyped, db: this.db }) - - } catch (error) { - console.error(error); - const errorMessage = typeof error === "string" ? error : error instanceof Error ? error.message : ""; - res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Something went wrong when processing your request" + (errorMessage? (": " + errorMessage) : "") }); - } - - }); - } - } - } -} \ No newline at end of file diff --git a/lib/Auth/setAuthSignup.ts b/lib/Auth/setAuthProviders.ts similarity index 82% rename from lib/Auth/setAuthSignup.ts rename to lib/Auth/setAuthProviders.ts index 956492de..b994ddfc 100644 --- a/lib/Auth/setAuthSignup.ts +++ b/lib/Auth/setAuthProviders.ts @@ -6,12 +6,13 @@ import { Strategy as GitHubStrategy } from "passport-github2"; import { Strategy as MicrosoftStrategy } from "passport-microsoft"; import { Strategy as FacebookStrategy } from "passport-facebook"; import { AuthSocketSchema, getKeys, isDefined, isEmpty } from "prostgles-types"; +import { AUTH_ROUTES_AND_PARAMS, AuthHandler } from "./AuthHandler"; -export const setAuthSignup = ({ registrations, app }: Required["expressConfig"]) => { +export function setAuthProviders (this: AuthHandler, { registrations, app }: Required["expressConfig"]) { if(!registrations) return; const { email, onRegister, websiteUrl, ...providers } = registrations; if(email){ - app.post("/signup", async (req, res) => { + app.post(AUTH_ROUTES_AND_PARAMS.emailSignup, async (req, res) => { const { username, password } = req.body; if(typeof username !== "string" || typeof password !== "string"){ res.status(400).json({ msg: "Invalid username or password" }); @@ -54,7 +55,7 @@ export const setAuthSignup = ({ registrations, app }: Required["expressCon providerName, }) => { - const callbackPath = `/auth/${providerName}/callback`; + const callbackPath = `${AUTH_ROUTES_AND_PARAMS.loginWithProvider}/${providerName}/callback`; passport.use( new (strategy as typeof GoogleStrategy)( { @@ -69,7 +70,7 @@ export const setAuthSignup = ({ registrations, app }: Required["expressCon ) ); - app.get(`/auth/${providerName}`, + app.get(`${AUTH_ROUTES_AND_PARAMS.loginWithProvider}/${providerName}`, passport.authenticate(providerName, authOpts ?? {}) ); @@ -83,7 +84,8 @@ export const setAuthSignup = ({ registrations, app }: Required["expressCon }); } -export const getProviders = (registrations: Required["expressConfig"]["registrations"]): AuthSocketSchema["providers"] | undefined => { +export function getProviders(this: AuthHandler): AuthSocketSchema["providers"] | undefined { + const { registrations } = this.opts?.expressConfig ?? {} if(!registrations) return undefined; const { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -96,7 +98,7 @@ export const getProviders = (registrations: Required["expressConfig"]["reg getKeys(providers).forEach(providerName => { if(providers[providerName]?.clientID){ result[providerName] = { - url: `/auth/${providerName}`, + url: `${AUTH_ROUTES_AND_PARAMS.loginWithProvider}/${providerName}`, } } }); diff --git a/lib/Auth/setupAuthRoutes.ts b/lib/Auth/setupAuthRoutes.ts new file mode 100644 index 00000000..2b51832c --- /dev/null +++ b/lib/Auth/setupAuthRoutes.ts @@ -0,0 +1,169 @@ +import { DBOFullyTyped } from "../DBSchemaBuilder"; +import { AUTH_ROUTES_AND_PARAMS, AuthHandler, getLoginClientInfo, HTTPCODES } from "./AuthHandler"; +import { AuthClientRequest, ExpressReq, ExpressRes } from "./AuthTypes"; +import { setAuthProviders } from "./setAuthProviders"; + +export async function setupAuthRoutes(this: AuthHandler) { + if (!this.opts) return; + + const { login, getUser, expressConfig } = this.opts; + + if (!login) { + throw "Invalid auth: Provide { sidKeyName: string } "; + } + + if ((AUTH_ROUTES_AND_PARAMS.sidKeyName as any) === "sid") { + throw "sidKeyName cannot be 'sid' due to collision with socket.io"; + } + + if (!getUser) throw "getUser missing from auth config"; + + if (!expressConfig) { + return + } + const { app, publicRoutes = [], onGetRequestOK, magicLinks, use } = expressConfig; + if (publicRoutes.find(r => typeof r !== "string" || !r)) { + throw "Invalid or empty string provided within publicRoutes " + } + + setAuthProviders.bind(this)(expressConfig); + + if(use){ + app.use((req, res, next) => { + use({ + req, + res, + next, + getUser: () => this.getUser({ httpReq: req }) as any, + dbo: this.dbo as DBOFullyTyped, + db: this.db, + }) + }) + } + + if (magicLinks) { + const { check } = magicLinks; + if (!check) { + throw "Check must be defined for magicLinks"; + } + + app.get(AUTH_ROUTES_AND_PARAMS.magicLinksExpressRoute, async (req: ExpressReq, res: ExpressRes) => { + const { id } = req.params ?? {}; + + if (typeof id !== "string" || !id) { + res.status(HTTPCODES.BAD_REQUEST).json({ msg: "Invalid magic-link id. Expecting a string" }); + } else { + try { + const session = await this.throttledFunc(async () => { + return check(id, this.dbo as any, this.db, getLoginClientInfo({ httpReq: req })); + }); + if (!session) { + res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Invalid magic-link" }); + } else { + this.setCookieAndGoToReturnURLIFSet(session, { req, res }); + } + + } catch (e) { + res.status(HTTPCODES.AUTH_ERROR).json({ msg: e }); + } + } + }); + } + + app.post(AUTH_ROUTES_AND_PARAMS.login, async (req: ExpressReq, res: ExpressRes) => { + try { + const start = Date.now(); + const { sid, expires } = await this.loginThrottled(req.body || {}, getLoginClientInfo({ httpReq: req })) || {}; + await this.prostgles.opts.onLog?.({ + type: "auth", + command: "login", + duration: Date.now() - start, + sid, + socketId: undefined, + }) + if (sid) { + + this.setCookieAndGoToReturnURLIFSet({ sid, expires }, { req, res }); + + } else { + throw ("Internal error: no user or session") + } + } catch (err) { + console.log(err) + res.status(HTTPCODES.AUTH_ERROR).json({ err }); + } + + }); + + if (AUTH_ROUTES_AND_PARAMS.logoutGetPath && this.opts.logout) { + app.get(AUTH_ROUTES_AND_PARAMS.logoutGetPath, async (req: ExpressReq, res: ExpressRes) => { + const sid = this.validateSid(req?.cookies?.[AUTH_ROUTES_AND_PARAMS.sidKeyName]); + if (sid) { + try { + await this.throttledFunc(() => { + return this.opts!.logout!(req?.cookies?.[AUTH_ROUTES_AND_PARAMS.sidKeyName], this.dbo as any, this.db); + }) + } catch (err) { + console.error(err); + } + } + res.redirect("/") + }); + } + + if (Array.isArray(publicRoutes)) { + + /* Redirect if not logged in and requesting non public content */ + app.get(AUTH_ROUTES_AND_PARAMS.catchAll, async (req: ExpressReq, res: ExpressRes, next) => { + + const clientReq: AuthClientRequest = { httpReq: req }; + const getUser = this.getUser; + if(this.prostgles.restApi){ + if(Object.values(this.prostgles.restApi.routes).some(restRoute => this.matchesRoute(restRoute.split("/:")[0], req.path))){ + next(); + return; + } + } + try { + const returnURL = this.getReturnUrl(req); + + if(this.matchesRoute(AUTH_ROUTES_AND_PARAMS.loginWithProvider, req.path)){ + next(); + return; + } + /** + * Requesting a User route + */ + if (this.isUserRoute(req.path)) { + + /* Check auth. Redirect to login if unauthorized */ + const u = await getUser(clientReq); + if (!u) { + res.redirect(`${AUTH_ROUTES_AND_PARAMS.login}?returnURL=${encodeURIComponent(req.originalUrl)}`); + return; + } + + /* If authorized and going to returnUrl then redirect. Otherwise serve file */ + } else if (returnURL && (await getUser(clientReq))) { + + res.redirect(returnURL); + return; + + /** If Logged in and requesting login then redirect to main page */ + } else if (this.matchesRoute(AUTH_ROUTES_AND_PARAMS.login, req.path) && (await getUser(clientReq))) { + + res.redirect("/"); + return; + } + + onGetRequestOK?.(req, res, { getUser: () => getUser(clientReq), dbo: this.dbo as DBOFullyTyped, db: this.db }) + + } catch (error) { + console.error(error); + const errorMessage = typeof error === "string" ? error : error instanceof Error ? error.message : ""; + res.status(HTTPCODES.AUTH_ERROR).json({ msg: "Something went wrong when processing your request" + (errorMessage? (": " + errorMessage) : "") }); + } + + }); + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 1529eccc..f9cc6f32 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "prostgles-server", - "version": "4.2.140", + "version": "4.2.141", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "prostgles-server", - "version": "4.2.140", + "version": "4.2.141", "license": "MIT", "dependencies": { "body-parser": "^1.20.3", diff --git a/package.json b/package.json index 384832c2..b8db2665 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prostgles-server", - "version": "4.2.140", + "version": "4.2.141", "description": "", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/tests/client/hooks.spec.ts b/tests/client/hooks.spec.ts index 3113c710..71a663ee 100644 --- a/tests/client/hooks.spec.ts +++ b/tests/client/hooks.spec.ts @@ -147,10 +147,15 @@ export const clientHooks = async (db: DBHandlerClient, getSocketOptions: (watchS expectedRerenders: 3 }); assert.equal(results.length, 3); - assert.deepStrictEqual(results.slice(0, 2), [ - { data: undefined, isLoading: true, error: undefined }, + assert.deepStrictEqual( + results[0], + { data: undefined, isLoading: true, error: undefined } + ); + /** This fails from time to time */ + assert.deepStrictEqual( + results[1], { data: [], error: undefined, isLoading: false }, - ]); + ); const lastData = results.at(-1)?.data; assert.equal(lastData.length, 1); const lastDataItem = lastData[0]; diff --git a/tests/client/index.ts b/tests/client/index.ts index 7affaab5..1b2e62e2 100644 --- a/tests/client/index.ts +++ b/tests/client/index.ts @@ -106,10 +106,12 @@ try { onReady: async (db, methods, tableSchema, auth, isReconnect) => { log(`TEST_NAME: ${TEST_NAME} Started`) try { + //@ts-ignore if(typeof window !== "undefined"){ const onLog = (...args: any[]) => { socket.emit("log", args.map(v => typeof v === "object"? JSON.stringify(v) : v).join(" ")); } + //@ts-ignore window.onerror = function myErrorHandler(errorMsg, url, lineNumber) { console.error("Error occured: " + errorMsg); stopTest({ err: errorMsg }); diff --git a/tests/client/package-lock.json b/tests/client/package-lock.json index 53879b62..990c4243 100644 --- a/tests/client/package-lock.json +++ b/tests/client/package-lock.json @@ -10,7 +10,7 @@ "license": "ISC", "dependencies": { "@types/node": "^20.9.2", - "prostgles-client": "^4.0.146", + "prostgles-client": "^4.0.147", "prostgles-types": "^4.0.51", "socket.io-client": "^4.7.5" }, @@ -3006,9 +3006,9 @@ } }, "node_modules/prostgles-client": { - "version": "4.0.146", - "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.146.tgz", - "integrity": "sha512-Xpy+mhnIERPly8GXNMvrkcJzDXbqlNMDhW+f+K2PqTceyQPxRVZGeFckWuguHXIy8NYB6qPPXa+nhQaHnag6Hw==", + "version": "4.0.147", + "resolved": "https://registry.npmjs.org/prostgles-client/-/prostgles-client-4.0.147.tgz", + "integrity": "sha512-oMBqHDFbMrI8WoJmHFT4SKygfxLcVqhuaNwRIgFQAgRKc90El99ftzFz7Bn8LYMnqVPjgOrlL6zY3jSH7dwtqA==", "license": "MIT", "dependencies": { "i": "^0.3.7", diff --git a/tests/client/package.json b/tests/client/package.json index ca74367a..70f16b87 100644 --- a/tests/client/package.json +++ b/tests/client/package.json @@ -13,7 +13,7 @@ "license": "ISC", "dependencies": { "@types/node": "^20.9.2", - "prostgles-client": "^4.0.146", + "prostgles-client": "^4.0.147", "prostgles-types": "^4.0.51", "socket.io-client": "^4.7.5" }, diff --git a/tests/clientOnlyQueries.spec.ts b/tests/clientOnlyQueries.spec.ts index 634d8ea2..5da1cd1d 100644 --- a/tests/clientOnlyQueries.spec.ts +++ b/tests/clientOnlyQueries.spec.ts @@ -8,6 +8,12 @@ export const clientOnlyQueries = async (db: DBHandlerClient, auth: AuthHandler, await describe("Client only queries", async (t) => { + // await test("Social auth redirect routes work", async ( ) => { + // assert.equal(!!auth.login.withProvider.github, true); + // const response = await fetch("http://localhost:3001/auth/github"); + // assert.equal(response.status, 302); + // }); + await test("SQL Stream more than 1k records", async ( ) => { const expectedRowCount = 2e3; await tryRunP("", async (resolve, reject) => { @@ -266,6 +272,7 @@ export const clientOnlyQueries = async (db: DBHandlerClient, auth: AuthHandler, await test("SQL Stream table fields are the same as on default request", async ( ) => { await tryRunP("", async (resolve, reject) => { + await db.sql!("TRUNCATE planes RESTART IDENTITY CASCADE;", {}); await db.sql!("INSERT INTO planes (last_updated) VALUES (56789);", {}); const res = await db.sql!("SELECT * FROM planes", {}, { returnType: "stream" }); const listener = async (packet: SocketSQLStreamPacket) => { @@ -417,6 +424,7 @@ export const clientOnlyQueries = async (db: DBHandlerClient, auth: AuthHandler, const start = Date.now(); await db.planes.delete!(); + await db.sql!("TRUNCATE planes RESTART IDENTITY CASCADE;", {}); let inserts = new Array(100).fill(null).map((d, i) => ({ id: i, flight_number: `FN${i}`, x: Math.random(), y: i })); await db.planes.insert!(inserts); diff --git a/tests/server/index.ts b/tests/server/index.ts index d952ba30..62924f34 100644 --- a/tests/server/index.ts +++ b/tests/server/index.ts @@ -198,7 +198,7 @@ function dd(){ res.sendFile(path.join(__dirname, '../../index.html')); }, registrations: { - websiteUrl: "http://localhost:3000", + websiteUrl: "http://localhost:3001", github: { clientID: "GITHUB_CLIENT_ID", clientSecret: "GITHUB" @@ -247,7 +247,7 @@ function dd(){ ], onReady: async ({ dbo, db }) => { log("prostgles onReady"); - + try { if(isClientTest){ diff --git a/tests/server/package-lock.json b/tests/server/package-lock.json index 70ef9e87..1e6eca43 100644 --- a/tests/server/package-lock.json +++ b/tests/server/package-lock.json @@ -21,7 +21,7 @@ }, "../..": { "name": "prostgles-server", - "version": "4.2.140", + "version": "4.2.141", "license": "MIT", "dependencies": { "body-parser": "^1.20.3", @@ -216,10 +216,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -1396,9 +1397,9 @@ } }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "path-key": "^3.1.0", diff --git a/tests/server/publishTypeCheck.ts b/tests/server/publishTypeCheck.ts index adc3c514..aa56db7a 100644 --- a/tests/server/publishTypeCheck.ts +++ b/tests/server/publishTypeCheck.ts @@ -34,7 +34,8 @@ export const testPublishTypes = () => { }, items3: "*" }; - const p123: PublishFullyTyped = p11; + const p123: PublishFullyTyped = p11; + //@ts-ignore const p1234: PublishFullyTyped = p1; const p12: PublishFullyTyped = "*";