rxdb-server
Version:
RxDB Server Plugin
157 lines (154 loc) • 5.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.docContainsServerOnlyFields = docContainsServerOnlyFields;
exports.doesContainRegexQuerySelector = doesContainRegexQuerySelector;
exports.getAuthDataByRequest = getAuthDataByRequest;
exports.getDocAllowedMatcher = getDocAllowedMatcher;
exports.mergeServerDocumentFieldsMonad = mergeServerDocumentFieldsMonad;
exports.removeServerOnlyFieldsMonad = removeServerOnlyFieldsMonad;
exports.setCors = setCors;
exports.stripServerOnlyFieldsMonad = stripServerOnlyFieldsMonad;
var _core = require("rxdb/plugins/core");
function setCors(server, path, cors) {
var useCors = cors;
if (!useCors) {
useCors = server.cors;
}
if (useCors) {
server.adapter.setCors(server.serverApp, path, useCors);
}
}
var AUTH_PER_REQUEST = new WeakMap();
async function getAuthDataByRequest(server, request, response) {
return (0, _core.getFromMapOrCreate)(AUTH_PER_REQUEST, request, async () => {
try {
var headers = server.adapter.getRequestHeaders(request);
var authData = await server.authHandler(headers);
return authData;
} catch (err) {
server.adapter.closeConnection(response, 401, 'Unauthorized');
return false;
}
});
}
;
var defaultMatchingQuery = {
selector: {},
skip: 0,
sort: []
};
function getDocAllowedMatcher(endpoint, authData) {
var useQuery = endpoint.queryModifier ? endpoint.queryModifier(authData, (0, _core.normalizeMangoQuery)(endpoint.collection.schema.jsonSchema, {})) : defaultMatchingQuery;
var docDataMatcher = (0, _core.getQueryMatcher)(endpoint.collection.schema.jsonSchema, useQuery);
return docDataMatcher;
}
function docContainsServerOnlyFields(serverOnlyFields, doc) {
var has = serverOnlyFields.find(field => {
return typeof doc[field] !== 'undefined';
});
return has;
}
/**
* Returns a function that strips the given server-only fields from a client
* document. This is used when accepting a NEW document from a client write to
* make sure that server-only fields cannot be populated by the client.
*
* Unlike {@link removeServerOnlyFieldsMonad} this does not assign undefined to
* RxDB internal meta fields (`_meta`, `_rev`, `_attachments`) so the result can
* be safely passed to `RxCollection.insert()`.
*/
function stripServerOnlyFieldsMonad(serverOnlyFields) {
if (serverOnlyFields.length === 0) {
return docData => docData;
}
return docData => {
var ret = (0, _core.flatClone)(docData);
for (var i = 0; i < serverOnlyFields.length; i++) {
delete ret[serverOnlyFields[i]];
}
return ret;
};
}
function removeServerOnlyFieldsMonad(serverOnlyFields) {
var serverOnlyFieldsStencil = {
_meta: undefined,
_rev: undefined,
_attachments: undefined
};
serverOnlyFields.forEach(field => serverOnlyFieldsStencil[field] = undefined);
return docData => {
if (!docData) {
return docData;
}
return Object.assign({}, docData, serverOnlyFieldsStencil);
};
}
function mergeServerDocumentFieldsMonad(serverOnlyFields) {
var useFields = serverOnlyFields.slice(0);
// useFields.push('_rev');
// useFields.push('_meta');
// useFields.push('_attachments');
useFields = (0, _core.uniqueArray)(useFields);
return (clientDoc, serverDoc) => {
if (!clientDoc) {
return clientDoc;
}
var ret = (0, _core.flatClone)(clientDoc);
if (!serverDoc) {
// No prior server-side state exists for this document (new
// insert). The client must not be able to populate server-only
// fields on creation, so strip them from the merged document.
useFields.forEach(field => delete ret[field]);
return ret;
}
useFields.forEach(field => {
/**
* If the field exists on the serverDoc, copy its value so that
* the server-side value always wins over anything the client
* sent. If it does not exist on the serverDoc, delete it from
* the merged document so the key is truly absent — using `null`
* here would make the merged row differ from the stored master
* state during the isEqual check inside masterWrite and
* produce a false conflict that silently reverts the write.
*/
if (field in serverDoc) {
ret[field] = serverDoc[field];
} else {
delete ret[field];
}
});
return ret;
};
}
/**
* $regex queries are dangerous because they can dos-attack the server.
*
* @param selector
*/
function doesContainRegexQuerySelector(selector) {
if (!selector) {
return false;
}
if (Array.isArray(selector)) {
var found = !!selector.find(item => doesContainRegexQuerySelector(item));
return found;
}
if (typeof selector !== 'object') {
return false;
}
var entries = Object.entries(selector);
for (var [key, value] of entries) {
if (key === '$regex') {
return true;
} else {
var has = doesContainRegexQuerySelector(value);
if (has) {
return true;
}
}
}
return false;
}
//# sourceMappingURL=helper.js.map