123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _Options = require("./Options");
- var _defaults = _interopRequireDefault(require("./defaults"));
- var logging = _interopRequireWildcard(require("./logger"));
- var _Config = _interopRequireDefault(require("./Config"));
- var _PromiseRouter = _interopRequireDefault(require("./PromiseRouter"));
- var _requiredParameter = _interopRequireDefault(require("./requiredParameter"));
- var _AnalyticsRouter = require("./Routers/AnalyticsRouter");
- var _ClassesRouter = require("./Routers/ClassesRouter");
- var _FeaturesRouter = require("./Routers/FeaturesRouter");
- var _FilesRouter = require("./Routers/FilesRouter");
- var _FunctionsRouter = require("./Routers/FunctionsRouter");
- var _GlobalConfigRouter = require("./Routers/GlobalConfigRouter");
- var _GraphQLRouter = require("./Routers/GraphQLRouter");
- var _HooksRouter = require("./Routers/HooksRouter");
- var _IAPValidationRouter = require("./Routers/IAPValidationRouter");
- var _InstallationsRouter = require("./Routers/InstallationsRouter");
- var _LogsRouter = require("./Routers/LogsRouter");
- var _ParseLiveQueryServer = require("./LiveQuery/ParseLiveQueryServer");
- var _PagesRouter = require("./Routers/PagesRouter");
- var _PublicAPIRouter = require("./Routers/PublicAPIRouter");
- var _PushRouter = require("./Routers/PushRouter");
- var _CloudCodeRouter = require("./Routers/CloudCodeRouter");
- var _RolesRouter = require("./Routers/RolesRouter");
- var _SchemasRouter = require("./Routers/SchemasRouter");
- var _SessionsRouter = require("./Routers/SessionsRouter");
- var _UsersRouter = require("./Routers/UsersRouter");
- var _PurgeRouter = require("./Routers/PurgeRouter");
- var _AudiencesRouter = require("./Routers/AudiencesRouter");
- var _AggregateRouter = require("./Routers/AggregateRouter");
- var _ParseServerRESTController = require("./ParseServerRESTController");
- var controllers = _interopRequireWildcard(require("./Controllers"));
- var _ParseGraphQLServer = require("./GraphQL/ParseGraphQLServer");
- var _SecurityRouter = require("./Routers/SecurityRouter");
- var _CheckRunner = _interopRequireDefault(require("./Security/CheckRunner"));
- var _Deprecator = _interopRequireDefault(require("./Deprecator/Deprecator"));
- var _DefinedSchemas = require("./SchemaMigrations/DefinedSchemas");
- var _Definitions = _interopRequireDefault(require("./Options/Definitions"));
- function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
- function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
- var batch = require('./batch'),
- bodyParser = require('body-parser'),
- express = require('express'),
- middlewares = require('./middlewares'),
- Parse = require('parse/node').Parse,
- {
- parse
- } = require('graphql'),
- path = require('path'),
- fs = require('fs');
- addParseCloud();
- class ParseServer {
-
- constructor(options) {
-
- _Deprecator.default.scanParseServerOptions(options);
- const interfaces = JSON.parse(JSON.stringify(_Definitions.default));
- function getValidObject(root) {
- const result = {};
- for (const key in root) {
- if (Object.prototype.hasOwnProperty.call(root[key], 'type')) {
- if (root[key].type.endsWith('[]')) {
- result[key] = [getValidObject(interfaces[root[key].type.slice(0, -2)])];
- } else {
- result[key] = getValidObject(interfaces[root[key].type]);
- }
- } else {
- result[key] = '';
- }
- }
- return result;
- }
- const optionsBlueprint = getValidObject(interfaces['ParseServerOptions']);
- function validateKeyNames(original, ref, name = '') {
- let result = [];
- const prefix = name + (name !== '' ? '.' : '');
- for (const key in original) {
- if (!Object.prototype.hasOwnProperty.call(ref, key)) {
- result.push(prefix + key);
- } else {
- if (ref[key] === '') continue;
- let res = [];
- if (Array.isArray(original[key]) && Array.isArray(ref[key])) {
- const type = ref[key][0];
- original[key].forEach((item, idx) => {
- if (typeof item === 'object' && item !== null) {
- res = res.concat(validateKeyNames(item, type, prefix + key + `[${idx}]`));
- }
- });
- } else if (typeof original[key] === 'object' && typeof ref[key] === 'object') {
- res = validateKeyNames(original[key], ref[key], prefix + key);
- }
- result = result.concat(res);
- }
- }
- return result;
- }
- const diff = validateKeyNames(options, optionsBlueprint);
- if (diff.length > 0) {
- const logger = logging.logger;
- logger.error(`Invalid key(s) found in Parse Server configuration: ${diff.join(', ')}`);
- }
-
- injectDefaults(options);
- const {
- appId = (0, _requiredParameter.default)('You must provide an appId!'),
- masterKey = (0, _requiredParameter.default)('You must provide a masterKey!'),
- javascriptKey,
- serverURL = (0, _requiredParameter.default)('You must provide a serverURL!')
- } = options;
-
- Parse.initialize(appId, javascriptKey || 'unused', masterKey);
- Parse.serverURL = serverURL;
- _Config.default.validateOptions(options);
- const allControllers = controllers.getControllers(options);
- options.state = 'initialized';
- this.config = _Config.default.put(Object.assign({}, options, allControllers));
- this.config.masterKeyIpsStore = new Map();
- this.config.maintenanceKeyIpsStore = new Map();
- logging.setLogger(allControllers.loggerController);
- }
-
- async start() {
- try {
- var _cacheController$adap;
- if (this.config.state === 'ok') {
- return this;
- }
- this.config.state = 'starting';
- _Config.default.put(this.config);
- const {
- databaseController,
- hooksController,
- cacheController,
- cloud,
- security,
- schema,
- liveQueryController
- } = this.config;
- try {
- await databaseController.performInitialization();
- } catch (e) {
- if (e.code !== Parse.Error.DUPLICATE_VALUE) {
- throw e;
- }
- }
- const pushController = await controllers.getPushController(this.config);
- await hooksController.load();
- const startupPromises = [];
- if (schema) {
- startupPromises.push(new _DefinedSchemas.DefinedSchemas(schema, this.config).execute());
- }
- if ((_cacheController$adap = cacheController.adapter) !== null && _cacheController$adap !== void 0 && _cacheController$adap.connect && typeof cacheController.adapter.connect === 'function') {
- startupPromises.push(cacheController.adapter.connect());
- }
- startupPromises.push(liveQueryController.connect());
- await Promise.all(startupPromises);
- if (cloud) {
- addParseCloud();
- if (typeof cloud === 'function') {
- await Promise.resolve(cloud(Parse));
- } else if (typeof cloud === 'string') {
- var _json;
- let json;
- if (process.env.npm_package_json) {
- json = require(process.env.npm_package_json);
- }
- if (process.env.npm_package_type === 'module' || ((_json = json) === null || _json === void 0 ? void 0 : _json.type) === 'module') {
- await import(path.resolve(process.cwd(), cloud));
- } else {
- require(path.resolve(process.cwd(), cloud));
- }
- } else {
- throw "argument 'cloud' must either be a string or a function";
- }
- await new Promise(resolve => setTimeout(resolve, 10));
- }
- if (security && security.enableCheck && security.enableCheckLog) {
- new _CheckRunner.default(security).run();
- }
- this.config.state = 'ok';
- this.config = _objectSpread(_objectSpread({}, this.config), pushController);
- _Config.default.put(this.config);
- return this;
- } catch (error) {
- console.error(error);
- this.config.state = 'error';
- throw error;
- }
- }
- get app() {
- if (!this._app) {
- this._app = ParseServer.app(this.config);
- }
- return this._app;
- }
- handleShutdown() {
- var _this$liveQueryServer;
- const promises = [];
- const {
- adapter: databaseAdapter
- } = this.config.databaseController;
- if (databaseAdapter && typeof databaseAdapter.handleShutdown === 'function') {
- promises.push(databaseAdapter.handleShutdown());
- }
- const {
- adapter: fileAdapter
- } = this.config.filesController;
- if (fileAdapter && typeof fileAdapter.handleShutdown === 'function') {
- promises.push(fileAdapter.handleShutdown());
- }
- const {
- adapter: cacheAdapter
- } = this.config.cacheController;
- if (cacheAdapter && typeof cacheAdapter.handleShutdown === 'function') {
- promises.push(cacheAdapter.handleShutdown());
- }
- if ((_this$liveQueryServer = this.liveQueryServer) !== null && _this$liveQueryServer !== void 0 && (_this$liveQueryServer = _this$liveQueryServer.server) !== null && _this$liveQueryServer !== void 0 && _this$liveQueryServer.close) {
- promises.push(new Promise(resolve => this.liveQueryServer.server.close(resolve)));
- }
- if (this.liveQueryServer) {
- promises.push(this.liveQueryServer.shutdown());
- }
- return (promises.length > 0 ? Promise.all(promises) : Promise.resolve()).then(() => {
- if (this.config.serverCloseComplete) {
- this.config.serverCloseComplete();
- }
- });
- }
-
- static app(options) {
- const {
- maxUploadSize = '20mb',
- appId,
- directAccess,
- pages,
- rateLimit = []
- } = options;
-
-
- var api = express();
-
- api.use(middlewares.allowCrossDomain(appId));
-
- api.use('/', new _FilesRouter.FilesRouter().expressRouter({
- maxUploadSize: maxUploadSize
- }));
- api.use('/health', function (req, res) {
- res.status(options.state === 'ok' ? 200 : 503);
- if (options.state === 'starting') {
- res.set('Retry-After', 1);
- }
- res.json({
- status: options.state
- });
- });
- api.use('/', bodyParser.urlencoded({
- extended: false
- }), pages.enableRouter ? new _PagesRouter.PagesRouter(pages).expressRouter() : new _PublicAPIRouter.PublicAPIRouter().expressRouter());
- api.use(bodyParser.json({
- type: '*/*',
- limit: maxUploadSize
- }));
- api.use(middlewares.allowMethodOverride);
- api.use(middlewares.handleParseHeaders);
- const routes = Array.isArray(rateLimit) ? rateLimit : [rateLimit];
- for (const route of routes) {
- middlewares.addRateLimit(route, options);
- }
- api.use(middlewares.handleParseSession);
- const appRouter = ParseServer.promiseRouter({
- appId
- });
- api.use(appRouter.expressRouter());
- api.use(middlewares.handleParseErrors);
-
- if (!process.env.TESTING) {
-
-
- process.on('uncaughtException', err => {
- if (err.code === 'EADDRINUSE') {
-
- process.stderr.write(`Unable to listen on port ${err.port}. The port is already in use.`);
- process.exit(0);
- } else {
- if (err.message) {
- process.stderr.write('An uncaught exception occurred: ' + err.message);
- }
- if (err.stack) {
- process.stderr.write('Stack Trace:\n' + err.stack);
- } else {
- process.stderr.write(err);
- }
- process.exit(1);
- }
- });
-
-
- api.on('mount', async function () {
- await new Promise(resolve => setTimeout(resolve, 1000));
- ParseServer.verifyServerUrl();
- });
- }
- if (process.env.PARSE_SERVER_ENABLE_EXPERIMENTAL_DIRECT_ACCESS === '1' || directAccess) {
- Parse.CoreManager.setRESTController((0, _ParseServerRESTController.ParseServerRESTController)(appId, appRouter));
- }
- return api;
- }
- static promiseRouter({
- appId
- }) {
- const routers = [new _ClassesRouter.ClassesRouter(), new _UsersRouter.UsersRouter(), new _SessionsRouter.SessionsRouter(), new _RolesRouter.RolesRouter(), new _AnalyticsRouter.AnalyticsRouter(), new _InstallationsRouter.InstallationsRouter(), new _FunctionsRouter.FunctionsRouter(), new _SchemasRouter.SchemasRouter(), new _PushRouter.PushRouter(), new _LogsRouter.LogsRouter(), new _IAPValidationRouter.IAPValidationRouter(), new _FeaturesRouter.FeaturesRouter(), new _GlobalConfigRouter.GlobalConfigRouter(), new _GraphQLRouter.GraphQLRouter(), new _PurgeRouter.PurgeRouter(), new _HooksRouter.HooksRouter(), new _CloudCodeRouter.CloudCodeRouter(), new _AudiencesRouter.AudiencesRouter(), new _AggregateRouter.AggregateRouter(), new _SecurityRouter.SecurityRouter()];
- const routes = routers.reduce((memo, router) => {
- return memo.concat(router.routes);
- }, []);
- const appRouter = new _PromiseRouter.default(routes, appId);
- batch.mountOnto(appRouter);
- return appRouter;
- }
-
- async startApp(options) {
- try {
- await this.start();
- } catch (e) {
- console.error('Error on ParseServer.startApp: ', e);
- throw e;
- }
- const app = express();
- if (options.middleware) {
- let middleware;
- if (typeof options.middleware == 'string') {
- middleware = require(path.resolve(process.cwd(), options.middleware));
- } else {
- middleware = options.middleware;
- }
- app.use(middleware);
- }
- app.use(options.mountPath, this.app);
- if (options.mountGraphQL === true || options.mountPlayground === true) {
- let graphQLCustomTypeDefs = undefined;
- if (typeof options.graphQLSchema === 'string') {
- graphQLCustomTypeDefs = parse(fs.readFileSync(options.graphQLSchema, 'utf8'));
- } else if (typeof options.graphQLSchema === 'object' || typeof options.graphQLSchema === 'function') {
- graphQLCustomTypeDefs = options.graphQLSchema;
- }
- const parseGraphQLServer = new _ParseGraphQLServer.ParseGraphQLServer(this, {
- graphQLPath: options.graphQLPath,
- playgroundPath: options.playgroundPath,
- graphQLCustomTypeDefs
- });
- if (options.mountGraphQL) {
- parseGraphQLServer.applyGraphQL(app);
- }
- if (options.mountPlayground) {
- parseGraphQLServer.applyPlayground(app);
- }
- }
- const server = await new Promise(resolve => {
- app.listen(options.port, options.host, function () {
- resolve(this);
- });
- });
- this.server = server;
- if (options.startLiveQueryServer || options.liveQueryServerOptions) {
- this.liveQueryServer = await ParseServer.createLiveQueryServer(server, options.liveQueryServerOptions, options);
- }
- if (options.trustProxy) {
- app.set('trust proxy', options.trustProxy);
- }
-
- if (!process.env.TESTING) {
- configureListeners(this);
- }
- this.expressApp = app;
- return this;
- }
-
- static async startApp(options) {
- const parseServer = new ParseServer(options);
- return parseServer.startApp(options);
- }
-
- static async createLiveQueryServer(httpServer, config, options) {
- if (!httpServer || config && config.port) {
- var app = express();
- httpServer = require('http').createServer(app);
- httpServer.listen(config.port);
- }
- const server = new _ParseLiveQueryServer.ParseLiveQueryServer(httpServer, config, options);
- await server.connect();
- return server;
- }
- static async verifyServerUrl() {
-
- if (Parse.serverURL) {
- var _response$headers;
- const isValidHttpUrl = string => {
- let url;
- try {
- url = new URL(string);
- } catch (_) {
- return false;
- }
- return url.protocol === 'http:' || url.protocol === 'https:';
- };
- const url = `${Parse.serverURL.replace(/\/$/, '')}/health`;
- if (!isValidHttpUrl(url)) {
- console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}' as the URL is invalid.` + ` Cloud code and push notifications may be unavailable!\n`);
- return;
- }
- const request = require('./request');
- const response = await request({
- url
- }).catch(response => response);
- const json = response.data || null;
- const retry = (_response$headers = response.headers) === null || _response$headers === void 0 ? void 0 : _response$headers['retry-after'];
- if (retry) {
- await new Promise(resolve => setTimeout(resolve, retry * 1000));
- return this.verifyServerUrl();
- }
- if (response.status !== 200 || (json === null || json === void 0 ? void 0 : json.status) !== 'ok') {
-
- console.warn(`\nWARNING, Unable to connect to '${Parse.serverURL}'.` + ` Cloud code and push notifications may be unavailable!\n`);
-
- return;
- }
- return true;
- }
- }
- }
- function addParseCloud() {
- const ParseCloud = require('./cloud-code/Parse.Cloud');
- const ParseServer = require('./cloud-code/Parse.Server');
- Object.defineProperty(Parse, 'Server', {
- get() {
- const conf = _Config.default.get(Parse.applicationId);
- return _objectSpread(_objectSpread({}, conf), ParseServer);
- },
- set(newVal) {
- newVal.appId = Parse.applicationId;
- _Config.default.put(newVal);
- },
- configurable: true
- });
- Object.assign(Parse.Cloud, ParseCloud);
- global.Parse = Parse;
- }
- function injectDefaults(options) {
- Object.keys(_defaults.default).forEach(key => {
- if (!Object.prototype.hasOwnProperty.call(options, key)) {
- options[key] = _defaults.default[key];
- }
- });
- if (!Object.prototype.hasOwnProperty.call(options, 'serverURL')) {
- options.serverURL = `http://localhost:${options.port}${options.mountPath}`;
- }
-
- if (options.appId) {
- const regex = /[!#$%'()*+&/:;=?@[\]{}^,|<>]/g;
- if (options.appId.match(regex)) {
- console.warn(`\nWARNING, appId that contains special characters can cause issues while using with urls.\n`);
- }
- }
-
- if (options.userSensitiveFields) {
-
- !process.env.TESTING && console.warn(`\nDEPRECATED: userSensitiveFields has been replaced by protectedFields allowing the ability to protect fields in all classes with CLP. \n`);
-
- const userSensitiveFields = Array.from(new Set([...(_defaults.default.userSensitiveFields || []), ...(options.userSensitiveFields || [])]));
-
-
-
-
- if (!('_User' in options.protectedFields)) {
- options.protectedFields = Object.assign({
- _User: []
- }, options.protectedFields);
- }
- options.protectedFields['_User']['*'] = Array.from(new Set([...(options.protectedFields['_User']['*'] || []), ...userSensitiveFields]));
- }
-
- Object.keys(_defaults.default.protectedFields).forEach(c => {
- const cur = options.protectedFields[c];
- if (!cur) {
- options.protectedFields[c] = _defaults.default.protectedFields[c];
- } else {
- Object.keys(_defaults.default.protectedFields[c]).forEach(r => {
- const unq = new Set([...(options.protectedFields[c][r] || []), ..._defaults.default.protectedFields[c][r]]);
- options.protectedFields[c][r] = Array.from(unq);
- });
- }
- });
- }
- function configureListeners(parseServer) {
- const server = parseServer.server;
- const sockets = {};
-
- server.on('connection', socket => {
- const socketId = socket.remoteAddress + ':' + socket.remotePort;
- sockets[socketId] = socket;
- socket.on('close', () => {
- delete sockets[socketId];
- });
- });
- const destroyAliveConnections = function () {
- for (const socketId in sockets) {
- try {
- sockets[socketId].destroy();
- } catch (e) {
-
- }
- }
- };
- const handleShutdown = function () {
- process.stdout.write('Termination signal received. Shutting down.');
- destroyAliveConnections();
- server.close();
- parseServer.handleShutdown();
- };
- process.on('SIGTERM', handleShutdown);
- process.on('SIGINT', handleShutdown);
- }
- var _default = exports.default = ParseServer;
|