prostgles-server 4.2.157 → 4.2.159
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/dist/Auth/AuthHandler.js +2 -2
- package/dist/Auth/AuthHandler.js.map +1 -1
- package/dist/Auth/AuthTypes.d.ts +4 -8
- package/dist/Auth/AuthTypes.d.ts.map +1 -1
- package/dist/Auth/setAuthProviders.d.ts +1 -1
- package/dist/Auth/setAuthProviders.d.ts.map +1 -1
- package/dist/Auth/setAuthProviders.js +6 -7
- package/dist/Auth/setAuthProviders.js.map +1 -1
- package/dist/Auth/setEmailProvider.d.ts +1 -1
- package/dist/Auth/setEmailProvider.d.ts.map +1 -1
- package/dist/Auth/setEmailProvider.js +22 -2
- package/dist/Auth/setEmailProvider.js.map +1 -1
- package/dist/Auth/setupAuthRoutes.js +1 -1
- package/dist/Auth/setupAuthRoutes.js.map +1 -1
- package/dist/Prostgles.d.ts +1 -0
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +6 -0
- package/dist/Prostgles.js.map +1 -1
- package/dist/initProstgles.d.ts.map +1 -1
- package/dist/initProstgles.js +2 -6
- package/dist/initProstgles.js.map +1 -1
- package/package.json +1 -1
- package/lib/Auth/AuthHandler.ts +0 -436
- package/lib/Auth/AuthTypes.ts +0 -285
- package/lib/Auth/getSafeReturnURL.ts +0 -35
- package/lib/Auth/sendEmail.ts +0 -83
- package/lib/Auth/setAuthProviders.ts +0 -129
- package/lib/Auth/setEmailProvider.ts +0 -63
- package/lib/Auth/setupAuthRoutes.ts +0 -161
- package/lib/DBEventsManager.ts +0 -178
- package/lib/DBSchemaBuilder.ts +0 -225
- package/lib/DboBuilder/DboBuilder.ts +0 -319
- package/lib/DboBuilder/DboBuilderTypes.ts +0 -361
- package/lib/DboBuilder/QueryBuilder/Functions.ts +0 -1153
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +0 -288
- package/lib/DboBuilder/QueryBuilder/getJoinQuery.ts +0 -263
- package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +0 -271
- package/lib/DboBuilder/QueryBuilder/getSelectQuery.ts +0 -136
- package/lib/DboBuilder/QueryBuilder/prepareHaving.ts +0 -22
- package/lib/DboBuilder/QueryStreamer.ts +0 -250
- package/lib/DboBuilder/TableHandler/DataValidator.ts +0 -428
- package/lib/DboBuilder/TableHandler/TableHandler.ts +0 -205
- package/lib/DboBuilder/TableHandler/delete.ts +0 -115
- package/lib/DboBuilder/TableHandler/insert.ts +0 -183
- package/lib/DboBuilder/TableHandler/insertTest.ts +0 -78
- package/lib/DboBuilder/TableHandler/onDeleteFromFileTable.ts +0 -62
- package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +0 -134
- package/lib/DboBuilder/TableHandler/update.ts +0 -126
- package/lib/DboBuilder/TableHandler/updateBatch.ts +0 -49
- package/lib/DboBuilder/TableHandler/updateFile.ts +0 -48
- package/lib/DboBuilder/TableHandler/upsert.ts +0 -34
- package/lib/DboBuilder/ViewHandler/ViewHandler.ts +0 -393
- package/lib/DboBuilder/ViewHandler/count.ts +0 -38
- package/lib/DboBuilder/ViewHandler/find.ts +0 -153
- package/lib/DboBuilder/ViewHandler/getExistsCondition.ts +0 -73
- package/lib/DboBuilder/ViewHandler/getExistsFilters.ts +0 -74
- package/lib/DboBuilder/ViewHandler/getInfo.ts +0 -32
- package/lib/DboBuilder/ViewHandler/getTableJoinQuery.ts +0 -84
- package/lib/DboBuilder/ViewHandler/parseComplexFilter.ts +0 -96
- package/lib/DboBuilder/ViewHandler/parseFieldFilter.ts +0 -105
- package/lib/DboBuilder/ViewHandler/parseJoinPath.ts +0 -208
- package/lib/DboBuilder/ViewHandler/prepareSortItems.ts +0 -163
- package/lib/DboBuilder/ViewHandler/prepareWhere.ts +0 -90
- package/lib/DboBuilder/ViewHandler/size.ts +0 -37
- package/lib/DboBuilder/ViewHandler/subscribe.ts +0 -118
- package/lib/DboBuilder/ViewHandler/validateViewRules.ts +0 -70
- package/lib/DboBuilder/dboBuilderUtils.ts +0 -222
- package/lib/DboBuilder/getColumns.ts +0 -114
- package/lib/DboBuilder/getCondition.ts +0 -201
- package/lib/DboBuilder/getSubscribeRelatedTables.ts +0 -190
- package/lib/DboBuilder/getTablesForSchemaPostgresSQL.ts +0 -426
- package/lib/DboBuilder/insertNestedRecords.ts +0 -355
- package/lib/DboBuilder/parseUpdateRules.ts +0 -187
- package/lib/DboBuilder/prepareShortestJoinPaths.ts +0 -186
- package/lib/DboBuilder/runSQL.ts +0 -182
- package/lib/DboBuilder/runTransaction.ts +0 -50
- package/lib/DboBuilder/sqlErrCodeToMsg.ts +0 -254
- package/lib/DboBuilder/uploadFile.ts +0 -69
- package/lib/Event_Trigger_Tags.ts +0 -118
- package/lib/FileManager/FileManager.ts +0 -358
- package/lib/FileManager/getValidatedFileType.ts +0 -69
- package/lib/FileManager/initFileManager.ts +0 -187
- package/lib/FileManager/upload.ts +0 -62
- package/lib/FileManager/uploadStream.ts +0 -79
- package/lib/Filtering.ts +0 -463
- package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +0 -502
- package/lib/JSONBValidation/validation.ts +0 -143
- package/lib/Logging.ts +0 -127
- package/lib/PostgresNotifListenManager.ts +0 -143
- package/lib/Prostgles.ts +0 -479
- package/lib/ProstglesTypes.ts +0 -196
- package/lib/PubSubManager/PubSubManager.ts +0 -609
- package/lib/PubSubManager/addSub.ts +0 -138
- package/lib/PubSubManager/addSync.ts +0 -141
- package/lib/PubSubManager/getCreatePubSubManagerError.ts +0 -72
- package/lib/PubSubManager/getPubSubManagerInitQuery.ts +0 -662
- package/lib/PubSubManager/initPubSubManager.ts +0 -79
- package/lib/PubSubManager/notifListener.ts +0 -173
- package/lib/PubSubManager/orphanTriggerCheck.ts +0 -70
- package/lib/PubSubManager/pushSubData.ts +0 -55
- package/lib/PublishParser/PublishParser.ts +0 -162
- package/lib/PublishParser/getFileTableRules.ts +0 -124
- package/lib/PublishParser/getSchemaFromPublish.ts +0 -141
- package/lib/PublishParser/getTableRulesWithoutFileTable.ts +0 -177
- package/lib/PublishParser/publishTypesAndUtils.ts +0 -399
- package/lib/RestApi.ts +0 -127
- package/lib/SchemaWatch/SchemaWatch.ts +0 -90
- package/lib/SchemaWatch/createSchemaWatchEventTrigger.ts +0 -3
- package/lib/SchemaWatch/getValidatedWatchSchemaType.ts +0 -45
- package/lib/SchemaWatch/getWatchSchemaTagList.ts +0 -27
- package/lib/SyncReplication.ts +0 -557
- package/lib/TableConfig/TableConfig.ts +0 -468
- package/lib/TableConfig/getColumnDefinitionQuery.ts +0 -111
- package/lib/TableConfig/getConstraintDefinitionQueries.ts +0 -95
- package/lib/TableConfig/getFutureTableSchema.ts +0 -64
- package/lib/TableConfig/getPGIndexes.ts +0 -53
- package/lib/TableConfig/getTableColumnQueries.ts +0 -129
- package/lib/TableConfig/initTableConfig.ts +0 -326
- package/lib/index.ts +0 -13
- package/lib/initProstgles.ts +0 -322
- package/lib/onSocketConnected.ts +0 -102
- package/lib/runClientRequest.ts +0 -129
- package/lib/shortestPath.ts +0 -122
- package/lib/typeTests/DBoGenerated.d.ts +0 -320
- package/lib/typeTests/dboTypeCheck.ts +0 -81
- package/lib/utils.ts +0 -15
- package/tests/client/hooks.spec.ts +0 -205
- package/tests/client/index.ts +0 -139
- package/tests/client/package-lock.json +0 -637
- package/tests/client/package.json +0 -26
- package/tests/client/renderReactHook.ts +0 -177
- package/tests/client/tsconfig.json +0 -15
- package/tests/client/useProstgles.spec.ts +0 -120
- package/tests/clientFileTests.spec.ts +0 -102
- package/tests/clientOnlyQueries.spec.ts +0 -667
- package/tests/clientRestApi.spec.ts +0 -82
- package/tests/config_test/DBoGenerated.d.ts +0 -407
- package/tests/config_test/index.html +0 -109
- package/tests/config_test/index.js +0 -86
- package/tests/config_test/index.js.map +0 -1
- package/tests/config_test/index.ts +0 -91
- package/tests/config_test/init.sql +0 -48
- package/tests/config_test/package.json +0 -29
- package/tests/config_test/tsconfig.json +0 -23
- package/tests/config_testDBoGenerated.d.ts +0 -407
- package/tests/isomorphicQueries.spec.ts +0 -1493
- package/tests/server/DBoGenerated.d.ts +0 -537
- package/tests/server/index.html +0 -73
- package/tests/server/index.ts +0 -289
- package/tests/server/init.sql +0 -224
- package/tests/server/package-lock.json +0 -2164
- package/tests/server/package.json +0 -25
- package/tests/server/publishTypeCheck.ts +0 -136
- package/tests/server/server.ts +0 -35
- package/tests/server/testPublish.ts +0 -147
- package/tests/server/testTableConfig.ts +0 -156
- package/tests/server/tsconfig.json +0 -22
- package/tests/serverOnlyQueries.spec.ts +0 -32
- package/tests/test.sh +0 -20
package/lib/Auth/AuthHandler.ts
DELETED
|
@@ -1,436 +0,0 @@
|
|
|
1
|
-
import { AnyObject, AuthGuardLocation, AuthGuardLocationResponse, CHANNELS, AuthSocketSchema } from "prostgles-types";
|
|
2
|
-
import { LocalParams, PRGLIOSocket } from "../DboBuilder/DboBuilder";
|
|
3
|
-
import { DBOFullyTyped } from "../DBSchemaBuilder";
|
|
4
|
-
import { removeExpressRoute } from "../FileManager/FileManager";
|
|
5
|
-
import { DB, DBHandlerServer, Prostgles } from "../Prostgles";
|
|
6
|
-
import { Auth, AuthClientRequest, AuthResult, BasicSession, ExpressReq, ExpressRes, LoginClientInfo, LoginParams } from "./AuthTypes"
|
|
7
|
-
import { getSafeReturnURL } from "./getSafeReturnURL";
|
|
8
|
-
import { setupAuthRoutes } from "./setupAuthRoutes";
|
|
9
|
-
import { getProviders } from "./setAuthProviders";
|
|
10
|
-
|
|
11
|
-
export const HTTPCODES = {
|
|
12
|
-
AUTH_ERROR: 401,
|
|
13
|
-
NOT_FOUND: 404,
|
|
14
|
-
BAD_REQUEST: 400,
|
|
15
|
-
INTERNAL_SERVER_ERROR: 500,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export const getLoginClientInfo = (req: AuthClientRequest): AuthClientRequest & LoginClientInfo => {
|
|
19
|
-
if("httpReq" in req){
|
|
20
|
-
const ip_address = req.httpReq.ip;
|
|
21
|
-
if(!ip_address) throw new Error("ip_address missing from req.httpReq");
|
|
22
|
-
const user_agent = req.httpReq.headers["user-agent"];
|
|
23
|
-
return {
|
|
24
|
-
...req,
|
|
25
|
-
ip_address,
|
|
26
|
-
ip_address_remote: req.httpReq.connection.remoteAddress,
|
|
27
|
-
x_real_ip: req.httpReq.headers['x-real-ip'] as any,
|
|
28
|
-
user_agent,
|
|
29
|
-
};
|
|
30
|
-
} else {
|
|
31
|
-
return {
|
|
32
|
-
...req,
|
|
33
|
-
ip_address: req.socket.handshake.address,
|
|
34
|
-
ip_address_remote: req.socket.request.connection.remoteAddress,
|
|
35
|
-
x_real_ip: req.socket.handshake.headers?.["x-real-ip"],
|
|
36
|
-
user_agent: req.socket.handshake.headers?.['user-agent'],
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const AUTH_ROUTES_AND_PARAMS = {
|
|
42
|
-
login: "/login",
|
|
43
|
-
loginWithProvider: "/auth",
|
|
44
|
-
emailSignup: "/register",
|
|
45
|
-
returnUrlParamName: "returnURL",
|
|
46
|
-
sidKeyName: "session_id",
|
|
47
|
-
logoutGetPath: "/logout",
|
|
48
|
-
magicLinksRoute: "/magic-link",
|
|
49
|
-
magicLinksExpressRoute: "/magic-link/:id",
|
|
50
|
-
confirmEmail: "/confirm-email",
|
|
51
|
-
confirmEmailExpressRoute: "/confirm-email/:id",
|
|
52
|
-
catchAll: "*",
|
|
53
|
-
} as const;
|
|
54
|
-
|
|
55
|
-
export class AuthHandler {
|
|
56
|
-
protected prostgles: Prostgles;
|
|
57
|
-
protected opts?: Auth;
|
|
58
|
-
dbo: DBHandlerServer;
|
|
59
|
-
db: DB;
|
|
60
|
-
|
|
61
|
-
constructor(prostgles: Prostgles) {
|
|
62
|
-
this.prostgles = prostgles;
|
|
63
|
-
this.opts = prostgles.opts.auth as any;
|
|
64
|
-
if(!prostgles.dbo || !prostgles.db) throw "dbo or db missing";
|
|
65
|
-
this.dbo = prostgles.dbo;
|
|
66
|
-
this.db = prostgles.db;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
get sidKeyName() {
|
|
70
|
-
return this.opts?.sidKeyName ?? AUTH_ROUTES_AND_PARAMS.sidKeyName;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
validateSid = (sid: string | undefined) => {
|
|
74
|
-
if (!sid) return undefined;
|
|
75
|
-
if (typeof sid !== "string") throw "sid missing or not a string";
|
|
76
|
-
return sid;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
matchesRoute = (route: string | undefined, clientFullRoute: string) => {
|
|
80
|
-
return route && clientFullRoute && (
|
|
81
|
-
route === clientFullRoute ||
|
|
82
|
-
clientFullRoute.startsWith(route) && ["/", "?", "#"].includes(clientFullRoute[route.length] ?? "")
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
isUserRoute = (pathname: string) => {
|
|
87
|
-
const { login, logoutGetPath, magicLinksRoute, loginWithProvider } = AUTH_ROUTES_AND_PARAMS;
|
|
88
|
-
const pubRoutes = [
|
|
89
|
-
...this.opts?.expressConfig?.publicRoutes || [],
|
|
90
|
-
login, logoutGetPath, magicLinksRoute, loginWithProvider,
|
|
91
|
-
].filter(publicRoute => publicRoute);
|
|
92
|
-
|
|
93
|
-
return !pubRoutes.some(publicRoute => {
|
|
94
|
-
return this.matchesRoute(publicRoute, pathname);
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
setCookieAndGoToReturnURLIFSet = (cookie: { sid: string; expires: number; }, r: { req: ExpressReq; res: ExpressRes }) => {
|
|
99
|
-
const { sid, expires } = cookie;
|
|
100
|
-
const { res, req } = r;
|
|
101
|
-
if (sid) {
|
|
102
|
-
const maxAgeOneDay = 60 * 60 * 24; // 24 hours;
|
|
103
|
-
type CD = { maxAge: number } | { expires: Date }
|
|
104
|
-
let cookieDuration: CD = {
|
|
105
|
-
maxAge: maxAgeOneDay
|
|
106
|
-
}
|
|
107
|
-
if(expires && Number.isFinite(expires) && !isNaN(+ new Date(expires))){
|
|
108
|
-
// const maxAge = (+new Date(expires)) - Date.now();
|
|
109
|
-
cookieDuration = { expires: new Date(expires) };
|
|
110
|
-
const days = (+cookieDuration.expires - Date.now())/(24 * 60 * 60e3);
|
|
111
|
-
if(days >= 400){
|
|
112
|
-
console.warn(`Cookie expiration is higher than the Chrome 400 day limit: ${days}days`)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const cookieOpts = {
|
|
117
|
-
...cookieDuration,
|
|
118
|
-
httpOnly: true, // The cookie only accessible by the web server
|
|
119
|
-
//signed: true // Indicates if the cookie should be signed
|
|
120
|
-
secure: true,
|
|
121
|
-
sameSite: "strict" as const,
|
|
122
|
-
...(this.opts?.expressConfig?.cookieOptions || {})
|
|
123
|
-
};
|
|
124
|
-
const cookieData = sid;
|
|
125
|
-
res.cookie(this.sidKeyName, cookieData, cookieOpts);
|
|
126
|
-
const successURL = this.getReturnUrl(req) || "/";
|
|
127
|
-
res.redirect(successURL);
|
|
128
|
-
|
|
129
|
-
} else {
|
|
130
|
-
throw ("no user or session")
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
getUser = async (clientReq: { httpReq: ExpressReq; }): Promise<AuthResult> => {
|
|
135
|
-
if(!this.opts?.getUser) {
|
|
136
|
-
throw "this.opts.getUser missing";
|
|
137
|
-
}
|
|
138
|
-
const sid = clientReq.httpReq?.cookies?.[this.sidKeyName];
|
|
139
|
-
if (!sid) return undefined;
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
return this.throttledFunc(async () => {
|
|
143
|
-
return this.opts!.getUser(this.validateSid(sid), this.dbo as any, this.db, getLoginClientInfo(clientReq));
|
|
144
|
-
}, 50)
|
|
145
|
-
} catch (err) {
|
|
146
|
-
console.error(err);
|
|
147
|
-
}
|
|
148
|
-
return undefined;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
init = setupAuthRoutes.bind(this);
|
|
152
|
-
|
|
153
|
-
getReturnUrl = (req: ExpressReq) => {
|
|
154
|
-
const { returnUrlParamName } = AUTH_ROUTES_AND_PARAMS;
|
|
155
|
-
if (returnUrlParamName && req?.query?.[returnUrlParamName]) {
|
|
156
|
-
const returnURL = decodeURIComponent(req?.query?.[returnUrlParamName] as string);
|
|
157
|
-
|
|
158
|
-
return getSafeReturnURL(returnURL, returnUrlParamName);
|
|
159
|
-
}
|
|
160
|
-
return null;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
destroy = () => {
|
|
164
|
-
const app = this.opts?.expressConfig?.app;
|
|
165
|
-
const { login, logoutGetPath, magicLinksExpressRoute, catchAll, loginWithProvider, emailSignup, magicLinksRoute, confirmEmail } = AUTH_ROUTES_AND_PARAMS;
|
|
166
|
-
removeExpressRoute(app, [login, logoutGetPath, magicLinksExpressRoute, catchAll, loginWithProvider, emailSignup, magicLinksRoute, confirmEmail]);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
throttledFunc = <T>(func: () => Promise<T>, throttle = 500): Promise<T> => {
|
|
170
|
-
|
|
171
|
-
return new Promise(async (resolve, reject) => {
|
|
172
|
-
|
|
173
|
-
let result: any, error: any, finished = false;
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Throttle reject response times to prevent timing attacks
|
|
177
|
-
*/
|
|
178
|
-
const interval = setInterval(() => {
|
|
179
|
-
if (finished) {
|
|
180
|
-
clearInterval(interval);
|
|
181
|
-
if (error) {
|
|
182
|
-
reject(error);
|
|
183
|
-
} else {
|
|
184
|
-
resolve(result)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}, throttle);
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
result = await func();
|
|
192
|
-
resolve(result);
|
|
193
|
-
clearInterval(interval);
|
|
194
|
-
} catch (err) {
|
|
195
|
-
console.log(err)
|
|
196
|
-
error = err;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
finished = true;
|
|
200
|
-
})
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
loginThrottled = async (params: LoginParams, client: LoginClientInfo): Promise<BasicSession> => {
|
|
204
|
-
if (!this.opts?.login) throw "Auth login config missing";
|
|
205
|
-
const { responseThrottle = 500 } = this.opts;
|
|
206
|
-
|
|
207
|
-
return this.throttledFunc(async () => {
|
|
208
|
-
const result = await this.opts?.login?.(params, this.dbo as DBOFullyTyped, this.db, client);
|
|
209
|
-
const err = {
|
|
210
|
-
msg: "Bad login result type. \nExpecting: undefined | null | { sid: string; expires: number } but got: " + JSON.stringify(result)
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
if(!result) throw err;
|
|
214
|
-
if(result && (typeof result.sid !== "string" || typeof result.expires !== "number") || !result && ![undefined, null].includes(result)) {
|
|
215
|
-
throw err
|
|
216
|
-
}
|
|
217
|
-
if(result && result.expires < Date.now()){
|
|
218
|
-
throw { msg: "auth.login() is returning an expired session. Can only login with a session.expires greater than Date.now()" }
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return result;
|
|
222
|
-
}, responseThrottle);
|
|
223
|
-
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
loginThrottledAndSetCookie = async (req: ExpressReq, res: ExpressRes, loginParams: LoginParams) => {
|
|
227
|
-
const start = Date.now();
|
|
228
|
-
const { sid, expires } = await this.loginThrottled(loginParams, getLoginClientInfo({ httpReq: req })) || {};
|
|
229
|
-
await this.prostgles.opts.onLog?.({
|
|
230
|
-
type: "auth",
|
|
231
|
-
command: "login",
|
|
232
|
-
duration: Date.now() - start,
|
|
233
|
-
sid,
|
|
234
|
-
socketId: undefined,
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
if (sid) {
|
|
238
|
-
|
|
239
|
-
this.setCookieAndGoToReturnURLIFSet({ sid, expires }, { req, res });
|
|
240
|
-
|
|
241
|
-
} else {
|
|
242
|
-
throw ("Internal error: no user or session")
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Will return first sid value found in:
|
|
249
|
-
* Bearer header
|
|
250
|
-
* http cookie
|
|
251
|
-
* query params
|
|
252
|
-
* Based on sid names in auth
|
|
253
|
-
*/
|
|
254
|
-
getSID(localParams: LocalParams): string | undefined {
|
|
255
|
-
if (!this.opts) return undefined;
|
|
256
|
-
|
|
257
|
-
if (!localParams) return undefined;
|
|
258
|
-
const { sidKeyName } = this;
|
|
259
|
-
if (localParams.socket) {
|
|
260
|
-
const { handshake } = localParams.socket;
|
|
261
|
-
const querySid = handshake?.auth?.[sidKeyName] || handshake?.query?.[sidKeyName];
|
|
262
|
-
let rawSid = querySid;
|
|
263
|
-
if (!rawSid) {
|
|
264
|
-
const cookie_str = localParams.socket?.handshake?.headers?.cookie;
|
|
265
|
-
const cookie = parseCookieStr(cookie_str);
|
|
266
|
-
rawSid = cookie[sidKeyName];
|
|
267
|
-
}
|
|
268
|
-
return this.validateSid(rawSid);
|
|
269
|
-
|
|
270
|
-
} else if (localParams.httpReq) {
|
|
271
|
-
const [tokenType, base64Token] = localParams.httpReq.headers.authorization?.split(' ') ?? [];
|
|
272
|
-
let bearerSid: string | undefined;
|
|
273
|
-
if(tokenType && base64Token){
|
|
274
|
-
if(tokenType.trim() !== "Bearer"){
|
|
275
|
-
throw "Only Bearer Authorization header allowed";
|
|
276
|
-
}
|
|
277
|
-
bearerSid = Buffer.from(base64Token, 'base64').toString();
|
|
278
|
-
}
|
|
279
|
-
return this.validateSid(bearerSid ?? localParams.httpReq?.cookies?.[sidKeyName]);
|
|
280
|
-
|
|
281
|
-
} else throw "socket OR httpReq missing from localParams";
|
|
282
|
-
|
|
283
|
-
function parseCookieStr(cookie_str: string | undefined): any {
|
|
284
|
-
if (!cookie_str || typeof cookie_str !== "string") {
|
|
285
|
-
return {}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
return cookie_str.replace(/\s/g, '')
|
|
289
|
-
.split(";")
|
|
290
|
-
.reduce<AnyObject>((prev, current) => {
|
|
291
|
-
const [name, value] = current.split('=');
|
|
292
|
-
prev[name!] = value;
|
|
293
|
-
return prev;
|
|
294
|
-
}, {});
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Used for logging
|
|
300
|
-
*/
|
|
301
|
-
getSIDNoError = (localParams: LocalParams | undefined): string | undefined => {
|
|
302
|
-
if(!localParams) return undefined;
|
|
303
|
-
try {
|
|
304
|
-
return this.getSID(localParams);
|
|
305
|
-
} catch {
|
|
306
|
-
return undefined;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
async getClientInfo(localParams: Pick<LocalParams, "socket" | "httpReq">): Promise<AuthResult> {
|
|
311
|
-
if (!this.opts) return {};
|
|
312
|
-
|
|
313
|
-
const getSession = this.opts.cacheSession?.getSession;
|
|
314
|
-
const isSocket = "socket" in localParams;
|
|
315
|
-
if(isSocket){
|
|
316
|
-
if(getSession && localParams.socket?.__prglCache){
|
|
317
|
-
const { session, user, clientUser } = localParams.socket.__prglCache;
|
|
318
|
-
const isValid = this.isValidSocketSession(localParams.socket, session)
|
|
319
|
-
if(isValid){
|
|
320
|
-
|
|
321
|
-
return {
|
|
322
|
-
sid: session.sid,
|
|
323
|
-
user,
|
|
324
|
-
clientUser,
|
|
325
|
-
}
|
|
326
|
-
} else return {
|
|
327
|
-
sid: session.sid
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
const authStart = Date.now();
|
|
333
|
-
const res = await this.throttledFunc(async () => {
|
|
334
|
-
|
|
335
|
-
const { getUser } = this.opts ?? {};
|
|
336
|
-
|
|
337
|
-
if (getUser && localParams && (localParams.httpReq || localParams.socket)) {
|
|
338
|
-
const sid = this.getSID(localParams);
|
|
339
|
-
const clientReq = localParams.httpReq? { httpReq: localParams.httpReq } : { socket: localParams.socket! };
|
|
340
|
-
let user, clientUser;
|
|
341
|
-
if(sid){
|
|
342
|
-
const res = await getUser(sid, this.dbo as any, this.db, getLoginClientInfo(clientReq)) as any;
|
|
343
|
-
user = res?.user;
|
|
344
|
-
clientUser = res?.clientUser;
|
|
345
|
-
}
|
|
346
|
-
if(getSession && isSocket){
|
|
347
|
-
const session = await getSession(sid, this.dbo as any, this.db)
|
|
348
|
-
if(session?.expires && user && clientUser && localParams.socket){
|
|
349
|
-
localParams.socket.__prglCache = {
|
|
350
|
-
session,
|
|
351
|
-
user,
|
|
352
|
-
clientUser,
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
if(sid) {
|
|
357
|
-
return { sid, user, clientUser }
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return {};
|
|
362
|
-
}, 5);
|
|
363
|
-
|
|
364
|
-
await this.prostgles.opts.onLog?.({
|
|
365
|
-
type: "auth",
|
|
366
|
-
command: "getClientInfo",
|
|
367
|
-
duration: Date.now() - authStart,
|
|
368
|
-
sid: res.sid,
|
|
369
|
-
socketId: localParams.socket?.id,
|
|
370
|
-
});
|
|
371
|
-
return res;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
isValidSocketSession = (socket: PRGLIOSocket, session: BasicSession): boolean => {
|
|
375
|
-
const hasExpired = Boolean(session && session.expires <= Date.now())
|
|
376
|
-
if(this.opts?.expressConfig?.publicRoutes && !this.opts.expressConfig?.disableSocketAuthGuard){
|
|
377
|
-
const error = "Session has expired";
|
|
378
|
-
if(hasExpired){
|
|
379
|
-
if(session.onExpiration === "redirect")
|
|
380
|
-
socket.emit(CHANNELS.AUTHGUARD, {
|
|
381
|
-
shouldReload: session.onExpiration === "redirect",
|
|
382
|
-
error
|
|
383
|
-
});
|
|
384
|
-
throw error;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
return Boolean(session && !hasExpired);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
getClientAuth = async (clientReq: Pick<LocalParams, "socket" | "httpReq">): Promise<{ auth: AuthSocketSchema; userData: AuthResult; }> => {
|
|
391
|
-
|
|
392
|
-
let pathGuard = false;
|
|
393
|
-
if (this.opts?.expressConfig?.publicRoutes && !this.opts.expressConfig?.disableSocketAuthGuard) {
|
|
394
|
-
|
|
395
|
-
pathGuard = true;
|
|
396
|
-
|
|
397
|
-
if("socket" in clientReq && clientReq.socket){
|
|
398
|
-
const { socket } = clientReq;
|
|
399
|
-
socket.removeAllListeners(CHANNELS.AUTHGUARD)
|
|
400
|
-
socket.on(CHANNELS.AUTHGUARD, async (params: AuthGuardLocation, cb = (_err: any, _res?: AuthGuardLocationResponse) => { /** EMPTY */ }) => {
|
|
401
|
-
|
|
402
|
-
try {
|
|
403
|
-
|
|
404
|
-
const { pathname, origin } = typeof params === "string" ? JSON.parse(params) : (params || {});
|
|
405
|
-
if (pathname && typeof pathname !== "string") {
|
|
406
|
-
console.warn("Invalid pathname provided for AuthGuardLocation: ", pathname);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
/** These origins */
|
|
410
|
-
const IGNORED_API_ORIGINS = ["file://"]
|
|
411
|
-
if (!IGNORED_API_ORIGINS.includes(origin) && pathname && typeof pathname === "string" && this.isUserRoute(pathname) && !(await this.getClientInfo({ socket }))?.user) {
|
|
412
|
-
cb(null, { shouldReload: true });
|
|
413
|
-
} else {
|
|
414
|
-
cb(null, { shouldReload: false });
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
} catch (err) {
|
|
418
|
-
console.error("AUTHGUARD err: ", err);
|
|
419
|
-
cb(err)
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
const userData = await this.getClientInfo(clientReq);
|
|
427
|
-
const auth: AuthSocketSchema = {
|
|
428
|
-
providers: getProviders.bind(this)(),
|
|
429
|
-
register: this.opts?.expressConfig?.registrations?.email && { type: this.opts?.expressConfig?.registrations?.email.signupType, url: AUTH_ROUTES_AND_PARAMS.emailSignup },
|
|
430
|
-
user: userData?.clientUser,
|
|
431
|
-
loginType: this.opts?.expressConfig?.registrations?.email?.signupType,
|
|
432
|
-
pathGuard,
|
|
433
|
-
};
|
|
434
|
-
return { auth, userData };
|
|
435
|
-
}
|
|
436
|
-
}
|