rxdb-server 15.13.1 → 15.13.3

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.
@@ -54,7 +54,7 @@ var RxServerAdapterExpress = exports.RxServerAdapterExpress = {
54
54
  error: true,
55
55
  message
56
56
  };
57
- response.statusCode = code;
57
+ response.status(code);
58
58
  response.set("Connection", "close");
59
59
  await response.write(JSON.stringify(responseWrite));
60
60
  response.end();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_express","_interopRequireDefault","require","_cors","_core","HTTP_SERVER_BY_EXPRESS","exports","WeakMap","RxServerAdapterExpress","create","app","express","use","json","setCors","serverApp","path","cors","options","expressCors","origin","optionsSuccessStatus","getRequestBody","req","body","getRequestHeaders","headers","getRequestQuery","query","onRequestClose","fn","on","setResponseHeader","res","k","v","setHeader","responseWrite","data","write","endResponseJson","endResponse","end","closeConnection","response","code","message","error","statusCode","set","JSON","stringify","setSSEHeaders","writeHead","flushHeaders","get","handler","post","all","listen","port","hostname","httpServer","Promise","rej","ret","ensureNotFalsy","close","getFromMapOrThrow","err","setImmediate","emit","closeAllConnections"],"sources":["../../../../src/plugins/adapter-express/index.ts"],"sourcesContent":["import type { RxServerAdapter } from '../server/types';\nimport type { Express } from 'express';\nimport express, { Request, Response } from 'express';\nimport {\n Server as HttpServer\n} from 'http';\nimport expressCors from 'cors';\nimport { ensureNotFalsy, getFromMapOrThrow } from 'rxdb/plugins/core';\n\nexport const HTTP_SERVER_BY_EXPRESS = new WeakMap<Express, HttpServer>();\n\nexport const RxServerAdapterExpress: RxServerAdapter<Express, Request, Response> = {\n async create() {\n const app = express();\n app.use(express.json());\n return app;\n },\n setCors(serverApp, path, cors) {\n serverApp.options('/' + path + '/*', expressCors({\n origin: cors,\n // some legacy browsers (IE11, various SmartTVs) choke on 204\n optionsSuccessStatus: 200\n }));\n },\n\n getRequestBody(req: Request) {\n return req.body;\n },\n getRequestHeaders(req: Request) {\n return req.headers as any;\n },\n getRequestQuery(req: Request) {\n return req.query;\n },\n onRequestClose(req: Request, fn) {\n req.on('close', () => {\n fn();\n });\n },\n\n setResponseHeader(res: Response, k: string, v: string) {\n res.setHeader(k, v);\n },\n responseWrite(res: Response, data: string) {\n res.write(data);\n },\n endResponseJson(res: Response, data: any) {\n res.json(data);\n },\n endResponse(res: Response) {\n res.end();\n },\n async closeConnection(response: Response, code: number, message: string) {\n const responseWrite = {\n code,\n error: true,\n message\n };\n response.statusCode = code;\n response.set(\"Connection\", \"close\");\n await response.write(JSON.stringify(responseWrite));\n response.end();\n },\n setSSEHeaders(res: Response) {\n res.writeHead(200, {\n /**\n * Use exact these headers to make is less likely\n * for people to have problems.\n * @link https://www.youtube.com/watch?v=0PcMuYGJPzM\n */\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Connection': 'keep-alive',\n 'Cache-Control': 'no-cache',\n /**\n * Required for nginx\n * @link https://stackoverflow.com/q/61029079/3443137\n */\n 'X-Accel-Buffering': 'no'\n });\n res.flushHeaders();\n },\n\n get(serverApp, path, handler) {\n serverApp.get(path, handler);\n },\n post(serverApp, path, handler) {\n serverApp.post(path, handler);\n },\n all(serverApp, path, handler) {\n serverApp.all(path, handler);\n },\n async listen(serverApp, port, hostname) {\n const httpServer: HttpServer = await new Promise((res, rej) => {\n const ret = ensureNotFalsy(serverApp).listen(port, hostname, () => {\n res(ret);\n });\n });\n HTTP_SERVER_BY_EXPRESS.set(serverApp, httpServer);\n },\n async close(serverApp) {\n const httpServer = getFromMapOrThrow(HTTP_SERVER_BY_EXPRESS, serverApp);\n await new Promise<void>((res, rej) => {\n httpServer.close((err) => {\n if (err) { rej(err); } else { res(); }\n });\n /**\n * By default it will await all ongoing connections\n * before it closes. So we have to close it directly.\n * @link https://stackoverflow.com/a/36830072/3443137\n */\n setImmediate(() => httpServer.emit('close'));\n });\n },\n async closeAllConnections(serverApp) {\n const httpServer = HTTP_SERVER_BY_EXPRESS.get(serverApp);\n if (httpServer) {\n await httpServer.closeAllConnections();\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_express","_interopRequireDefault","require","_cors","_core","HTTP_SERVER_BY_EXPRESS","exports","WeakMap","RxServerAdapterExpress","create","app","express","use","json","setCors","serverApp","path","cors","options","expressCors","origin","optionsSuccessStatus","getRequestBody","req","body","getRequestHeaders","headers","getRequestQuery","query","onRequestClose","fn","on","setResponseHeader","res","k","v","setHeader","responseWrite","data","write","endResponseJson","endResponse","end","closeConnection","response","code","message","error","status","set","JSON","stringify","setSSEHeaders","writeHead","flushHeaders","get","handler","post","all","listen","port","hostname","httpServer","Promise","rej","ret","ensureNotFalsy","close","getFromMapOrThrow","err","setImmediate","emit","closeAllConnections"],"sources":["../../../../src/plugins/adapter-express/index.ts"],"sourcesContent":["import type { RxServerAdapter } from '../server/types';\nimport type { Express } from 'express';\nimport express, { Request, Response } from 'express';\nimport {\n Server as HttpServer\n} from 'http';\nimport expressCors from 'cors';\nimport { ensureNotFalsy, getFromMapOrThrow } from 'rxdb/plugins/core';\n\nexport const HTTP_SERVER_BY_EXPRESS = new WeakMap<Express, HttpServer>();\n\nexport const RxServerAdapterExpress: RxServerAdapter<Express, Request, Response> = {\n async create() {\n const app = express();\n app.use(express.json());\n return app;\n },\n setCors(serverApp, path, cors) {\n serverApp.options('/' + path + '/*', expressCors({\n origin: cors,\n // some legacy browsers (IE11, various SmartTVs) choke on 204\n optionsSuccessStatus: 200\n }));\n },\n\n getRequestBody(req: Request) {\n return req.body;\n },\n getRequestHeaders(req: Request) {\n return req.headers as any;\n },\n getRequestQuery(req: Request) {\n return req.query;\n },\n onRequestClose(req: Request, fn) {\n req.on('close', () => {\n fn();\n });\n },\n\n setResponseHeader(res: Response, k: string, v: string) {\n res.setHeader(k, v);\n },\n responseWrite(res: Response, data: string) {\n res.write(data);\n },\n endResponseJson(res: Response, data: any) {\n res.json(data);\n },\n endResponse(res: Response) {\n res.end();\n },\n async closeConnection(response: Response, code: number, message: string) {\n const responseWrite = {\n code,\n error: true,\n message\n };\n response.status(code);\n response.set(\"Connection\", \"close\");\n await response.write(JSON.stringify(responseWrite));\n response.end();\n },\n setSSEHeaders(res: Response) {\n res.writeHead(200, {\n /**\n * Use exact these headers to make is less likely\n * for people to have problems.\n * @link https://www.youtube.com/watch?v=0PcMuYGJPzM\n */\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Connection': 'keep-alive',\n 'Cache-Control': 'no-cache',\n /**\n * Required for nginx\n * @link https://stackoverflow.com/q/61029079/3443137\n */\n 'X-Accel-Buffering': 'no'\n });\n res.flushHeaders();\n },\n\n get(serverApp, path, handler) {\n serverApp.get(path, handler);\n },\n post(serverApp, path, handler) {\n serverApp.post(path, handler);\n },\n all(serverApp, path, handler) {\n serverApp.all(path, handler);\n },\n async listen(serverApp, port, hostname) {\n const httpServer: HttpServer = await new Promise((res, rej) => {\n const ret = ensureNotFalsy(serverApp).listen(port, hostname, () => {\n res(ret);\n });\n });\n HTTP_SERVER_BY_EXPRESS.set(serverApp, httpServer);\n },\n async close(serverApp) {\n const httpServer = getFromMapOrThrow(HTTP_SERVER_BY_EXPRESS, serverApp);\n await new Promise<void>((res, rej) => {\n httpServer.close((err) => {\n if (err) { rej(err); } else { res(); }\n });\n /**\n * By default it will await all ongoing connections\n * before it closes. So we have to close it directly.\n * @link https://stackoverflow.com/a/36830072/3443137\n */\n setImmediate(() => httpServer.emit('close'));\n });\n },\n async closeAllConnections(serverApp) {\n const httpServer = HTTP_SERVER_BY_EXPRESS.get(serverApp);\n if (httpServer) {\n await httpServer.closeAllConnections();\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
@@ -22,7 +22,6 @@ var RxServerReplicationEndpoint = exports.RxServerReplicationEndpoint = function
22
22
  this.urlPath = [this.name, collection.schema.version].join('/');
23
23
  var primaryPath = this.collection.schema.primaryPath;
24
24
  var replicationHandler = (0, _replicationWebsocket.getReplicationHandlerByCollection)(this.server.database, collection.name);
25
- var authDataByRequest = (0, _helper.addAuthMiddleware)(this.server, this.urlPath);
26
25
  this.queryModifier = (authData, query) => {
27
26
  if ((0, _helper.doesContainRegexQuerySelector)(query.selector)) {
28
27
  throw new Error('$regex queries not allowed because of DOS-attacks');
@@ -38,7 +37,10 @@ var RxServerReplicationEndpoint = exports.RxServerReplicationEndpoint = function
38
37
  var removeServerOnlyFields = (0, _helper.removeServerOnlyFieldsMonad)(this.serverOnlyFields);
39
38
  var mergeServerDocumentFields = (0, _helper.mergeServerDocumentFieldsMonad)(this.serverOnlyFields);
40
39
  this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pull', async (req, res) => {
41
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
40
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
41
+ if (!authData) {
42
+ return;
43
+ }
42
44
  var urlQuery = adapter.getRequestQuery(req);
43
45
  var id = urlQuery.id ? urlQuery.id : '';
44
46
  var lwt = urlQuery.lwt ? parseInt(urlQuery.lwt, 10) : 0;
@@ -65,7 +67,10 @@ var RxServerReplicationEndpoint = exports.RxServerReplicationEndpoint = function
65
67
  });
66
68
  });
67
69
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/push', async (req, res) => {
68
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
70
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
71
+ if (!authData) {
72
+ return;
73
+ }
69
74
  var docDataMatcherWrite = (0, _helper.getDocAllowedMatcher)(this, (0, _utils.ensureNotFalsy)(authData));
70
75
  var rows = adapter.getRequestBody(req);
71
76
  var ids = [];
@@ -115,8 +120,11 @@ var RxServerReplicationEndpoint = exports.RxServerReplicationEndpoint = function
115
120
  adapter.endResponseJson(res, conflicts);
116
121
  });
117
122
  this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pullStream', async (req, res) => {
123
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
124
+ if (!authData) {
125
+ return;
126
+ }
118
127
  adapter.setSSEHeaders(res);
119
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
120
128
  var docDataMatcherStream = (0, _helper.getDocAllowedMatcher)(this, (0, _utils.ensureNotFalsy)(authData));
121
129
  var subscription = replicationHandler.masterChangeStream$.pipe((0, _rxjs.mergeMap)(async changes => {
122
130
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint-replication.js","names":["_core","require","_replicationWebsocket","_rxjs","_utils","_helper","RxServerReplicationEndpoint","exports","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","type","adapter","setCors","join","blockPreviousVersionPaths","schema","version","urlPath","primaryPath","replicationHandler","getReplicationHandlerByCollection","database","authDataByRequest","addAuthMiddleware","authData","query","doesContainRegexQuerySelector","selector","Error","change","assumedMasterState","docContainsServerOnlyFields","newDocumentState","removeServerOnlyFields","removeServerOnlyFieldsMonad","mergeServerDocumentFields","mergeServerDocumentFieldsMonad","get","serverApp","req","res","getFromMapOrThrow","urlQuery","getRequestQuery","id","lwt","parseInt","limit","plainQuery","getChangedDocumentsSinceQuery","storageInstance","useQueryChanges","ensureNotFalsy","prepared","prepareQuery","jsonSchema","result","newCheckpoint","documents","length","lastOfArray","updatedAt","_meta","responseDocuments","map","d","setResponseHeader","endResponseJson","checkpoint","post","docDataMatcherWrite","getDocAllowedMatcher","rows","getRequestBody","ids","forEach","row","push","nonAllowedRow","find","closeConnection","hasInvalidChange","currentStateDocsArray","findDocumentsById","currentStateDocs","Map","set","useRows","isChangeValid","serverDoc","conflicts","masterWrite","setSSEHeaders","docDataMatcherStream","subscription","masterChangeStream$","pipe","mergeMap","changes","authHandler","getRequestHeaders","err","useDocs","filter","f","subscribe","filteredAndModified","responseWrite","JSON","stringify","onRequestClose","unsubscribe","endResponse"],"sources":["../../../../src/plugins/server/endpoint-replication.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxReplicationHandler,\n RxReplicationWriteToMasterRow,\n RxStorageDefaultCheckpoint,\n StringKeys,\n prepareQuery,\n getChangedDocumentsSinceQuery,\n RxDocumentData\n} from 'rxdb/plugins/core';\nimport { getReplicationHandlerByCollection } from 'rxdb/plugins/replication-websocket';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerAuthData,\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow,\n lastOfArray\n} from 'rxdb/plugins/utils';\n\nimport {\n addAuthMiddleware,\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getDocAllowedMatcher,\n mergeServerDocumentFieldsMonad,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\nexport type RxReplicationEndpointMessageType = {\n id: string;\n method: StringKeys<RxReplicationHandler<any, any>> | 'auth';\n params: any[];\n};\n\nexport class RxServerReplicationEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'replication';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string,\n ) {\n const adapter = this.server.adapter;\n\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n\n const primaryPath = this.collection.schema.primaryPath;\n const replicationHandler = getReplicationHandlerByCollection(this.server.database, collection.name);\n const authDataByRequest = addAuthMiddleware(\n this.server,\n this.urlPath\n );\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (change.assumedMasterState && docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad<RxDocType>(this.serverOnlyFields);\n const mergeServerDocumentFields = mergeServerDocumentFieldsMonad<RxDocType>(this.serverOnlyFields);\n\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pull', async (req: any, res: any) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n\n const urlQuery = adapter.getRequestQuery(req);\n const id = urlQuery.id ? urlQuery.id as string : '';\n const lwt = urlQuery.lwt ? parseInt(urlQuery.lwt as any, 10) : 0;\n const limit = urlQuery.limit ? parseInt(urlQuery.limit as any, 10) : 1;\n const plainQuery = getChangedDocumentsSinceQuery<RxDocType, RxStorageDefaultCheckpoint>(\n this.collection.storageInstance,\n limit,\n { id, lwt }\n );\n const useQueryChanges: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData as any),\n plainQuery\n );\n const prepared = prepareQuery<RxDocType>(\n this.collection.schema.jsonSchema,\n useQueryChanges\n );\n const result = await this.collection.storageInstance.query(prepared);\n\n const newCheckpoint = result.documents.length === 0 ? { id, lwt } : {\n id: ensureNotFalsy(lastOfArray(result.documents))[primaryPath],\n updatedAt: ensureNotFalsy(lastOfArray(result.documents))._meta.lwt\n };\n const responseDocuments = result.documents.map(d => removeServerOnlyFields(d));\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: responseDocuments,\n checkpoint: newCheckpoint\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/push', async (req: any, res: any) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData as any));\n const rows: RxReplicationWriteToMasterRow<RxDocType>[] = adapter.getRequestBody(req);\n const ids: string[] = [];\n rows.forEach(row => ids.push((row.newDocumentState as any)[primaryPath]));\n\n for (const row of rows) {\n // TODO remove this check\n if (row.assumedMasterState && (row.assumedMasterState as any)._meta) {\n throw new Error('body document contains meta!');\n }\n }\n\n // ensure all writes are allowed\n const nonAllowedRow = rows.find(row => {\n if (\n !docDataMatcherWrite(row.newDocumentState as any) ||\n (row.assumedMasterState && !docDataMatcherWrite(row.assumedMasterState as any))\n ) {\n return true;\n }\n });\n if (nonAllowedRow) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n let hasInvalidChange = false;\n\n const currentStateDocsArray = await this.collection.storageInstance.findDocumentsById(ids, true);\n const currentStateDocs = new Map<string, RxDocumentData<RxDocType>>();\n currentStateDocsArray.forEach(d => currentStateDocs.set((d as any)[primaryPath], d));\n\n const useRows: typeof rows = rows.map((row) => {\n const id = (row.newDocumentState as any)[primaryPath];\n const isChangeValid = this.changeValidator(ensureNotFalsy(authData as any), {\n newDocumentState: removeServerOnlyFields(row.newDocumentState),\n assumedMasterState: removeServerOnlyFields(row.assumedMasterState)\n });\n if (!isChangeValid) {\n hasInvalidChange = true;\n }\n\n const serverDoc = currentStateDocs.get(id);\n return {\n newDocumentState: mergeServerDocumentFields(row.newDocumentState, serverDoc),\n assumedMasterState: mergeServerDocumentFields(row.assumedMasterState as any, serverDoc)\n } as typeof row;\n });\n if (hasInvalidChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const conflicts = await replicationHandler.masterWrite(useRows);\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, conflicts);\n });\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pullStream', async (req, res) => {\n adapter.setSSEHeaders(res);\n\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherStream = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n const subscription = replicationHandler.masterChangeStream$.pipe(\n mergeMap(async (changes) => {\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting an event.\n */\n let authData: RxServerAuthData<AuthType>;\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n if (changes === 'RESYNC') {\n return changes;\n } else {\n const useDocs = changes.documents.filter(d => docDataMatcherStream(d as any));\n return {\n documents: useDocs,\n checkpoint: changes.checkpoint\n };\n }\n }),\n filter(f => f !== null && (f === 'RESYNC' || f.documents.length > 0))\n ).subscribe(filteredAndModified => {\n if (filteredAndModified === 'RESYNC') {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(filteredAndModified) + '\\n\\n');\n } else {\n const responseDocuments = ensureNotFalsy(filteredAndModified).documents.map(d => removeServerOnlyFields(d as any));\n adapter.responseWrite(res, 'data: ' + JSON.stringify({ documents: responseDocuments, checkpoint: ensureNotFalsy(filteredAndModified).checkpoint }) + '\\n\\n');\n }\n\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(res);\n });\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"endpoint-replication.js","names":["_core","require","_replicationWebsocket","_rxjs","_utils","_helper","RxServerReplicationEndpoint","exports","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","type","adapter","setCors","join","blockPreviousVersionPaths","schema","version","urlPath","primaryPath","replicationHandler","getReplicationHandlerByCollection","database","authData","query","doesContainRegexQuerySelector","selector","Error","change","assumedMasterState","docContainsServerOnlyFields","newDocumentState","removeServerOnlyFields","removeServerOnlyFieldsMonad","mergeServerDocumentFields","mergeServerDocumentFieldsMonad","get","serverApp","req","res","getAuthDataByRequest","urlQuery","getRequestQuery","id","lwt","parseInt","limit","plainQuery","getChangedDocumentsSinceQuery","storageInstance","useQueryChanges","ensureNotFalsy","prepared","prepareQuery","jsonSchema","result","newCheckpoint","documents","length","lastOfArray","updatedAt","_meta","responseDocuments","map","d","setResponseHeader","endResponseJson","checkpoint","post","docDataMatcherWrite","getDocAllowedMatcher","rows","getRequestBody","ids","forEach","row","push","nonAllowedRow","find","closeConnection","hasInvalidChange","currentStateDocsArray","findDocumentsById","currentStateDocs","Map","set","useRows","isChangeValid","serverDoc","conflicts","masterWrite","setSSEHeaders","docDataMatcherStream","subscription","masterChangeStream$","pipe","mergeMap","changes","authHandler","getRequestHeaders","err","useDocs","filter","f","subscribe","filteredAndModified","responseWrite","JSON","stringify","onRequestClose","unsubscribe","endResponse"],"sources":["../../../../src/plugins/server/endpoint-replication.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxReplicationHandler,\n RxReplicationWriteToMasterRow,\n RxStorageDefaultCheckpoint,\n StringKeys,\n prepareQuery,\n getChangedDocumentsSinceQuery,\n RxDocumentData\n} from 'rxdb/plugins/core';\nimport { getReplicationHandlerByCollection } from 'rxdb/plugins/replication-websocket';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerAuthData,\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow,\n lastOfArray\n} from 'rxdb/plugins/utils';\n\nimport {\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getAuthDataByRequest,\n getDocAllowedMatcher,\n mergeServerDocumentFieldsMonad,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\nexport type RxReplicationEndpointMessageType = {\n id: string;\n method: StringKeys<RxReplicationHandler<any, any>> | 'auth';\n params: any[];\n};\n\nexport class RxServerReplicationEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'replication';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string,\n ) {\n const adapter = this.server.adapter;\n\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n\n const primaryPath = this.collection.schema.primaryPath;\n const replicationHandler = getReplicationHandlerByCollection(this.server.database, collection.name);\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (change.assumedMasterState && docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad<RxDocType>(this.serverOnlyFields);\n const mergeServerDocumentFields = mergeServerDocumentFieldsMonad<RxDocType>(this.serverOnlyFields);\n\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pull', async (req: any, res: any) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const urlQuery = adapter.getRequestQuery(req);\n const id = urlQuery.id ? urlQuery.id as string : '';\n const lwt = urlQuery.lwt ? parseInt(urlQuery.lwt as any, 10) : 0;\n const limit = urlQuery.limit ? parseInt(urlQuery.limit as any, 10) : 1;\n const plainQuery = getChangedDocumentsSinceQuery<RxDocType, RxStorageDefaultCheckpoint>(\n this.collection.storageInstance,\n limit,\n { id, lwt }\n );\n const useQueryChanges: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n plainQuery\n );\n const prepared = prepareQuery<RxDocType>(\n this.collection.schema.jsonSchema,\n useQueryChanges\n );\n const result = await this.collection.storageInstance.query(prepared);\n\n const newCheckpoint = result.documents.length === 0 ? { id, lwt } : {\n id: ensureNotFalsy(lastOfArray(result.documents))[primaryPath],\n updatedAt: ensureNotFalsy(lastOfArray(result.documents))._meta.lwt\n };\n const responseDocuments = result.documents.map(d => removeServerOnlyFields(d));\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: responseDocuments,\n checkpoint: newCheckpoint\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/push', async (req: any, res: any) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData as any));\n const rows: RxReplicationWriteToMasterRow<RxDocType>[] = adapter.getRequestBody(req);\n const ids: string[] = [];\n rows.forEach(row => ids.push((row.newDocumentState as any)[primaryPath]));\n\n for (const row of rows) {\n // TODO remove this check\n if (row.assumedMasterState && (row.assumedMasterState as any)._meta) {\n throw new Error('body document contains meta!');\n }\n }\n\n // ensure all writes are allowed\n const nonAllowedRow = rows.find(row => {\n if (\n !docDataMatcherWrite(row.newDocumentState as any) ||\n (row.assumedMasterState && !docDataMatcherWrite(row.assumedMasterState as any))\n ) {\n return true;\n }\n });\n if (nonAllowedRow) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n let hasInvalidChange = false;\n\n const currentStateDocsArray = await this.collection.storageInstance.findDocumentsById(ids, true);\n const currentStateDocs = new Map<string, RxDocumentData<RxDocType>>();\n currentStateDocsArray.forEach(d => currentStateDocs.set((d as any)[primaryPath], d));\n\n const useRows: typeof rows = rows.map((row) => {\n const id = (row.newDocumentState as any)[primaryPath];\n const isChangeValid = this.changeValidator(ensureNotFalsy(authData), {\n newDocumentState: removeServerOnlyFields(row.newDocumentState),\n assumedMasterState: removeServerOnlyFields(row.assumedMasterState)\n });\n if (!isChangeValid) {\n hasInvalidChange = true;\n }\n\n const serverDoc = currentStateDocs.get(id);\n return {\n newDocumentState: mergeServerDocumentFields(row.newDocumentState, serverDoc),\n assumedMasterState: mergeServerDocumentFields(row.assumedMasterState as any, serverDoc)\n } as typeof row;\n });\n if (hasInvalidChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const conflicts = await replicationHandler.masterWrite(useRows);\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, conflicts);\n });\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pullStream', async (req, res) => {\n \n const authData = await getAuthDataByRequest<AuthType, any, any>(this.server, req, res);\n if (!authData) { return; }\n \n adapter.setSSEHeaders(res);\n const docDataMatcherStream = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n const subscription = replicationHandler.masterChangeStream$.pipe(\n mergeMap(async (changes) => {\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting an event.\n */\n let authData: RxServerAuthData<AuthType>;\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n if (changes === 'RESYNC') {\n return changes;\n } else {\n const useDocs = changes.documents.filter(d => docDataMatcherStream(d as any));\n return {\n documents: useDocs,\n checkpoint: changes.checkpoint\n };\n }\n }),\n filter(f => f !== null && (f === 'RESYNC' || f.documents.length > 0))\n ).subscribe(filteredAndModified => {\n if (filteredAndModified === 'RESYNC') {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(filteredAndModified) + '\\n\\n');\n } else {\n const responseDocuments = ensureNotFalsy(filteredAndModified).documents.map(d => removeServerOnlyFields(d as any));\n adapter.responseWrite(res, 'data: ' + JSON.stringify({ documents: responseDocuments, checkpoint: ensureNotFalsy(filteredAndModified).checkpoint }) + '\\n\\n');\n }\n\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(res);\n });\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -29,7 +29,6 @@ var RxServerRestEndpoint = exports.RxServerRestEndpoint = function RxServerRestE
29
29
  (0, _helper.blockPreviousVersionPaths)(this.server, [this.name].join('/'), collection.schema.version);
30
30
  this.urlPath = [this.name, collection.schema.version].join('/');
31
31
  var primaryPath = this.collection.schema.primaryPath;
32
- var authDataByRequest = (0, _helper.addAuthMiddleware)(this.server, this.urlPath);
33
32
  this.queryModifier = (authData, query) => {
34
33
  if ((0, _helper.doesContainRegexQuerySelector)(query.selector)) {
35
34
  throw new Error('$regex queries not allowed because of DOS-attacks');
@@ -45,7 +44,10 @@ var RxServerRestEndpoint = exports.RxServerRestEndpoint = function RxServerRestE
45
44
  var removeServerOnlyFields = (0, _helper.removeServerOnlyFieldsMonad)(this.serverOnlyFields);
46
45
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {
47
46
  (0, _utils.ensureNotFalsy)(adapter.getRequestBody(req), 'req body is empty');
48
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
47
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
48
+ if (!authData) {
49
+ return;
50
+ }
49
51
  var useQuery;
50
52
  try {
51
53
  useQuery = this.queryModifier((0, _utils.ensureNotFalsy)(authData), (0, _core.normalizeMangoQuery)(this.collection.schema.jsonSchema, adapter.getRequestBody(req)));
@@ -67,7 +69,10 @@ var RxServerRestEndpoint = exports.RxServerRestEndpoint = function RxServerRestE
67
69
  * like ?query=e3NlbGVjdG9yOiB7fX0=
68
70
  */
69
71
  this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {
70
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
72
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
73
+ if (!authData) {
74
+ return;
75
+ }
71
76
  adapter.setSSEHeaders(res);
72
77
  var useQuery = this.queryModifier((0, _utils.ensureNotFalsy)(authData), (0, _core.normalizeMangoQuery)(this.collection.schema.jsonSchema, JSON.parse(atob(adapter.getRequestQuery(req).query))));
73
78
  var rxQuery = this.collection.find(useQuery);
@@ -99,7 +104,10 @@ var RxServerRestEndpoint = exports.RxServerRestEndpoint = function RxServerRestE
99
104
  });
100
105
  });
101
106
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {
102
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
107
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
108
+ if (!authData) {
109
+ return;
110
+ }
103
111
  var ids = adapter.getRequestBody(req);
104
112
  var rxQuery = this.collection.findByIds(ids);
105
113
  var resultMap = await rxQuery.exec();
@@ -114,7 +122,10 @@ var RxServerRestEndpoint = exports.RxServerRestEndpoint = function RxServerRestE
114
122
  });
115
123
  });
116
124
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {
117
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
125
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
126
+ if (!authData) {
127
+ return;
128
+ }
118
129
  var docDataMatcherWrite = (0, _helper.getDocAllowedMatcher)(this, (0, _utils.ensureNotFalsy)(authData));
119
130
  var docsData = adapter.getRequestBody(req);
120
131
  for (var docData of docsData) {
@@ -168,7 +179,10 @@ var RxServerRestEndpoint = exports.RxServerRestEndpoint = function RxServerRestE
168
179
  adapter.endResponseJson(res, {});
169
180
  });
170
181
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {
171
- var authData = (0, _utils.getFromMapOrThrow)(authDataByRequest, req);
182
+ var authData = await (0, _helper.getAuthDataByRequest)(this.server, req, res);
183
+ if (!authData) {
184
+ return;
185
+ }
172
186
  var docDataMatcherWrite = (0, _helper.getDocAllowedMatcher)(this, (0, _utils.ensureNotFalsy)(authData));
173
187
  var ids = adapter.getRequestBody(req);
174
188
  while (ids.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint-rest.js","names":["_core","require","_rxjs","_utils","_helper","REST_PATHS","exports","RxServerRestEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","_this","type","adapter","setCors","join","blockPreviousVersionPaths","schema","version","urlPath","primaryPath","authDataByRequest","addAuthMiddleware","authData","query","doesContainRegexQuerySelector","selector","Error","change","assumedMasterState","docContainsServerOnlyFields","newDocumentState","removeServerOnlyFields","removeServerOnlyFieldsMonad","post","serverApp","req","res","ensureNotFalsy","getRequestBody","getFromMapOrThrow","useQuery","normalizeMangoQuery","jsonSchema","err","closeConnection","rxQuery","find","result","exec","setResponseHeader","endResponseJson","documents","map","d","toJSON","get","setSSEHeaders","JSON","parse","atob","getRequestQuery","subscription","$","pipe","mergeMap","resultData","doc","authHandler","getRequestHeaders","filter","f","subscribe","responseWrite","stringify","onRequestClose","unsubscribe","endResponse","ids","findByIds","resultMap","resultValues","Array","from","values","docMatcher","getDocAllowedMatcher","useDocs","docDataMatcherWrite","docsData","docData","allowed","onWriteError","rxdb","code","push","length","promises","docs","useDocsData","slice","_loop","_docData","id","insert","catch","isAllowed","v","patch","_ret","Promise","all","useIds","docsMap","_loop2","isAllowedDoc","isAllowedChange","remove","_ret2"],"sources":["../../../../src/plugins/server/endpoint-rest.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxError,\n normalizeMangoQuery\n} from 'rxdb/plugins/core';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow\n} from 'rxdb/plugins/utils';\n\nimport {\n addAuthMiddleware,\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getDocAllowedMatcher,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\n\nexport const REST_PATHS = [\n 'query',\n 'query/observe',\n 'get',\n 'set',\n 'delete',\n\n // TODO\n /*\n 'attachments/add',\n 'attachments/delete',\n 'events'\n */\n] as const;\n\n\nexport class RxServerRestEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'rest';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string\n ) {\n const adapter = server.adapter;\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n const primaryPath = this.collection.schema.primaryPath;\n const authDataByRequest = addAuthMiddleware(\n this.server,\n this.urlPath\n );\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (\n change.assumedMasterState &&\n docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)\n ) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {\n ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');\n const authData = getFromMapOrThrow(authDataByRequest, req);\n let useQuery: FilledMangoQuery<RxDocType>\n try {\n useQuery = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n adapter.getRequestBody(req)\n )\n );\n } catch (err) {\n adapter.closeConnection(res, 400, 'Bad Request');\n return;\n }\n const rxQuery = this.collection.find(useQuery as any);\n const result = await rxQuery.exec();\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: result.map(d => removeServerOnlyFields(d.toJSON()))\n });\n });\n\n /**\n * It is not possible to send data with server send events,\n * so we send the query as query parameter in base64\n * like ?query=e3NlbGVjdG9yOiB7fX0=\n */\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {\n let authData = getFromMapOrThrow(authDataByRequest, req);\n adapter.setSSEHeaders(res);\n\n const useQuery: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n JSON.parse(atob(adapter.getRequestQuery(req).query as string))\n )\n );\n\n const rxQuery = this.collection.find(useQuery as any);\n const subscription = rxQuery.$.pipe(\n mergeMap(async (result) => {\n const resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));\n\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting the new results.\n */\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n return resultData;\n }),\n filter(f => f !== null)\n ).subscribe(resultData => {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(resultData) + '\\n\\n');\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(req);\n });\n });\n\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const ids: string[] = adapter.getRequestBody(req);\n\n const rxQuery = this.collection.findByIds(ids);\n const resultMap = await rxQuery.exec();\n const resultValues = Array.from(resultMap.values());\n const docMatcher = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n let useDocs = resultValues.map(d => d.toJSON());\n useDocs = useDocs.filter(d => docMatcher(d as any));\n useDocs = useDocs.map(d => removeServerOnlyFields(d))\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: useDocs\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let docsData: RxDocType[] = adapter.getRequestBody(req);\n\n for (const docData of docsData) {\n const allowed = docDataMatcherWrite(docData as any);\n if (!allowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n }\n\n function onWriteError(err: RxError, docData: RxDocType) {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n docsData.push(docData);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }\n\n while (docsData.length > 0) {\n const promises: Promise<any>[] = [];\n const docs = await collection.findByIds(docsData.map(d => (d as any)[primaryPath])).exec();\n let useDocsData = docsData.slice();\n docsData = [];\n for (const docData of useDocsData) {\n const id = (docData as any)[primaryPath];\n const doc = docs.get(id);\n if (!doc) {\n promises.push(this.collection.insert(docData).catch(err => onWriteError(err, docData)));\n } else {\n const isAllowed = this.changeValidator(authData, {\n newDocumentState: removeServerOnlyFields(docData as any),\n assumedMasterState: removeServerOnlyFields(doc.toJSON(true))\n });\n if (!isAllowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n promises.push(doc.patch(docData).catch(err => onWriteError(err, docData)));\n }\n }\n await Promise.all(promises);\n }\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json')\n adapter.endResponseJson(res, {});\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let ids: string[] = adapter.getRequestBody(req);\n while (ids.length > 0) {\n const useIds = ids.slice(0);\n ids = [];\n const promises: Promise<any>[] = [];\n const docsMap = await this.collection.findByIds(useIds).exec();\n for (const id of useIds) {\n const doc = docsMap.get(id);\n if (doc) {\n const isAllowedDoc = docDataMatcherWrite(doc.toJSON(true) as any);\n if (!isAllowedDoc) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const isAllowedChange = this.changeValidator(authData, {\n newDocumentState: doc.toJSON(true) as any,\n assumedMasterState: doc.toJSON(true) as any\n });\n if (!isAllowedChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n promises.push(doc.remove().catch((err: RxError) => {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n ids.push(id);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }));\n }\n }\n await Promise.all(promises);\n }\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {});\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"endpoint-rest.js","names":["_core","require","_rxjs","_utils","_helper","REST_PATHS","exports","RxServerRestEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","_this","type","adapter","setCors","join","blockPreviousVersionPaths","schema","version","urlPath","primaryPath","authData","query","doesContainRegexQuerySelector","selector","Error","change","assumedMasterState","docContainsServerOnlyFields","newDocumentState","removeServerOnlyFields","removeServerOnlyFieldsMonad","post","serverApp","req","res","ensureNotFalsy","getRequestBody","getAuthDataByRequest","useQuery","normalizeMangoQuery","jsonSchema","err","closeConnection","rxQuery","find","result","exec","setResponseHeader","endResponseJson","documents","map","d","toJSON","get","setSSEHeaders","JSON","parse","atob","getRequestQuery","subscription","$","pipe","mergeMap","resultData","doc","authHandler","getRequestHeaders","filter","f","subscribe","responseWrite","stringify","onRequestClose","unsubscribe","endResponse","ids","findByIds","resultMap","resultValues","Array","from","values","docMatcher","getDocAllowedMatcher","useDocs","docDataMatcherWrite","docsData","docData","allowed","onWriteError","rxdb","code","push","length","promises","docs","useDocsData","slice","_loop","_docData","id","insert","catch","isAllowed","v","patch","_ret","Promise","all","useIds","docsMap","_loop2","isAllowedDoc","isAllowedChange","remove","_ret2"],"sources":["../../../../src/plugins/server/endpoint-rest.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxError,\n normalizeMangoQuery\n} from 'rxdb/plugins/core';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow\n} from 'rxdb/plugins/utils';\n\nimport {\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getAuthDataByRequest,\n getDocAllowedMatcher,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\n\nexport const REST_PATHS = [\n 'query',\n 'query/observe',\n 'get',\n 'set',\n 'delete',\n\n // TODO\n /*\n 'attachments/add',\n 'attachments/delete',\n 'events'\n */\n] as const;\n\n\nexport class RxServerRestEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'rest';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string\n ) {\n const adapter = server.adapter;\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n const primaryPath = this.collection.schema.primaryPath;\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (\n change.assumedMasterState &&\n docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)\n ) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {\n ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n let useQuery: FilledMangoQuery<RxDocType>\n try {\n useQuery = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n adapter.getRequestBody(req)\n )\n );\n } catch (err) {\n adapter.closeConnection(res, 400, 'Bad Request');\n return;\n }\n const rxQuery = this.collection.find(useQuery as any);\n const result = await rxQuery.exec();\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: result.map(d => removeServerOnlyFields(d.toJSON()))\n });\n });\n\n /**\n * It is not possible to send data with server send events,\n * so we send the query as query parameter in base64\n * like ?query=e3NlbGVjdG9yOiB7fX0=\n */\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {\n let authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n adapter.setSSEHeaders(res);\n\n const useQuery: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n JSON.parse(atob(adapter.getRequestQuery(req).query as string))\n )\n );\n\n const rxQuery = this.collection.find(useQuery as any);\n const subscription = rxQuery.$.pipe(\n mergeMap(async (result) => {\n const resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));\n\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting the new results.\n */\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req)) as any;\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n return resultData;\n }),\n filter(f => f !== null)\n ).subscribe(resultData => {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(resultData) + '\\n\\n');\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(req);\n });\n });\n\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const ids: string[] = adapter.getRequestBody(req);\n\n const rxQuery = this.collection.findByIds(ids);\n const resultMap = await rxQuery.exec();\n const resultValues = Array.from(resultMap.values());\n const docMatcher = getDocAllowedMatcher(this, ensureNotFalsy(authData) as any);\n let useDocs = resultValues.map(d => d.toJSON());\n useDocs = useDocs.filter(d => docMatcher(d as any));\n useDocs = useDocs.map(d => removeServerOnlyFields(d))\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: useDocs\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData) as any);\n\n let docsData: RxDocType[] = adapter.getRequestBody(req);\n\n for (const docData of docsData) {\n const allowed = docDataMatcherWrite(docData as any);\n if (!allowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n }\n\n function onWriteError(err: RxError, docData: RxDocType) {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n docsData.push(docData);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }\n\n while (docsData.length > 0) {\n const promises: Promise<any>[] = [];\n const docs = await collection.findByIds(docsData.map(d => (d as any)[primaryPath])).exec();\n let useDocsData = docsData.slice();\n docsData = [];\n for (const docData of useDocsData) {\n const id = (docData as any)[primaryPath];\n const doc = docs.get(id);\n if (!doc) {\n promises.push(this.collection.insert(docData).catch(err => onWriteError(err, docData)));\n } else {\n const isAllowed = this.changeValidator(authData, {\n newDocumentState: removeServerOnlyFields(docData as any),\n assumedMasterState: removeServerOnlyFields(doc.toJSON(true))\n });\n if (!isAllowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n promises.push(doc.patch(docData).catch(err => onWriteError(err, docData)));\n }\n }\n await Promise.all(promises);\n }\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json')\n adapter.endResponseJson(res, {});\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let ids: string[] = adapter.getRequestBody(req);\n while (ids.length > 0) {\n const useIds = ids.slice(0);\n ids = [];\n const promises: Promise<any>[] = [];\n const docsMap = await this.collection.findByIds(useIds).exec();\n for (const id of useIds) {\n const doc = docsMap.get(id);\n if (doc) {\n const isAllowedDoc = docDataMatcherWrite(doc.toJSON(true) as any);\n if (!isAllowedDoc) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const isAllowedChange = this.changeValidator(authData, {\n newDocumentState: doc.toJSON(true) as any,\n assumedMasterState: doc.toJSON(true) as any\n });\n if (!isAllowedChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n promises.push(doc.remove().catch((err: RxError) => {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n ids.push(id);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }));\n }\n }\n await Promise.all(promises);\n }\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {});\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -3,10 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.addAuthMiddleware = addAuthMiddleware;
7
6
  exports.blockPreviousVersionPaths = blockPreviousVersionPaths;
8
7
  exports.docContainsServerOnlyFields = docContainsServerOnlyFields;
9
8
  exports.doesContainRegexQuerySelector = doesContainRegexQuerySelector;
9
+ exports.getAuthDataByRequest = getAuthDataByRequest;
10
10
  exports.getDocAllowedMatcher = getDocAllowedMatcher;
11
11
  exports.mergeServerDocumentFieldsMonad = mergeServerDocumentFieldsMonad;
12
12
  exports.removeServerOnlyFieldsMonad = removeServerOnlyFieldsMonad;
@@ -39,21 +39,20 @@ function blockPreviousVersionPaths(server, path, currentVersion) {
39
39
  _loop();
40
40
  }
41
41
  }
42
- function addAuthMiddleware(server, path) {
43
- var authDataByRequest = new WeakMap();
44
- async function auth(req, res, next) {
42
+ var AUTH_PER_REQUEST = new WeakMap();
43
+ async function getAuthDataByRequest(server, request, response) {
44
+ return (0, _core.getFromMapOrCreate)(AUTH_PER_REQUEST, request, async () => {
45
45
  try {
46
- var authData = await server.authHandler(req.headers);
47
- authDataByRequest.set(req, authData);
48
- next();
46
+ var headers = server.adapter.getRequestHeaders(request);
47
+ var authData = await server.authHandler(headers);
48
+ return authData;
49
49
  } catch (err) {
50
- server.adapter.closeConnection(res, 401, 'Unauthorized');
51
- return;
50
+ server.adapter.closeConnection(response, 401, 'Unauthorized');
51
+ return false;
52
52
  }
53
- }
54
- server.adapter.all(server.serverApp, '/' + path + '/*', auth);
55
- return authDataByRequest;
53
+ });
56
54
  }
55
+ ;
57
56
  var defaultMatchingQuery = {
58
57
  selector: {},
59
58
  skip: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","names":["_core","require","setCors","server","path","cors","useCors","adapter","serverApp","blockPreviousVersionPaths","currentVersion","v","_loop","version","all","req","res","closeConnection","addAuthMiddleware","authDataByRequest","WeakMap","auth","next","authData","authHandler","headers","set","err","defaultMatchingQuery","selector","skip","sort","getDocAllowedMatcher","endpoint","useQuery","queryModifier","normalizeMangoQuery","collection","schema","jsonSchema","docDataMatcher","getQueryMatcher","docContainsServerOnlyFields","serverOnlyFields","doc","has","find","field","removeServerOnlyFieldsMonad","serverOnlyFieldsStencil","_meta","undefined","_rev","_attachments","forEach","docData","Object","assign","mergeServerDocumentFieldsMonad","useFields","slice","uniqueArray","clientDoc","serverDoc","ret","flatClone","doesContainRegexQuerySelector","Array","isArray","found","item","entries","key","value"],"sources":["../../../../src/plugins/server/helper.ts"],"sourcesContent":["import { RxServer } from './rx-server';\nimport type {\n Request,\n Response,\n NextFunction\n} from 'express';\nimport type { RxServerAdapter, RxServerAuthData, RxServerEndpoint } from './types';\nimport {\n FilledMangoQuery,\n MangoQuerySelector,\n RxDocumentData,\n flatClone,\n getQueryMatcher,\n normalizeMangoQuery,\n uniqueArray\n} from 'rxdb/plugins/core';\n\nexport function setCors(\n server: RxServer<any, any>,\n path: string,\n cors?: string\n) {\n let useCors = cors;\n if (!useCors) {\n useCors = server.cors;\n }\n if (useCors) {\n server.adapter.setCors(server.serverApp, path, useCors);\n }\n}\n\n/**\n * \"block\" the previous version urls and send a 426 on them so that\n * the clients know they must update.\n */\nexport function blockPreviousVersionPaths(\n server: RxServer<any, any>,\n path: string,\n currentVersion: number\n\n) {\n let v = 0;\n while (v < currentVersion) {\n const version = v;\n server.adapter.all(server.serverApp, '/' + path + '/' + version + '/*', (req, res) => {\n server.adapter.closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');\n });\n v++;\n }\n}\n\n\nexport function addAuthMiddleware<AuthType>(\n server: RxServer<any, AuthType>,\n path: string,\n): WeakMap<Request, RxServerAuthData<AuthType>> {\n const authDataByRequest = new WeakMap<Request, RxServerAuthData<AuthType>>();\n async function auth(req: any, res: any, next: NextFunction) {\n try {\n const authData = await server.authHandler(req.headers);\n authDataByRequest.set(req, authData);\n next();\n } catch (err) {\n server.adapter.closeConnection(res, 401, 'Unauthorized');\n return;\n }\n }\n server.adapter.all(server.serverApp, '/' + path + '/*', auth);\n return authDataByRequest;\n}\n\nconst defaultMatchingQuery: FilledMangoQuery<any> = {\n selector: {},\n skip: 0,\n sort: []\n} as const;\n\nexport function getDocAllowedMatcher<RxDocType, AuthType>(\n endpoint: RxServerEndpoint<AuthType, RxDocType>,\n authData: RxServerAuthData<AuthType>\n) {\n const useQuery: FilledMangoQuery<RxDocType> = endpoint.queryModifier ? endpoint.queryModifier(\n authData,\n normalizeMangoQuery(\n endpoint.collection.schema.jsonSchema,\n {}\n )\n ) : defaultMatchingQuery;\n const docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);\n return docDataMatcher;\n}\n\n\nexport function docContainsServerOnlyFields(\n serverOnlyFields: string[],\n doc: any\n) {\n const has = serverOnlyFields.find(field => {\n return typeof doc[field] !== 'undefined'\n });\n return has;\n}\n\nexport function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n const serverOnlyFieldsStencil: any = {\n _meta: undefined,\n _rev: undefined,\n _attachments: undefined\n };\n serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);\n return (\n docData?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!docData) {\n return docData;\n }\n return Object.assign({}, docData, serverOnlyFieldsStencil);\n }\n}\n\nexport function mergeServerDocumentFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n let useFields = serverOnlyFields.slice(0);\n // useFields.push('_rev');\n // useFields.push('_meta');\n // useFields.push('_attachments');\n useFields = uniqueArray(useFields);\n\n return (\n clientDoc: RxDocType | RxDocumentData<RxDocType>,\n serverDoc?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!serverDoc) {\n return clientDoc;\n }\n const ret = flatClone(clientDoc);\n useFields.forEach(field => {\n (ret as any)[field] = (serverDoc as any)[field];\n });\n return ret;\n }\n}\n\n\n/**\n * $regex queries are dangerous because they can dos-attack the server.\n * \n * @param selector \n */\nexport function doesContainRegexQuerySelector(selector: MangoQuerySelector<any> | any): boolean {\n if (!selector) {\n return false;\n }\n if (Array.isArray(selector)) {\n const found = !!selector.find(item => doesContainRegexQuerySelector(item));\n return found;\n }\n\n if (typeof selector !== 'object') {\n return false;\n }\n\n const entries = Object.entries(selector);\n for (const [key, value] of entries) {\n if (key === '$regex') {\n return true;\n } else {\n const has = doesContainRegexQuerySelector(value);\n if (has) {\n return true;\n }\n }\n }\n\n return false;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"helper.js","names":["_core","require","setCors","server","path","cors","useCors","adapter","serverApp","blockPreviousVersionPaths","currentVersion","v","_loop","version","all","req","res","closeConnection","AUTH_PER_REQUEST","WeakMap","getAuthDataByRequest","request","response","getFromMapOrCreate","headers","getRequestHeaders","authData","authHandler","err","defaultMatchingQuery","selector","skip","sort","getDocAllowedMatcher","endpoint","useQuery","queryModifier","normalizeMangoQuery","collection","schema","jsonSchema","docDataMatcher","getQueryMatcher","docContainsServerOnlyFields","serverOnlyFields","doc","has","find","field","removeServerOnlyFieldsMonad","serverOnlyFieldsStencil","_meta","undefined","_rev","_attachments","forEach","docData","Object","assign","mergeServerDocumentFieldsMonad","useFields","slice","uniqueArray","clientDoc","serverDoc","ret","flatClone","doesContainRegexQuerySelector","Array","isArray","found","item","entries","key","value"],"sources":["../../../../src/plugins/server/helper.ts"],"sourcesContent":["import { RxServer } from './rx-server';\nimport type {\n Request,\n Response,\n NextFunction\n} from 'express';\nimport type { RxServerAdapter, RxServerAuthData, RxServerEndpoint } from './types';\nimport {\n FilledMangoQuery,\n MangoQuerySelector,\n RxDocumentData,\n flatClone,\n getFromMapOrCreate,\n getQueryMatcher,\n normalizeMangoQuery,\n uniqueArray\n} from 'rxdb/plugins/core';\n\nexport function setCors(\n server: RxServer<any, any>,\n path: string,\n cors?: string\n) {\n let useCors = cors;\n if (!useCors) {\n useCors = server.cors;\n }\n if (useCors) {\n server.adapter.setCors(server.serverApp, path, useCors);\n }\n}\n\n/**\n * \"block\" the previous version urls and send a 426 on them so that\n * the clients know they must update.\n */\nexport function blockPreviousVersionPaths(\n server: RxServer<any, any>,\n path: string,\n currentVersion: number\n\n) {\n let v = 0;\n while (v < currentVersion) {\n const version = v;\n server.adapter.all(server.serverApp, '/' + path + '/' + version + '/*', (req, res) => {\n server.adapter.closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');\n });\n v++;\n }\n}\n\n\n\nconst AUTH_PER_REQUEST = new WeakMap<any, Promise<any>>();\n\nexport async function getAuthDataByRequest<AuthType, RequestType, ResponseType>(\n server: RxServer<any, AuthType>,\n request: RequestType,\n response: ResponseType\n): Promise<RxServerAuthData<AuthType> | false> {\n return getFromMapOrCreate(\n AUTH_PER_REQUEST,\n request,\n async () => {\n try {\n const headers = server.adapter.getRequestHeaders(request);\n const authData = await server.authHandler(headers);\n return authData;\n } catch (err) {\n server.adapter.closeConnection(response, 401, 'Unauthorized');\n return false;\n }\n }\n );\n};\n\nconst defaultMatchingQuery: FilledMangoQuery<any> = {\n selector: {},\n skip: 0,\n sort: []\n} as const;\n\nexport function getDocAllowedMatcher<RxDocType, AuthType>(\n endpoint: RxServerEndpoint<AuthType, RxDocType>,\n authData: RxServerAuthData<AuthType>\n) {\n const useQuery: FilledMangoQuery<RxDocType> = endpoint.queryModifier ? endpoint.queryModifier(\n authData,\n normalizeMangoQuery(\n endpoint.collection.schema.jsonSchema,\n {}\n )\n ) : defaultMatchingQuery;\n const docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);\n return docDataMatcher;\n}\n\n\nexport function docContainsServerOnlyFields(\n serverOnlyFields: string[],\n doc: any\n) {\n const has = serverOnlyFields.find(field => {\n return typeof doc[field] !== 'undefined'\n });\n return has;\n}\n\nexport function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n const serverOnlyFieldsStencil: any = {\n _meta: undefined,\n _rev: undefined,\n _attachments: undefined\n };\n serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);\n return (\n docData?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!docData) {\n return docData;\n }\n return Object.assign({}, docData, serverOnlyFieldsStencil);\n }\n}\n\nexport function mergeServerDocumentFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n let useFields = serverOnlyFields.slice(0);\n // useFields.push('_rev');\n // useFields.push('_meta');\n // useFields.push('_attachments');\n useFields = uniqueArray(useFields);\n\n return (\n clientDoc: RxDocType | RxDocumentData<RxDocType>,\n serverDoc?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!serverDoc) {\n return clientDoc;\n }\n const ret = flatClone(clientDoc);\n useFields.forEach(field => {\n (ret as any)[field] = (serverDoc as any)[field];\n });\n return ret;\n }\n}\n\n\n/**\n * $regex queries are dangerous because they can dos-attack the server.\n * \n * @param selector \n */\nexport function doesContainRegexQuerySelector(selector: MangoQuerySelector<any> | any): boolean {\n if (!selector) {\n return false;\n }\n if (Array.isArray(selector)) {\n const found = !!selector.find(item => doesContainRegexQuerySelector(item));\n return found;\n }\n\n if (typeof selector !== 'object') {\n return false;\n }\n\n const entries = Object.entries(selector);\n for (const [key, value] of entries) {\n if (key === '$regex') {\n return true;\n } else {\n const has = doesContainRegexQuerySelector(value);\n if (has) {\n return true;\n }\n }\n }\n\n return false;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -47,7 +47,7 @@ export var RxServerAdapterExpress = {
47
47
  error: true,
48
48
  message
49
49
  };
50
- response.statusCode = code;
50
+ response.status(code);
51
51
  response.set("Connection", "close");
52
52
  await response.write(JSON.stringify(responseWrite));
53
53
  response.end();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["express","expressCors","ensureNotFalsy","getFromMapOrThrow","HTTP_SERVER_BY_EXPRESS","WeakMap","RxServerAdapterExpress","create","app","use","json","setCors","serverApp","path","cors","options","origin","optionsSuccessStatus","getRequestBody","req","body","getRequestHeaders","headers","getRequestQuery","query","onRequestClose","fn","on","setResponseHeader","res","k","v","setHeader","responseWrite","data","write","endResponseJson","endResponse","end","closeConnection","response","code","message","error","statusCode","set","JSON","stringify","setSSEHeaders","writeHead","flushHeaders","get","handler","post","all","listen","port","hostname","httpServer","Promise","rej","ret","close","err","setImmediate","emit","closeAllConnections"],"sources":["../../../../src/plugins/adapter-express/index.ts"],"sourcesContent":["import type { RxServerAdapter } from '../server/types';\nimport type { Express } from 'express';\nimport express, { Request, Response } from 'express';\nimport {\n Server as HttpServer\n} from 'http';\nimport expressCors from 'cors';\nimport { ensureNotFalsy, getFromMapOrThrow } from 'rxdb/plugins/core';\n\nexport const HTTP_SERVER_BY_EXPRESS = new WeakMap<Express, HttpServer>();\n\nexport const RxServerAdapterExpress: RxServerAdapter<Express, Request, Response> = {\n async create() {\n const app = express();\n app.use(express.json());\n return app;\n },\n setCors(serverApp, path, cors) {\n serverApp.options('/' + path + '/*', expressCors({\n origin: cors,\n // some legacy browsers (IE11, various SmartTVs) choke on 204\n optionsSuccessStatus: 200\n }));\n },\n\n getRequestBody(req: Request) {\n return req.body;\n },\n getRequestHeaders(req: Request) {\n return req.headers as any;\n },\n getRequestQuery(req: Request) {\n return req.query;\n },\n onRequestClose(req: Request, fn) {\n req.on('close', () => {\n fn();\n });\n },\n\n setResponseHeader(res: Response, k: string, v: string) {\n res.setHeader(k, v);\n },\n responseWrite(res: Response, data: string) {\n res.write(data);\n },\n endResponseJson(res: Response, data: any) {\n res.json(data);\n },\n endResponse(res: Response) {\n res.end();\n },\n async closeConnection(response: Response, code: number, message: string) {\n const responseWrite = {\n code,\n error: true,\n message\n };\n response.statusCode = code;\n response.set(\"Connection\", \"close\");\n await response.write(JSON.stringify(responseWrite));\n response.end();\n },\n setSSEHeaders(res: Response) {\n res.writeHead(200, {\n /**\n * Use exact these headers to make is less likely\n * for people to have problems.\n * @link https://www.youtube.com/watch?v=0PcMuYGJPzM\n */\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Connection': 'keep-alive',\n 'Cache-Control': 'no-cache',\n /**\n * Required for nginx\n * @link https://stackoverflow.com/q/61029079/3443137\n */\n 'X-Accel-Buffering': 'no'\n });\n res.flushHeaders();\n },\n\n get(serverApp, path, handler) {\n serverApp.get(path, handler);\n },\n post(serverApp, path, handler) {\n serverApp.post(path, handler);\n },\n all(serverApp, path, handler) {\n serverApp.all(path, handler);\n },\n async listen(serverApp, port, hostname) {\n const httpServer: HttpServer = await new Promise((res, rej) => {\n const ret = ensureNotFalsy(serverApp).listen(port, hostname, () => {\n res(ret);\n });\n });\n HTTP_SERVER_BY_EXPRESS.set(serverApp, httpServer);\n },\n async close(serverApp) {\n const httpServer = getFromMapOrThrow(HTTP_SERVER_BY_EXPRESS, serverApp);\n await new Promise<void>((res, rej) => {\n httpServer.close((err) => {\n if (err) { rej(err); } else { res(); }\n });\n /**\n * By default it will await all ongoing connections\n * before it closes. So we have to close it directly.\n * @link https://stackoverflow.com/a/36830072/3443137\n */\n setImmediate(() => httpServer.emit('close'));\n });\n },\n async closeAllConnections(serverApp) {\n const httpServer = HTTP_SERVER_BY_EXPRESS.get(serverApp);\n if (httpServer) {\n await httpServer.closeAllConnections();\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["express","expressCors","ensureNotFalsy","getFromMapOrThrow","HTTP_SERVER_BY_EXPRESS","WeakMap","RxServerAdapterExpress","create","app","use","json","setCors","serverApp","path","cors","options","origin","optionsSuccessStatus","getRequestBody","req","body","getRequestHeaders","headers","getRequestQuery","query","onRequestClose","fn","on","setResponseHeader","res","k","v","setHeader","responseWrite","data","write","endResponseJson","endResponse","end","closeConnection","response","code","message","error","status","set","JSON","stringify","setSSEHeaders","writeHead","flushHeaders","get","handler","post","all","listen","port","hostname","httpServer","Promise","rej","ret","close","err","setImmediate","emit","closeAllConnections"],"sources":["../../../../src/plugins/adapter-express/index.ts"],"sourcesContent":["import type { RxServerAdapter } from '../server/types';\nimport type { Express } from 'express';\nimport express, { Request, Response } from 'express';\nimport {\n Server as HttpServer\n} from 'http';\nimport expressCors from 'cors';\nimport { ensureNotFalsy, getFromMapOrThrow } from 'rxdb/plugins/core';\n\nexport const HTTP_SERVER_BY_EXPRESS = new WeakMap<Express, HttpServer>();\n\nexport const RxServerAdapterExpress: RxServerAdapter<Express, Request, Response> = {\n async create() {\n const app = express();\n app.use(express.json());\n return app;\n },\n setCors(serverApp, path, cors) {\n serverApp.options('/' + path + '/*', expressCors({\n origin: cors,\n // some legacy browsers (IE11, various SmartTVs) choke on 204\n optionsSuccessStatus: 200\n }));\n },\n\n getRequestBody(req: Request) {\n return req.body;\n },\n getRequestHeaders(req: Request) {\n return req.headers as any;\n },\n getRequestQuery(req: Request) {\n return req.query;\n },\n onRequestClose(req: Request, fn) {\n req.on('close', () => {\n fn();\n });\n },\n\n setResponseHeader(res: Response, k: string, v: string) {\n res.setHeader(k, v);\n },\n responseWrite(res: Response, data: string) {\n res.write(data);\n },\n endResponseJson(res: Response, data: any) {\n res.json(data);\n },\n endResponse(res: Response) {\n res.end();\n },\n async closeConnection(response: Response, code: number, message: string) {\n const responseWrite = {\n code,\n error: true,\n message\n };\n response.status(code);\n response.set(\"Connection\", \"close\");\n await response.write(JSON.stringify(responseWrite));\n response.end();\n },\n setSSEHeaders(res: Response) {\n res.writeHead(200, {\n /**\n * Use exact these headers to make is less likely\n * for people to have problems.\n * @link https://www.youtube.com/watch?v=0PcMuYGJPzM\n */\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Connection': 'keep-alive',\n 'Cache-Control': 'no-cache',\n /**\n * Required for nginx\n * @link https://stackoverflow.com/q/61029079/3443137\n */\n 'X-Accel-Buffering': 'no'\n });\n res.flushHeaders();\n },\n\n get(serverApp, path, handler) {\n serverApp.get(path, handler);\n },\n post(serverApp, path, handler) {\n serverApp.post(path, handler);\n },\n all(serverApp, path, handler) {\n serverApp.all(path, handler);\n },\n async listen(serverApp, port, hostname) {\n const httpServer: HttpServer = await new Promise((res, rej) => {\n const ret = ensureNotFalsy(serverApp).listen(port, hostname, () => {\n res(ret);\n });\n });\n HTTP_SERVER_BY_EXPRESS.set(serverApp, httpServer);\n },\n async close(serverApp) {\n const httpServer = getFromMapOrThrow(HTTP_SERVER_BY_EXPRESS, serverApp);\n await new Promise<void>((res, rej) => {\n httpServer.close((err) => {\n if (err) { rej(err); } else { res(); }\n });\n /**\n * By default it will await all ongoing connections\n * before it closes. So we have to close it directly.\n * @link https://stackoverflow.com/a/36830072/3443137\n */\n setImmediate(() => httpServer.emit('close'));\n });\n },\n async closeAllConnections(serverApp) {\n const httpServer = HTTP_SERVER_BY_EXPRESS.get(serverApp);\n if (httpServer) {\n await httpServer.closeAllConnections();\n }\n }\n};\n"],"mappings":"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","ignoreList":[]}
@@ -1,8 +1,8 @@
1
1
  import { prepareQuery, getChangedDocumentsSinceQuery } from 'rxdb/plugins/core';
2
2
  import { getReplicationHandlerByCollection } from 'rxdb/plugins/replication-websocket';
3
3
  import { filter, mergeMap } from 'rxjs';
4
- import { ensureNotFalsy, getFromMapOrThrow, lastOfArray } from 'rxdb/plugins/utils';
5
- import { addAuthMiddleware, blockPreviousVersionPaths, docContainsServerOnlyFields, doesContainRegexQuerySelector, getDocAllowedMatcher, mergeServerDocumentFieldsMonad, removeServerOnlyFieldsMonad, setCors } from "./helper.js";
4
+ import { ensureNotFalsy, lastOfArray } from 'rxdb/plugins/utils';
5
+ import { blockPreviousVersionPaths, docContainsServerOnlyFields, doesContainRegexQuerySelector, getAuthDataByRequest, getDocAllowedMatcher, mergeServerDocumentFieldsMonad, removeServerOnlyFieldsMonad, setCors } from "./helper.js";
6
6
  export var RxServerReplicationEndpoint = function RxServerReplicationEndpoint(server, name, collection, queryModifier, changeValidator, serverOnlyFields, cors) {
7
7
  this.type = 'replication';
8
8
  this.server = server;
@@ -16,7 +16,6 @@ export var RxServerReplicationEndpoint = function RxServerReplicationEndpoint(se
16
16
  this.urlPath = [this.name, collection.schema.version].join('/');
17
17
  var primaryPath = this.collection.schema.primaryPath;
18
18
  var replicationHandler = getReplicationHandlerByCollection(this.server.database, collection.name);
19
- var authDataByRequest = addAuthMiddleware(this.server, this.urlPath);
20
19
  this.queryModifier = (authData, query) => {
21
20
  if (doesContainRegexQuerySelector(query.selector)) {
22
21
  throw new Error('$regex queries not allowed because of DOS-attacks');
@@ -32,7 +31,10 @@ export var RxServerReplicationEndpoint = function RxServerReplicationEndpoint(se
32
31
  var removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);
33
32
  var mergeServerDocumentFields = mergeServerDocumentFieldsMonad(this.serverOnlyFields);
34
33
  this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pull', async (req, res) => {
35
- var authData = getFromMapOrThrow(authDataByRequest, req);
34
+ var authData = await getAuthDataByRequest(this.server, req, res);
35
+ if (!authData) {
36
+ return;
37
+ }
36
38
  var urlQuery = adapter.getRequestQuery(req);
37
39
  var id = urlQuery.id ? urlQuery.id : '';
38
40
  var lwt = urlQuery.lwt ? parseInt(urlQuery.lwt, 10) : 0;
@@ -59,7 +61,10 @@ export var RxServerReplicationEndpoint = function RxServerReplicationEndpoint(se
59
61
  });
60
62
  });
61
63
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/push', async (req, res) => {
62
- var authData = getFromMapOrThrow(authDataByRequest, req);
64
+ var authData = await getAuthDataByRequest(this.server, req, res);
65
+ if (!authData) {
66
+ return;
67
+ }
63
68
  var docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));
64
69
  var rows = adapter.getRequestBody(req);
65
70
  var ids = [];
@@ -109,8 +114,11 @@ export var RxServerReplicationEndpoint = function RxServerReplicationEndpoint(se
109
114
  adapter.endResponseJson(res, conflicts);
110
115
  });
111
116
  this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pullStream', async (req, res) => {
117
+ var authData = await getAuthDataByRequest(this.server, req, res);
118
+ if (!authData) {
119
+ return;
120
+ }
112
121
  adapter.setSSEHeaders(res);
113
- var authData = getFromMapOrThrow(authDataByRequest, req);
114
122
  var docDataMatcherStream = getDocAllowedMatcher(this, ensureNotFalsy(authData));
115
123
  var subscription = replicationHandler.masterChangeStream$.pipe(mergeMap(async changes => {
116
124
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint-replication.js","names":["prepareQuery","getChangedDocumentsSinceQuery","getReplicationHandlerByCollection","filter","mergeMap","ensureNotFalsy","getFromMapOrThrow","lastOfArray","addAuthMiddleware","blockPreviousVersionPaths","docContainsServerOnlyFields","doesContainRegexQuerySelector","getDocAllowedMatcher","mergeServerDocumentFieldsMonad","removeServerOnlyFieldsMonad","setCors","RxServerReplicationEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","type","adapter","join","schema","version","urlPath","primaryPath","replicationHandler","database","authDataByRequest","authData","query","selector","Error","change","assumedMasterState","newDocumentState","removeServerOnlyFields","mergeServerDocumentFields","get","serverApp","req","res","urlQuery","getRequestQuery","id","lwt","parseInt","limit","plainQuery","storageInstance","useQueryChanges","prepared","jsonSchema","result","newCheckpoint","documents","length","updatedAt","_meta","responseDocuments","map","d","setResponseHeader","endResponseJson","checkpoint","post","docDataMatcherWrite","rows","getRequestBody","ids","forEach","row","push","nonAllowedRow","find","closeConnection","hasInvalidChange","currentStateDocsArray","findDocumentsById","currentStateDocs","Map","set","useRows","isChangeValid","serverDoc","conflicts","masterWrite","setSSEHeaders","docDataMatcherStream","subscription","masterChangeStream$","pipe","changes","authHandler","getRequestHeaders","err","useDocs","f","subscribe","filteredAndModified","responseWrite","JSON","stringify","onRequestClose","unsubscribe","endResponse"],"sources":["../../../../src/plugins/server/endpoint-replication.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxReplicationHandler,\n RxReplicationWriteToMasterRow,\n RxStorageDefaultCheckpoint,\n StringKeys,\n prepareQuery,\n getChangedDocumentsSinceQuery,\n RxDocumentData\n} from 'rxdb/plugins/core';\nimport { getReplicationHandlerByCollection } from 'rxdb/plugins/replication-websocket';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerAuthData,\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow,\n lastOfArray\n} from 'rxdb/plugins/utils';\n\nimport {\n addAuthMiddleware,\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getDocAllowedMatcher,\n mergeServerDocumentFieldsMonad,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\nexport type RxReplicationEndpointMessageType = {\n id: string;\n method: StringKeys<RxReplicationHandler<any, any>> | 'auth';\n params: any[];\n};\n\nexport class RxServerReplicationEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'replication';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string,\n ) {\n const adapter = this.server.adapter;\n\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n\n const primaryPath = this.collection.schema.primaryPath;\n const replicationHandler = getReplicationHandlerByCollection(this.server.database, collection.name);\n const authDataByRequest = addAuthMiddleware(\n this.server,\n this.urlPath\n );\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (change.assumedMasterState && docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad<RxDocType>(this.serverOnlyFields);\n const mergeServerDocumentFields = mergeServerDocumentFieldsMonad<RxDocType>(this.serverOnlyFields);\n\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pull', async (req: any, res: any) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n\n const urlQuery = adapter.getRequestQuery(req);\n const id = urlQuery.id ? urlQuery.id as string : '';\n const lwt = urlQuery.lwt ? parseInt(urlQuery.lwt as any, 10) : 0;\n const limit = urlQuery.limit ? parseInt(urlQuery.limit as any, 10) : 1;\n const plainQuery = getChangedDocumentsSinceQuery<RxDocType, RxStorageDefaultCheckpoint>(\n this.collection.storageInstance,\n limit,\n { id, lwt }\n );\n const useQueryChanges: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData as any),\n plainQuery\n );\n const prepared = prepareQuery<RxDocType>(\n this.collection.schema.jsonSchema,\n useQueryChanges\n );\n const result = await this.collection.storageInstance.query(prepared);\n\n const newCheckpoint = result.documents.length === 0 ? { id, lwt } : {\n id: ensureNotFalsy(lastOfArray(result.documents))[primaryPath],\n updatedAt: ensureNotFalsy(lastOfArray(result.documents))._meta.lwt\n };\n const responseDocuments = result.documents.map(d => removeServerOnlyFields(d));\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: responseDocuments,\n checkpoint: newCheckpoint\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/push', async (req: any, res: any) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData as any));\n const rows: RxReplicationWriteToMasterRow<RxDocType>[] = adapter.getRequestBody(req);\n const ids: string[] = [];\n rows.forEach(row => ids.push((row.newDocumentState as any)[primaryPath]));\n\n for (const row of rows) {\n // TODO remove this check\n if (row.assumedMasterState && (row.assumedMasterState as any)._meta) {\n throw new Error('body document contains meta!');\n }\n }\n\n // ensure all writes are allowed\n const nonAllowedRow = rows.find(row => {\n if (\n !docDataMatcherWrite(row.newDocumentState as any) ||\n (row.assumedMasterState && !docDataMatcherWrite(row.assumedMasterState as any))\n ) {\n return true;\n }\n });\n if (nonAllowedRow) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n let hasInvalidChange = false;\n\n const currentStateDocsArray = await this.collection.storageInstance.findDocumentsById(ids, true);\n const currentStateDocs = new Map<string, RxDocumentData<RxDocType>>();\n currentStateDocsArray.forEach(d => currentStateDocs.set((d as any)[primaryPath], d));\n\n const useRows: typeof rows = rows.map((row) => {\n const id = (row.newDocumentState as any)[primaryPath];\n const isChangeValid = this.changeValidator(ensureNotFalsy(authData as any), {\n newDocumentState: removeServerOnlyFields(row.newDocumentState),\n assumedMasterState: removeServerOnlyFields(row.assumedMasterState)\n });\n if (!isChangeValid) {\n hasInvalidChange = true;\n }\n\n const serverDoc = currentStateDocs.get(id);\n return {\n newDocumentState: mergeServerDocumentFields(row.newDocumentState, serverDoc),\n assumedMasterState: mergeServerDocumentFields(row.assumedMasterState as any, serverDoc)\n } as typeof row;\n });\n if (hasInvalidChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const conflicts = await replicationHandler.masterWrite(useRows);\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, conflicts);\n });\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pullStream', async (req, res) => {\n adapter.setSSEHeaders(res);\n\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherStream = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n const subscription = replicationHandler.masterChangeStream$.pipe(\n mergeMap(async (changes) => {\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting an event.\n */\n let authData: RxServerAuthData<AuthType>;\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n if (changes === 'RESYNC') {\n return changes;\n } else {\n const useDocs = changes.documents.filter(d => docDataMatcherStream(d as any));\n return {\n documents: useDocs,\n checkpoint: changes.checkpoint\n };\n }\n }),\n filter(f => f !== null && (f === 'RESYNC' || f.documents.length > 0))\n ).subscribe(filteredAndModified => {\n if (filteredAndModified === 'RESYNC') {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(filteredAndModified) + '\\n\\n');\n } else {\n const responseDocuments = ensureNotFalsy(filteredAndModified).documents.map(d => removeServerOnlyFields(d as any));\n adapter.responseWrite(res, 'data: ' + JSON.stringify({ documents: responseDocuments, checkpoint: ensureNotFalsy(filteredAndModified).checkpoint }) + '\\n\\n');\n }\n\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(res);\n });\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"endpoint-replication.js","names":["prepareQuery","getChangedDocumentsSinceQuery","getReplicationHandlerByCollection","filter","mergeMap","ensureNotFalsy","lastOfArray","blockPreviousVersionPaths","docContainsServerOnlyFields","doesContainRegexQuerySelector","getAuthDataByRequest","getDocAllowedMatcher","mergeServerDocumentFieldsMonad","removeServerOnlyFieldsMonad","setCors","RxServerReplicationEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","type","adapter","join","schema","version","urlPath","primaryPath","replicationHandler","database","authData","query","selector","Error","change","assumedMasterState","newDocumentState","removeServerOnlyFields","mergeServerDocumentFields","get","serverApp","req","res","urlQuery","getRequestQuery","id","lwt","parseInt","limit","plainQuery","storageInstance","useQueryChanges","prepared","jsonSchema","result","newCheckpoint","documents","length","updatedAt","_meta","responseDocuments","map","d","setResponseHeader","endResponseJson","checkpoint","post","docDataMatcherWrite","rows","getRequestBody","ids","forEach","row","push","nonAllowedRow","find","closeConnection","hasInvalidChange","currentStateDocsArray","findDocumentsById","currentStateDocs","Map","set","useRows","isChangeValid","serverDoc","conflicts","masterWrite","setSSEHeaders","docDataMatcherStream","subscription","masterChangeStream$","pipe","changes","authHandler","getRequestHeaders","err","useDocs","f","subscribe","filteredAndModified","responseWrite","JSON","stringify","onRequestClose","unsubscribe","endResponse"],"sources":["../../../../src/plugins/server/endpoint-replication.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxReplicationHandler,\n RxReplicationWriteToMasterRow,\n RxStorageDefaultCheckpoint,\n StringKeys,\n prepareQuery,\n getChangedDocumentsSinceQuery,\n RxDocumentData\n} from 'rxdb/plugins/core';\nimport { getReplicationHandlerByCollection } from 'rxdb/plugins/replication-websocket';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerAuthData,\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow,\n lastOfArray\n} from 'rxdb/plugins/utils';\n\nimport {\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getAuthDataByRequest,\n getDocAllowedMatcher,\n mergeServerDocumentFieldsMonad,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\nexport type RxReplicationEndpointMessageType = {\n id: string;\n method: StringKeys<RxReplicationHandler<any, any>> | 'auth';\n params: any[];\n};\n\nexport class RxServerReplicationEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'replication';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string,\n ) {\n const adapter = this.server.adapter;\n\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n\n const primaryPath = this.collection.schema.primaryPath;\n const replicationHandler = getReplicationHandlerByCollection(this.server.database, collection.name);\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (change.assumedMasterState && docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad<RxDocType>(this.serverOnlyFields);\n const mergeServerDocumentFields = mergeServerDocumentFieldsMonad<RxDocType>(this.serverOnlyFields);\n\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pull', async (req: any, res: any) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const urlQuery = adapter.getRequestQuery(req);\n const id = urlQuery.id ? urlQuery.id as string : '';\n const lwt = urlQuery.lwt ? parseInt(urlQuery.lwt as any, 10) : 0;\n const limit = urlQuery.limit ? parseInt(urlQuery.limit as any, 10) : 1;\n const plainQuery = getChangedDocumentsSinceQuery<RxDocType, RxStorageDefaultCheckpoint>(\n this.collection.storageInstance,\n limit,\n { id, lwt }\n );\n const useQueryChanges: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n plainQuery\n );\n const prepared = prepareQuery<RxDocType>(\n this.collection.schema.jsonSchema,\n useQueryChanges\n );\n const result = await this.collection.storageInstance.query(prepared);\n\n const newCheckpoint = result.documents.length === 0 ? { id, lwt } : {\n id: ensureNotFalsy(lastOfArray(result.documents))[primaryPath],\n updatedAt: ensureNotFalsy(lastOfArray(result.documents))._meta.lwt\n };\n const responseDocuments = result.documents.map(d => removeServerOnlyFields(d));\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: responseDocuments,\n checkpoint: newCheckpoint\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/push', async (req: any, res: any) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData as any));\n const rows: RxReplicationWriteToMasterRow<RxDocType>[] = adapter.getRequestBody(req);\n const ids: string[] = [];\n rows.forEach(row => ids.push((row.newDocumentState as any)[primaryPath]));\n\n for (const row of rows) {\n // TODO remove this check\n if (row.assumedMasterState && (row.assumedMasterState as any)._meta) {\n throw new Error('body document contains meta!');\n }\n }\n\n // ensure all writes are allowed\n const nonAllowedRow = rows.find(row => {\n if (\n !docDataMatcherWrite(row.newDocumentState as any) ||\n (row.assumedMasterState && !docDataMatcherWrite(row.assumedMasterState as any))\n ) {\n return true;\n }\n });\n if (nonAllowedRow) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n let hasInvalidChange = false;\n\n const currentStateDocsArray = await this.collection.storageInstance.findDocumentsById(ids, true);\n const currentStateDocs = new Map<string, RxDocumentData<RxDocType>>();\n currentStateDocsArray.forEach(d => currentStateDocs.set((d as any)[primaryPath], d));\n\n const useRows: typeof rows = rows.map((row) => {\n const id = (row.newDocumentState as any)[primaryPath];\n const isChangeValid = this.changeValidator(ensureNotFalsy(authData), {\n newDocumentState: removeServerOnlyFields(row.newDocumentState),\n assumedMasterState: removeServerOnlyFields(row.assumedMasterState)\n });\n if (!isChangeValid) {\n hasInvalidChange = true;\n }\n\n const serverDoc = currentStateDocs.get(id);\n return {\n newDocumentState: mergeServerDocumentFields(row.newDocumentState, serverDoc),\n assumedMasterState: mergeServerDocumentFields(row.assumedMasterState as any, serverDoc)\n } as typeof row;\n });\n if (hasInvalidChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const conflicts = await replicationHandler.masterWrite(useRows);\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, conflicts);\n });\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/pullStream', async (req, res) => {\n \n const authData = await getAuthDataByRequest<AuthType, any, any>(this.server, req, res);\n if (!authData) { return; }\n \n adapter.setSSEHeaders(res);\n const docDataMatcherStream = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n const subscription = replicationHandler.masterChangeStream$.pipe(\n mergeMap(async (changes) => {\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting an event.\n */\n let authData: RxServerAuthData<AuthType>;\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n if (changes === 'RESYNC') {\n return changes;\n } else {\n const useDocs = changes.documents.filter(d => docDataMatcherStream(d as any));\n return {\n documents: useDocs,\n checkpoint: changes.checkpoint\n };\n }\n }),\n filter(f => f !== null && (f === 'RESYNC' || f.documents.length > 0))\n ).subscribe(filteredAndModified => {\n if (filteredAndModified === 'RESYNC') {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(filteredAndModified) + '\\n\\n');\n } else {\n const responseDocuments = ensureNotFalsy(filteredAndModified).documents.map(d => removeServerOnlyFields(d as any));\n adapter.responseWrite(res, 'data: ' + JSON.stringify({ documents: responseDocuments, checkpoint: ensureNotFalsy(filteredAndModified).checkpoint }) + '\\n\\n');\n }\n\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(res);\n });\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  import { normalizeMangoQuery } from 'rxdb/plugins/core';
2
2
  import { filter, mergeMap } from 'rxjs';
3
- import { ensureNotFalsy, getFromMapOrThrow } from 'rxdb/plugins/utils';
4
- import { addAuthMiddleware, blockPreviousVersionPaths, docContainsServerOnlyFields, doesContainRegexQuerySelector, getDocAllowedMatcher, removeServerOnlyFieldsMonad, setCors } from "./helper.js";
3
+ import { ensureNotFalsy } from 'rxdb/plugins/utils';
4
+ import { blockPreviousVersionPaths, docContainsServerOnlyFields, doesContainRegexQuerySelector, getAuthDataByRequest, getDocAllowedMatcher, removeServerOnlyFieldsMonad, setCors } from "./helper.js";
5
5
  export var REST_PATHS = ['query', 'query/observe', 'get', 'set', 'delete'
6
6
 
7
7
  // TODO
@@ -23,7 +23,6 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
23
23
  blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);
24
24
  this.urlPath = [this.name, collection.schema.version].join('/');
25
25
  var primaryPath = this.collection.schema.primaryPath;
26
- var authDataByRequest = addAuthMiddleware(this.server, this.urlPath);
27
26
  this.queryModifier = (authData, query) => {
28
27
  if (doesContainRegexQuerySelector(query.selector)) {
29
28
  throw new Error('$regex queries not allowed because of DOS-attacks');
@@ -39,7 +38,10 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
39
38
  var removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);
40
39
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {
41
40
  ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');
42
- var authData = getFromMapOrThrow(authDataByRequest, req);
41
+ var authData = await getAuthDataByRequest(this.server, req, res);
42
+ if (!authData) {
43
+ return;
44
+ }
43
45
  var useQuery;
44
46
  try {
45
47
  useQuery = this.queryModifier(ensureNotFalsy(authData), normalizeMangoQuery(this.collection.schema.jsonSchema, adapter.getRequestBody(req)));
@@ -61,7 +63,10 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
61
63
  * like ?query=e3NlbGVjdG9yOiB7fX0=
62
64
  */
63
65
  this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {
64
- var authData = getFromMapOrThrow(authDataByRequest, req);
66
+ var authData = await getAuthDataByRequest(this.server, req, res);
67
+ if (!authData) {
68
+ return;
69
+ }
65
70
  adapter.setSSEHeaders(res);
66
71
  var useQuery = this.queryModifier(ensureNotFalsy(authData), normalizeMangoQuery(this.collection.schema.jsonSchema, JSON.parse(atob(adapter.getRequestQuery(req).query))));
67
72
  var rxQuery = this.collection.find(useQuery);
@@ -93,7 +98,10 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
93
98
  });
94
99
  });
95
100
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {
96
- var authData = getFromMapOrThrow(authDataByRequest, req);
101
+ var authData = await getAuthDataByRequest(this.server, req, res);
102
+ if (!authData) {
103
+ return;
104
+ }
97
105
  var ids = adapter.getRequestBody(req);
98
106
  var rxQuery = this.collection.findByIds(ids);
99
107
  var resultMap = await rxQuery.exec();
@@ -108,7 +116,10 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
108
116
  });
109
117
  });
110
118
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {
111
- var authData = getFromMapOrThrow(authDataByRequest, req);
119
+ var authData = await getAuthDataByRequest(this.server, req, res);
120
+ if (!authData) {
121
+ return;
122
+ }
112
123
  var docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));
113
124
  var docsData = adapter.getRequestBody(req);
114
125
  for (var docData of docsData) {
@@ -162,7 +173,10 @@ export var RxServerRestEndpoint = function RxServerRestEndpoint(server, name, co
162
173
  adapter.endResponseJson(res, {});
163
174
  });
164
175
  this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {
165
- var authData = getFromMapOrThrow(authDataByRequest, req);
176
+ var authData = await getAuthDataByRequest(this.server, req, res);
177
+ if (!authData) {
178
+ return;
179
+ }
166
180
  var docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));
167
181
  var ids = adapter.getRequestBody(req);
168
182
  while (ids.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint-rest.js","names":["normalizeMangoQuery","filter","mergeMap","ensureNotFalsy","getFromMapOrThrow","addAuthMiddleware","blockPreviousVersionPaths","docContainsServerOnlyFields","doesContainRegexQuerySelector","getDocAllowedMatcher","removeServerOnlyFieldsMonad","setCors","REST_PATHS","RxServerRestEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","_this","type","adapter","join","schema","version","urlPath","primaryPath","authDataByRequest","authData","query","selector","Error","change","assumedMasterState","newDocumentState","removeServerOnlyFields","post","serverApp","req","res","getRequestBody","useQuery","jsonSchema","err","closeConnection","rxQuery","find","result","exec","setResponseHeader","endResponseJson","documents","map","d","toJSON","get","setSSEHeaders","JSON","parse","atob","getRequestQuery","subscription","$","pipe","resultData","doc","authHandler","getRequestHeaders","f","subscribe","responseWrite","stringify","onRequestClose","unsubscribe","endResponse","ids","findByIds","resultMap","resultValues","Array","from","values","docMatcher","useDocs","docDataMatcherWrite","docsData","docData","allowed","onWriteError","rxdb","code","push","length","promises","docs","useDocsData","slice","_loop","_docData","id","insert","catch","isAllowed","v","patch","_ret","Promise","all","useIds","docsMap","_loop2","isAllowedDoc","isAllowedChange","remove","_ret2"],"sources":["../../../../src/plugins/server/endpoint-rest.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxError,\n normalizeMangoQuery\n} from 'rxdb/plugins/core';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow\n} from 'rxdb/plugins/utils';\n\nimport {\n addAuthMiddleware,\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getDocAllowedMatcher,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\n\nexport const REST_PATHS = [\n 'query',\n 'query/observe',\n 'get',\n 'set',\n 'delete',\n\n // TODO\n /*\n 'attachments/add',\n 'attachments/delete',\n 'events'\n */\n] as const;\n\n\nexport class RxServerRestEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'rest';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string\n ) {\n const adapter = server.adapter;\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n const primaryPath = this.collection.schema.primaryPath;\n const authDataByRequest = addAuthMiddleware(\n this.server,\n this.urlPath\n );\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (\n change.assumedMasterState &&\n docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)\n ) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {\n ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');\n const authData = getFromMapOrThrow(authDataByRequest, req);\n let useQuery: FilledMangoQuery<RxDocType>\n try {\n useQuery = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n adapter.getRequestBody(req)\n )\n );\n } catch (err) {\n adapter.closeConnection(res, 400, 'Bad Request');\n return;\n }\n const rxQuery = this.collection.find(useQuery as any);\n const result = await rxQuery.exec();\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: result.map(d => removeServerOnlyFields(d.toJSON()))\n });\n });\n\n /**\n * It is not possible to send data with server send events,\n * so we send the query as query parameter in base64\n * like ?query=e3NlbGVjdG9yOiB7fX0=\n */\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {\n let authData = getFromMapOrThrow(authDataByRequest, req);\n adapter.setSSEHeaders(res);\n\n const useQuery: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n JSON.parse(atob(adapter.getRequestQuery(req).query as string))\n )\n );\n\n const rxQuery = this.collection.find(useQuery as any);\n const subscription = rxQuery.$.pipe(\n mergeMap(async (result) => {\n const resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));\n\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting the new results.\n */\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req));\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n return resultData;\n }),\n filter(f => f !== null)\n ).subscribe(resultData => {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(resultData) + '\\n\\n');\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(req);\n });\n });\n\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const ids: string[] = adapter.getRequestBody(req);\n\n const rxQuery = this.collection.findByIds(ids);\n const resultMap = await rxQuery.exec();\n const resultValues = Array.from(resultMap.values());\n const docMatcher = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n let useDocs = resultValues.map(d => d.toJSON());\n useDocs = useDocs.filter(d => docMatcher(d as any));\n useDocs = useDocs.map(d => removeServerOnlyFields(d))\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: useDocs\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let docsData: RxDocType[] = adapter.getRequestBody(req);\n\n for (const docData of docsData) {\n const allowed = docDataMatcherWrite(docData as any);\n if (!allowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n }\n\n function onWriteError(err: RxError, docData: RxDocType) {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n docsData.push(docData);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }\n\n while (docsData.length > 0) {\n const promises: Promise<any>[] = [];\n const docs = await collection.findByIds(docsData.map(d => (d as any)[primaryPath])).exec();\n let useDocsData = docsData.slice();\n docsData = [];\n for (const docData of useDocsData) {\n const id = (docData as any)[primaryPath];\n const doc = docs.get(id);\n if (!doc) {\n promises.push(this.collection.insert(docData).catch(err => onWriteError(err, docData)));\n } else {\n const isAllowed = this.changeValidator(authData, {\n newDocumentState: removeServerOnlyFields(docData as any),\n assumedMasterState: removeServerOnlyFields(doc.toJSON(true))\n });\n if (!isAllowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n promises.push(doc.patch(docData).catch(err => onWriteError(err, docData)));\n }\n }\n await Promise.all(promises);\n }\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json')\n adapter.endResponseJson(res, {});\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {\n const authData = getFromMapOrThrow(authDataByRequest, req);\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let ids: string[] = adapter.getRequestBody(req);\n while (ids.length > 0) {\n const useIds = ids.slice(0);\n ids = [];\n const promises: Promise<any>[] = [];\n const docsMap = await this.collection.findByIds(useIds).exec();\n for (const id of useIds) {\n const doc = docsMap.get(id);\n if (doc) {\n const isAllowedDoc = docDataMatcherWrite(doc.toJSON(true) as any);\n if (!isAllowedDoc) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const isAllowedChange = this.changeValidator(authData, {\n newDocumentState: doc.toJSON(true) as any,\n assumedMasterState: doc.toJSON(true) as any\n });\n if (!isAllowedChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n promises.push(doc.remove().catch((err: RxError) => {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n ids.push(id);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }));\n }\n }\n await Promise.all(promises);\n }\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {});\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"endpoint-rest.js","names":["normalizeMangoQuery","filter","mergeMap","ensureNotFalsy","blockPreviousVersionPaths","docContainsServerOnlyFields","doesContainRegexQuerySelector","getAuthDataByRequest","getDocAllowedMatcher","removeServerOnlyFieldsMonad","setCors","REST_PATHS","RxServerRestEndpoint","server","name","collection","queryModifier","changeValidator","serverOnlyFields","cors","_this","type","adapter","join","schema","version","urlPath","primaryPath","authData","query","selector","Error","change","assumedMasterState","newDocumentState","removeServerOnlyFields","post","serverApp","req","res","getRequestBody","useQuery","jsonSchema","err","closeConnection","rxQuery","find","result","exec","setResponseHeader","endResponseJson","documents","map","d","toJSON","get","setSSEHeaders","JSON","parse","atob","getRequestQuery","subscription","$","pipe","resultData","doc","authHandler","getRequestHeaders","f","subscribe","responseWrite","stringify","onRequestClose","unsubscribe","endResponse","ids","findByIds","resultMap","resultValues","Array","from","values","docMatcher","useDocs","docDataMatcherWrite","docsData","docData","allowed","onWriteError","rxdb","code","push","length","promises","docs","useDocsData","slice","_loop","_docData","id","insert","catch","isAllowed","v","patch","_ret","Promise","all","useIds","docsMap","_loop2","isAllowedDoc","isAllowedChange","remove","_ret2"],"sources":["../../../../src/plugins/server/endpoint-rest.ts"],"sourcesContent":["import {\n FilledMangoQuery,\n RxCollection,\n RxError,\n normalizeMangoQuery\n} from 'rxdb/plugins/core';\nimport type { RxServer } from './rx-server.ts';\nimport type {\n RxServerChangeValidator,\n RxServerEndpoint,\n RxServerQueryModifier\n} from './types.ts';\nimport { filter, mergeMap } from 'rxjs';\nimport {\n ensureNotFalsy,\n getFromMapOrThrow\n} from 'rxdb/plugins/utils';\n\nimport {\n blockPreviousVersionPaths,\n docContainsServerOnlyFields,\n doesContainRegexQuerySelector,\n getAuthDataByRequest,\n getDocAllowedMatcher,\n removeServerOnlyFieldsMonad,\n setCors\n} from './helper.ts';\n\n\nexport const REST_PATHS = [\n 'query',\n 'query/observe',\n 'get',\n 'set',\n 'delete',\n\n // TODO\n /*\n 'attachments/add',\n 'attachments/delete',\n 'events'\n */\n] as const;\n\n\nexport class RxServerRestEndpoint<ServerAppType, AuthType, RxDocType> implements RxServerEndpoint<AuthType, RxDocType> {\n readonly type = 'rest';\n readonly urlPath: string;\n readonly changeValidator: RxServerChangeValidator<AuthType, RxDocType>;\n readonly queryModifier: RxServerQueryModifier<AuthType, RxDocType>;\n constructor(\n public readonly server: RxServer<ServerAppType, AuthType>,\n public readonly name: string,\n public readonly collection: RxCollection<RxDocType>,\n queryModifier: RxServerQueryModifier<AuthType, RxDocType>,\n changeValidator: RxServerChangeValidator<AuthType, RxDocType>,\n public readonly serverOnlyFields: string[],\n public readonly cors?: string\n ) {\n const adapter = server.adapter;\n setCors(this.server, [this.name].join('/'), cors);\n blockPreviousVersionPaths(this.server, [this.name].join('/'), collection.schema.version);\n\n this.urlPath = [this.name, collection.schema.version].join('/');\n const primaryPath = this.collection.schema.primaryPath;\n\n this.queryModifier = (authData, query) => {\n if (doesContainRegexQuerySelector(query.selector)) {\n throw new Error('$regex queries not allowed because of DOS-attacks');\n }\n return queryModifier(authData, query);\n }\n this.changeValidator = (authData, change) => {\n if (\n (\n change.assumedMasterState &&\n docContainsServerOnlyFields(serverOnlyFields, change.assumedMasterState)\n ) ||\n docContainsServerOnlyFields(serverOnlyFields, change.newDocumentState)\n ) {\n return false;\n }\n return changeValidator(authData, change);\n }\n const removeServerOnlyFields = removeServerOnlyFieldsMonad(this.serverOnlyFields);\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/query', async (req, res) => {\n ensureNotFalsy(adapter.getRequestBody(req), 'req body is empty');\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n let useQuery: FilledMangoQuery<RxDocType>\n try {\n useQuery = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n adapter.getRequestBody(req)\n )\n );\n } catch (err) {\n adapter.closeConnection(res, 400, 'Bad Request');\n return;\n }\n const rxQuery = this.collection.find(useQuery as any);\n const result = await rxQuery.exec();\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: result.map(d => removeServerOnlyFields(d.toJSON()))\n });\n });\n\n /**\n * It is not possible to send data with server send events,\n * so we send the query as query parameter in base64\n * like ?query=e3NlbGVjdG9yOiB7fX0=\n */\n this.server.adapter.get(this.server.serverApp, '/' + this.urlPath + '/query/observe', async (req, res) => {\n let authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n adapter.setSSEHeaders(res);\n\n const useQuery: FilledMangoQuery<RxDocType> = this.queryModifier(\n ensureNotFalsy(authData),\n normalizeMangoQuery(\n this.collection.schema.jsonSchema,\n JSON.parse(atob(adapter.getRequestQuery(req).query as string))\n )\n );\n\n const rxQuery = this.collection.find(useQuery as any);\n const subscription = rxQuery.$.pipe(\n mergeMap(async (result) => {\n const resultData = result.map(doc => removeServerOnlyFields(doc.toJSON()));\n\n /**\n * The auth-data might be expired\n * so we re-run the auth parsing each time\n * before emitting the new results.\n */\n try {\n authData = await server.authHandler(adapter.getRequestHeaders(req)) as any;\n } catch (err) {\n adapter.closeConnection(res, 401, 'Unauthorized');\n return null;\n }\n\n return resultData;\n }),\n filter(f => f !== null)\n ).subscribe(resultData => {\n adapter.responseWrite(res, 'data: ' + JSON.stringify(resultData) + '\\n\\n');\n });\n\n /**\n * @link https://youtu.be/0PcMuYGJPzM?si=AxkczxcMaUwhh8k9&t=363\n */\n adapter.onRequestClose(req, () => {\n subscription.unsubscribe();\n adapter.endResponse(req);\n });\n });\n\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/get', async (req, res) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const ids: string[] = adapter.getRequestBody(req);\n\n const rxQuery = this.collection.findByIds(ids);\n const resultMap = await rxQuery.exec();\n const resultValues = Array.from(resultMap.values());\n const docMatcher = getDocAllowedMatcher(this, ensureNotFalsy(authData) as any);\n let useDocs = resultValues.map(d => d.toJSON());\n useDocs = useDocs.filter(d => docMatcher(d as any));\n useDocs = useDocs.map(d => removeServerOnlyFields(d))\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {\n documents: useDocs\n });\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/set', async (req, res) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData) as any);\n\n let docsData: RxDocType[] = adapter.getRequestBody(req);\n\n for (const docData of docsData) {\n const allowed = docDataMatcherWrite(docData as any);\n if (!allowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n }\n\n function onWriteError(err: RxError, docData: RxDocType) {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n docsData.push(docData);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }\n\n while (docsData.length > 0) {\n const promises: Promise<any>[] = [];\n const docs = await collection.findByIds(docsData.map(d => (d as any)[primaryPath])).exec();\n let useDocsData = docsData.slice();\n docsData = [];\n for (const docData of useDocsData) {\n const id = (docData as any)[primaryPath];\n const doc = docs.get(id);\n if (!doc) {\n promises.push(this.collection.insert(docData).catch(err => onWriteError(err, docData)));\n } else {\n const isAllowed = this.changeValidator(authData, {\n newDocumentState: removeServerOnlyFields(docData as any),\n assumedMasterState: removeServerOnlyFields(doc.toJSON(true))\n });\n if (!isAllowed) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n promises.push(doc.patch(docData).catch(err => onWriteError(err, docData)));\n }\n }\n await Promise.all(promises);\n }\n\n adapter.setResponseHeader(res, 'Content-Type', 'application/json')\n adapter.endResponseJson(res, {});\n });\n\n this.server.adapter.post(this.server.serverApp, '/' + this.urlPath + '/delete', async (req, res) => {\n const authData = await getAuthDataByRequest(this.server, req, res);\n if (!authData) { return; }\n\n const docDataMatcherWrite = getDocAllowedMatcher(this, ensureNotFalsy(authData));\n\n let ids: string[] = adapter.getRequestBody(req);\n while (ids.length > 0) {\n const useIds = ids.slice(0);\n ids = [];\n const promises: Promise<any>[] = [];\n const docsMap = await this.collection.findByIds(useIds).exec();\n for (const id of useIds) {\n const doc = docsMap.get(id);\n if (doc) {\n const isAllowedDoc = docDataMatcherWrite(doc.toJSON(true) as any);\n if (!isAllowedDoc) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n const isAllowedChange = this.changeValidator(authData, {\n newDocumentState: doc.toJSON(true) as any,\n assumedMasterState: doc.toJSON(true) as any\n });\n if (!isAllowedChange) {\n adapter.closeConnection(res, 403, 'Forbidden');\n return;\n }\n\n promises.push(doc.remove().catch((err: RxError) => {\n if (err.rxdb && err.code === 'CONFLICT') {\n // just retry on conflicts\n ids.push(id);\n } else {\n adapter.closeConnection(res, 500, 'Internal Server Error');\n throw err;\n }\n }));\n }\n }\n await Promise.all(promises);\n }\n adapter.setResponseHeader(res, 'Content-Type', 'application/json');\n adapter.endResponseJson(res, {});\n });\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- import { flatClone, getQueryMatcher, normalizeMangoQuery, uniqueArray } from 'rxdb/plugins/core';
1
+ import { flatClone, getFromMapOrCreate, getQueryMatcher, normalizeMangoQuery, uniqueArray } from 'rxdb/plugins/core';
2
2
  export function setCors(server, path, cors) {
3
3
  var useCors = cors;
4
4
  if (!useCors) {
@@ -26,21 +26,20 @@ export function blockPreviousVersionPaths(server, path, currentVersion) {
26
26
  _loop();
27
27
  }
28
28
  }
29
- export function addAuthMiddleware(server, path) {
30
- var authDataByRequest = new WeakMap();
31
- async function auth(req, res, next) {
29
+ var AUTH_PER_REQUEST = new WeakMap();
30
+ export async function getAuthDataByRequest(server, request, response) {
31
+ return getFromMapOrCreate(AUTH_PER_REQUEST, request, async () => {
32
32
  try {
33
- var authData = await server.authHandler(req.headers);
34
- authDataByRequest.set(req, authData);
35
- next();
33
+ var headers = server.adapter.getRequestHeaders(request);
34
+ var authData = await server.authHandler(headers);
35
+ return authData;
36
36
  } catch (err) {
37
- server.adapter.closeConnection(res, 401, 'Unauthorized');
38
- return;
37
+ server.adapter.closeConnection(response, 401, 'Unauthorized');
38
+ return false;
39
39
  }
40
- }
41
- server.adapter.all(server.serverApp, '/' + path + '/*', auth);
42
- return authDataByRequest;
40
+ });
43
41
  }
42
+ ;
44
43
  var defaultMatchingQuery = {
45
44
  selector: {},
46
45
  skip: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"helper.js","names":["flatClone","getQueryMatcher","normalizeMangoQuery","uniqueArray","setCors","server","path","cors","useCors","adapter","serverApp","blockPreviousVersionPaths","currentVersion","v","_loop","version","all","req","res","closeConnection","addAuthMiddleware","authDataByRequest","WeakMap","auth","next","authData","authHandler","headers","set","err","defaultMatchingQuery","selector","skip","sort","getDocAllowedMatcher","endpoint","useQuery","queryModifier","collection","schema","jsonSchema","docDataMatcher","docContainsServerOnlyFields","serverOnlyFields","doc","has","find","field","removeServerOnlyFieldsMonad","serverOnlyFieldsStencil","_meta","undefined","_rev","_attachments","forEach","docData","Object","assign","mergeServerDocumentFieldsMonad","useFields","slice","clientDoc","serverDoc","ret","doesContainRegexQuerySelector","Array","isArray","found","item","entries","key","value"],"sources":["../../../../src/plugins/server/helper.ts"],"sourcesContent":["import { RxServer } from './rx-server';\nimport type {\n Request,\n Response,\n NextFunction\n} from 'express';\nimport type { RxServerAdapter, RxServerAuthData, RxServerEndpoint } from './types';\nimport {\n FilledMangoQuery,\n MangoQuerySelector,\n RxDocumentData,\n flatClone,\n getQueryMatcher,\n normalizeMangoQuery,\n uniqueArray\n} from 'rxdb/plugins/core';\n\nexport function setCors(\n server: RxServer<any, any>,\n path: string,\n cors?: string\n) {\n let useCors = cors;\n if (!useCors) {\n useCors = server.cors;\n }\n if (useCors) {\n server.adapter.setCors(server.serverApp, path, useCors);\n }\n}\n\n/**\n * \"block\" the previous version urls and send a 426 on them so that\n * the clients know they must update.\n */\nexport function blockPreviousVersionPaths(\n server: RxServer<any, any>,\n path: string,\n currentVersion: number\n\n) {\n let v = 0;\n while (v < currentVersion) {\n const version = v;\n server.adapter.all(server.serverApp, '/' + path + '/' + version + '/*', (req, res) => {\n server.adapter.closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');\n });\n v++;\n }\n}\n\n\nexport function addAuthMiddleware<AuthType>(\n server: RxServer<any, AuthType>,\n path: string,\n): WeakMap<Request, RxServerAuthData<AuthType>> {\n const authDataByRequest = new WeakMap<Request, RxServerAuthData<AuthType>>();\n async function auth(req: any, res: any, next: NextFunction) {\n try {\n const authData = await server.authHandler(req.headers);\n authDataByRequest.set(req, authData);\n next();\n } catch (err) {\n server.adapter.closeConnection(res, 401, 'Unauthorized');\n return;\n }\n }\n server.adapter.all(server.serverApp, '/' + path + '/*', auth);\n return authDataByRequest;\n}\n\nconst defaultMatchingQuery: FilledMangoQuery<any> = {\n selector: {},\n skip: 0,\n sort: []\n} as const;\n\nexport function getDocAllowedMatcher<RxDocType, AuthType>(\n endpoint: RxServerEndpoint<AuthType, RxDocType>,\n authData: RxServerAuthData<AuthType>\n) {\n const useQuery: FilledMangoQuery<RxDocType> = endpoint.queryModifier ? endpoint.queryModifier(\n authData,\n normalizeMangoQuery(\n endpoint.collection.schema.jsonSchema,\n {}\n )\n ) : defaultMatchingQuery;\n const docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);\n return docDataMatcher;\n}\n\n\nexport function docContainsServerOnlyFields(\n serverOnlyFields: string[],\n doc: any\n) {\n const has = serverOnlyFields.find(field => {\n return typeof doc[field] !== 'undefined'\n });\n return has;\n}\n\nexport function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n const serverOnlyFieldsStencil: any = {\n _meta: undefined,\n _rev: undefined,\n _attachments: undefined\n };\n serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);\n return (\n docData?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!docData) {\n return docData;\n }\n return Object.assign({}, docData, serverOnlyFieldsStencil);\n }\n}\n\nexport function mergeServerDocumentFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n let useFields = serverOnlyFields.slice(0);\n // useFields.push('_rev');\n // useFields.push('_meta');\n // useFields.push('_attachments');\n useFields = uniqueArray(useFields);\n\n return (\n clientDoc: RxDocType | RxDocumentData<RxDocType>,\n serverDoc?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!serverDoc) {\n return clientDoc;\n }\n const ret = flatClone(clientDoc);\n useFields.forEach(field => {\n (ret as any)[field] = (serverDoc as any)[field];\n });\n return ret;\n }\n}\n\n\n/**\n * $regex queries are dangerous because they can dos-attack the server.\n * \n * @param selector \n */\nexport function doesContainRegexQuerySelector(selector: MangoQuerySelector<any> | any): boolean {\n if (!selector) {\n return false;\n }\n if (Array.isArray(selector)) {\n const found = !!selector.find(item => doesContainRegexQuerySelector(item));\n return found;\n }\n\n if (typeof selector !== 'object') {\n return false;\n }\n\n const entries = Object.entries(selector);\n for (const [key, value] of entries) {\n if (key === '$regex') {\n return true;\n } else {\n const has = doesContainRegexQuerySelector(value);\n if (has) {\n return true;\n }\n }\n }\n\n return false;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"helper.js","names":["flatClone","getFromMapOrCreate","getQueryMatcher","normalizeMangoQuery","uniqueArray","setCors","server","path","cors","useCors","adapter","serverApp","blockPreviousVersionPaths","currentVersion","v","_loop","version","all","req","res","closeConnection","AUTH_PER_REQUEST","WeakMap","getAuthDataByRequest","request","response","headers","getRequestHeaders","authData","authHandler","err","defaultMatchingQuery","selector","skip","sort","getDocAllowedMatcher","endpoint","useQuery","queryModifier","collection","schema","jsonSchema","docDataMatcher","docContainsServerOnlyFields","serverOnlyFields","doc","has","find","field","removeServerOnlyFieldsMonad","serverOnlyFieldsStencil","_meta","undefined","_rev","_attachments","forEach","docData","Object","assign","mergeServerDocumentFieldsMonad","useFields","slice","clientDoc","serverDoc","ret","doesContainRegexQuerySelector","Array","isArray","found","item","entries","key","value"],"sources":["../../../../src/plugins/server/helper.ts"],"sourcesContent":["import { RxServer } from './rx-server';\nimport type {\n Request,\n Response,\n NextFunction\n} from 'express';\nimport type { RxServerAdapter, RxServerAuthData, RxServerEndpoint } from './types';\nimport {\n FilledMangoQuery,\n MangoQuerySelector,\n RxDocumentData,\n flatClone,\n getFromMapOrCreate,\n getQueryMatcher,\n normalizeMangoQuery,\n uniqueArray\n} from 'rxdb/plugins/core';\n\nexport function setCors(\n server: RxServer<any, any>,\n path: string,\n cors?: string\n) {\n let useCors = cors;\n if (!useCors) {\n useCors = server.cors;\n }\n if (useCors) {\n server.adapter.setCors(server.serverApp, path, useCors);\n }\n}\n\n/**\n * \"block\" the previous version urls and send a 426 on them so that\n * the clients know they must update.\n */\nexport function blockPreviousVersionPaths(\n server: RxServer<any, any>,\n path: string,\n currentVersion: number\n\n) {\n let v = 0;\n while (v < currentVersion) {\n const version = v;\n server.adapter.all(server.serverApp, '/' + path + '/' + version + '/*', (req, res) => {\n server.adapter.closeConnection(res, 426, 'Outdated version ' + version + ' (newest is ' + currentVersion + ')');\n });\n v++;\n }\n}\n\n\n\nconst AUTH_PER_REQUEST = new WeakMap<any, Promise<any>>();\n\nexport async function getAuthDataByRequest<AuthType, RequestType, ResponseType>(\n server: RxServer<any, AuthType>,\n request: RequestType,\n response: ResponseType\n): Promise<RxServerAuthData<AuthType> | false> {\n return getFromMapOrCreate(\n AUTH_PER_REQUEST,\n request,\n async () => {\n try {\n const headers = server.adapter.getRequestHeaders(request);\n const authData = await server.authHandler(headers);\n return authData;\n } catch (err) {\n server.adapter.closeConnection(response, 401, 'Unauthorized');\n return false;\n }\n }\n );\n};\n\nconst defaultMatchingQuery: FilledMangoQuery<any> = {\n selector: {},\n skip: 0,\n sort: []\n} as const;\n\nexport function getDocAllowedMatcher<RxDocType, AuthType>(\n endpoint: RxServerEndpoint<AuthType, RxDocType>,\n authData: RxServerAuthData<AuthType>\n) {\n const useQuery: FilledMangoQuery<RxDocType> = endpoint.queryModifier ? endpoint.queryModifier(\n authData,\n normalizeMangoQuery(\n endpoint.collection.schema.jsonSchema,\n {}\n )\n ) : defaultMatchingQuery;\n const docDataMatcher = getQueryMatcher(endpoint.collection.schema.jsonSchema, useQuery);\n return docDataMatcher;\n}\n\n\nexport function docContainsServerOnlyFields(\n serverOnlyFields: string[],\n doc: any\n) {\n const has = serverOnlyFields.find(field => {\n return typeof doc[field] !== 'undefined'\n });\n return has;\n}\n\nexport function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n const serverOnlyFieldsStencil: any = {\n _meta: undefined,\n _rev: undefined,\n _attachments: undefined\n };\n serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);\n return (\n docData?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!docData) {\n return docData;\n }\n return Object.assign({}, docData, serverOnlyFieldsStencil);\n }\n}\n\nexport function mergeServerDocumentFieldsMonad<RxDocType>(serverOnlyFields: string[]) {\n let useFields = serverOnlyFields.slice(0);\n // useFields.push('_rev');\n // useFields.push('_meta');\n // useFields.push('_attachments');\n useFields = uniqueArray(useFields);\n\n return (\n clientDoc: RxDocType | RxDocumentData<RxDocType>,\n serverDoc?: RxDocType | RxDocumentData<RxDocType>\n ) => {\n if (!serverDoc) {\n return clientDoc;\n }\n const ret = flatClone(clientDoc);\n useFields.forEach(field => {\n (ret as any)[field] = (serverDoc as any)[field];\n });\n return ret;\n }\n}\n\n\n/**\n * $regex queries are dangerous because they can dos-attack the server.\n * \n * @param selector \n */\nexport function doesContainRegexQuerySelector(selector: MangoQuerySelector<any> | any): boolean {\n if (!selector) {\n return false;\n }\n if (Array.isArray(selector)) {\n const found = !!selector.find(item => doesContainRegexQuerySelector(item));\n return found;\n }\n\n if (typeof selector !== 'object') {\n return false;\n }\n\n const entries = Object.entries(selector);\n for (const [key, value] of entries) {\n if (key === '$regex') {\n return true;\n } else {\n const has = doesContainRegexQuerySelector(value);\n if (has) {\n return true;\n }\n }\n }\n\n return false;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,5 +1,4 @@
1
1
  import { RxServer } from './rx-server';
2
- import type { Request } from 'express';
3
2
  import type { RxServerAuthData, RxServerEndpoint } from './types';
4
3
  import { MangoQuerySelector, RxDocumentData } from 'rxdb/plugins/core';
5
4
  export declare function setCors(server: RxServer<any, any>, path: string, cors?: string): void;
@@ -8,7 +7,7 @@ export declare function setCors(server: RxServer<any, any>, path: string, cors?:
8
7
  * the clients know they must update.
9
8
  */
10
9
  export declare function blockPreviousVersionPaths(server: RxServer<any, any>, path: string, currentVersion: number): void;
11
- export declare function addAuthMiddleware<AuthType>(server: RxServer<any, AuthType>, path: string): WeakMap<Request, RxServerAuthData<AuthType>>;
10
+ export declare function getAuthDataByRequest<AuthType, RequestType, ResponseType>(server: RxServer<any, AuthType>, request: RequestType, response: ResponseType): Promise<RxServerAuthData<AuthType> | false>;
12
11
  export declare function getDocAllowedMatcher<RxDocType, AuthType>(endpoint: RxServerEndpoint<AuthType, RxDocType>, authData: RxServerAuthData<AuthType>): import("rxdb/plugins/core").QueryMatcher<RxDocumentData<RxDocType>>;
13
12
  export declare function docContainsServerOnlyFields(serverOnlyFields: string[], doc: any): string | undefined;
14
13
  export declare function removeServerOnlyFieldsMonad<RxDocType>(serverOnlyFields: string[]): (docData?: RxDocType | RxDocumentData<RxDocType>) => any;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rxdb-server",
3
- "version": "15.13.1",
3
+ "version": "15.13.3",
4
4
  "description": "RxDB Server Plugin",
5
5
  "license": "SSPL",
6
6
  "author": "pubkey",
@@ -131,7 +131,7 @@
131
131
  "minify-all-js": "0.1.9",
132
132
  "mocha": "10.3.0",
133
133
  "rimraf": "5.0.5",
134
- "rxdb": "15.13.1",
134
+ "rxdb": "15.13.3",
135
135
  "rxjs": "7.8.1",
136
136
  "ts-loader": "9.5.1",
137
137
  "ts-mocha": "10.0.0",