1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.default = void 0;
- var _RestQuery = _interopRequireDefault(require("./RestQuery"));
- var _lodash = _interopRequireDefault(require("lodash"));
- var _logger = _interopRequireDefault(require("./logger"));
- var _SchemaController = require("./Controllers/SchemaController");
- 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 SchemaController = require('./Controllers/SchemaController');
- var deepcopy = require('deepcopy');
- const Auth = require('./Auth');
- const Utils = require('./Utils');
- var cryptoUtils = require('./cryptoUtils');
- var passwordCrypto = require('./password');
- var Parse = require('parse/node');
- var triggers = require('./triggers');
- var ClientSDK = require('./ClientSDK');
- const util = require('util');
- function RestWrite(config, auth, className, query, data, originalData, clientSDK, context, action) {
- if (auth.isReadOnly) {
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Cannot perform a write operation when using readOnlyMasterKey');
- }
- this.config = config;
- this.auth = auth;
- this.className = className;
- this.clientSDK = clientSDK;
- this.storage = {};
- this.runOptions = {};
- this.context = context || {};
- if (action) {
- this.runOptions.action = action;
- }
- if (!query) {
- if (this.config.allowCustomObjectId) {
- if (Object.prototype.hasOwnProperty.call(data, 'objectId') && !data.objectId) {
- throw new Parse.Error(Parse.Error.MISSING_OBJECT_ID, 'objectId must not be empty, null or undefined');
- }
- } else {
- if (data.objectId) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'objectId is an invalid field name.');
- }
- if (data.id) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'id is an invalid field name.');
- }
- }
- }
-
-
-
-
-
- this.response = null;
-
-
- this.query = deepcopy(query);
- this.data = deepcopy(data);
-
- this.originalData = originalData;
-
- this.updatedAt = Parse._encode(new Date()).iso;
-
-
- this.validSchemaController = null;
- this.pendingOps = {
- operations: null,
- identifier: null
- };
- }
- RestWrite.prototype.execute = function () {
- return Promise.resolve().then(() => {
- return this.getUserAndRoleACL();
- }).then(() => {
- return this.validateClientClassCreation();
- }).then(() => {
- return this.handleInstallation();
- }).then(() => {
- return this.handleSession();
- }).then(() => {
- return this.validateAuthData();
- }).then(() => {
- return this.checkRestrictedFields();
- }).then(() => {
- return this.runBeforeSaveTrigger();
- }).then(() => {
- return this.ensureUniqueAuthDataId();
- }).then(() => {
- return this.deleteEmailResetTokenIfNeeded();
- }).then(() => {
- return this.validateSchema();
- }).then(schemaController => {
- this.validSchemaController = schemaController;
- return this.setRequiredFieldsIfNeeded();
- }).then(() => {
- return this.transformUser();
- }).then(() => {
- return this.expandFilesForExistingObjects();
- }).then(() => {
- return this.destroyDuplicatedSessions();
- }).then(() => {
- return this.runDatabaseOperation();
- }).then(() => {
- return this.createSessionTokenIfNeeded();
- }).then(() => {
- return this.handleFollowup();
- }).then(() => {
- return this.runAfterSaveTrigger();
- }).then(() => {
- return this.cleanUserAuthData();
- }).then(() => {
-
- if (this.authDataResponse) {
- if (this.response && this.response.response) {
- this.response.response.authDataResponse = this.authDataResponse;
- }
- }
- if (this.storage.rejectSignup && this.config.preventSignupWithUnverifiedEmail) {
- throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.');
- }
- return this.response;
- });
- };
- RestWrite.prototype.getUserAndRoleACL = function () {
- if (this.auth.isMaster || this.auth.isMaintenance) {
- return Promise.resolve();
- }
- this.runOptions.acl = ['*'];
- if (this.auth.user) {
- return this.auth.getUserRoles().then(roles => {
- this.runOptions.acl = this.runOptions.acl.concat(roles, [this.auth.user.id]);
- return;
- });
- } else {
- return Promise.resolve();
- }
- };
- RestWrite.prototype.validateClientClassCreation = function () {
- if (this.config.allowClientClassCreation === false && !this.auth.isMaster && !this.auth.isMaintenance && SchemaController.systemClasses.indexOf(this.className) === -1) {
- return this.config.database.loadSchema().then(schemaController => schemaController.hasClass(this.className)).then(hasClass => {
- if (hasClass !== true) {
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'This user is not allowed to access ' + 'non-existent class: ' + this.className);
- }
- });
- } else {
- return Promise.resolve();
- }
- };
- RestWrite.prototype.validateSchema = function () {
- return this.config.database.validateObject(this.className, this.data, this.query, this.runOptions, this.auth.isMaintenance);
- };
- RestWrite.prototype.runBeforeSaveTrigger = function () {
- if (this.response || this.runOptions.many) {
- return;
- }
-
- if (!triggers.triggerExists(this.className, triggers.Types.beforeSave, this.config.applicationId)) {
- return Promise.resolve();
- }
- const {
- originalObject,
- updatedObject
- } = this.buildParseObjects();
- const identifier = updatedObject._getStateIdentifier();
- const stateController = Parse.CoreManager.getObjectStateController();
- const [pending] = stateController.getPendingOps(identifier);
- this.pendingOps = {
- operations: _objectSpread({}, pending),
- identifier
- };
- return Promise.resolve().then(() => {
-
- let databasePromise = null;
- if (this.query) {
-
- databasePromise = this.config.database.update(this.className, this.query, this.data, this.runOptions, true, true);
- } else {
-
- databasePromise = this.config.database.create(this.className, this.data, this.runOptions, true);
- }
-
- return databasePromise.then(result => {
- if (!result || result.length <= 0) {
- throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found.');
- }
- });
- }).then(() => {
- return triggers.maybeRunTrigger(triggers.Types.beforeSave, this.auth, updatedObject, originalObject, this.config, this.context);
- }).then(response => {
- if (response && response.object) {
- this.storage.fieldsChangedByTrigger = _lodash.default.reduce(response.object, (result, value, key) => {
- if (!_lodash.default.isEqual(this.data[key], value)) {
- result.push(key);
- }
- return result;
- }, []);
- this.data = response.object;
-
- if (this.query && this.query.objectId) {
- delete this.data.objectId;
- }
- }
- try {
- Utils.checkProhibitedKeywords(this.config, this.data);
- } catch (error) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, error);
- }
- });
- };
- RestWrite.prototype.runBeforeLoginTrigger = async function (userData) {
-
- if (!triggers.triggerExists(this.className, triggers.Types.beforeLogin, this.config.applicationId)) {
- return;
- }
-
- const extraData = {
- className: this.className
- };
-
- await this.config.filesController.expandFilesInObject(this.config, userData);
- const user = triggers.inflate(extraData, userData);
-
- await triggers.maybeRunTrigger(triggers.Types.beforeLogin, this.auth, user, null, this.config, this.context);
- };
- RestWrite.prototype.setRequiredFieldsIfNeeded = function () {
- if (this.data) {
- return this.validSchemaController.getAllClasses().then(allClasses => {
- const schema = allClasses.find(oneClass => oneClass.className === this.className);
- const setRequiredFieldIfNeeded = (fieldName, setDefault) => {
- if (this.data[fieldName] === undefined || this.data[fieldName] === null || this.data[fieldName] === '' || typeof this.data[fieldName] === 'object' && this.data[fieldName].__op === 'Delete') {
- if (setDefault && schema.fields[fieldName] && schema.fields[fieldName].defaultValue !== null && schema.fields[fieldName].defaultValue !== undefined && (this.data[fieldName] === undefined || typeof this.data[fieldName] === 'object' && this.data[fieldName].__op === 'Delete')) {
- this.data[fieldName] = schema.fields[fieldName].defaultValue;
- this.storage.fieldsChangedByTrigger = this.storage.fieldsChangedByTrigger || [];
- if (this.storage.fieldsChangedByTrigger.indexOf(fieldName) < 0) {
- this.storage.fieldsChangedByTrigger.push(fieldName);
- }
- } else if (schema.fields[fieldName] && schema.fields[fieldName].required === true) {
- throw new Parse.Error(Parse.Error.VALIDATION_ERROR, `${fieldName} is required`);
- }
- }
- };
-
- if (!this.query) {
-
- if (this.auth.isMaintenance && this.data.createdAt && this.data.createdAt.__type === 'Date') {
- this.data.createdAt = this.data.createdAt.iso;
- if (this.data.updatedAt && this.data.updatedAt.__type === 'Date') {
- const createdAt = new Date(this.data.createdAt);
- const updatedAt = new Date(this.data.updatedAt.iso);
- if (updatedAt < createdAt) {
- throw new Parse.Error(Parse.Error.VALIDATION_ERROR, 'updatedAt cannot occur before createdAt');
- }
- this.data.updatedAt = this.data.updatedAt.iso;
- }
-
- else {
- this.data.updatedAt = this.data.createdAt;
- }
- } else {
- this.data.updatedAt = this.updatedAt;
- this.data.createdAt = this.updatedAt;
- }
-
- if (!this.data.objectId) {
- this.data.objectId = cryptoUtils.newObjectId(this.config.objectIdSize);
- }
- if (schema) {
- Object.keys(schema.fields).forEach(fieldName => {
- setRequiredFieldIfNeeded(fieldName, true);
- });
- }
- } else if (schema) {
- this.data.updatedAt = this.updatedAt;
- Object.keys(this.data).forEach(fieldName => {
- setRequiredFieldIfNeeded(fieldName, false);
- });
- }
- });
- }
- return Promise.resolve();
- };
- RestWrite.prototype.validateAuthData = function () {
- if (this.className !== '_User') {
- return;
- }
- const authData = this.data.authData;
- const hasUsernameAndPassword = typeof this.data.username === 'string' && typeof this.data.password === 'string';
- if (!this.query && !authData) {
- if (typeof this.data.username !== 'string' || _lodash.default.isEmpty(this.data.username)) {
- throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'bad or missing username');
- }
- if (typeof this.data.password !== 'string' || _lodash.default.isEmpty(this.data.password)) {
- throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'password is required');
- }
- }
- if (authData && !Object.keys(authData).length || !Object.prototype.hasOwnProperty.call(this.data, 'authData')) {
-
- return;
- } else if (Object.prototype.hasOwnProperty.call(this.data, 'authData') && !this.data.authData) {
-
- throw new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.');
- }
- var providers = Object.keys(authData);
- if (providers.length > 0) {
- const canHandleAuthData = providers.some(provider => {
- var providerAuthData = authData[provider];
- var hasToken = providerAuthData && providerAuthData.id;
- return hasToken || providerAuthData === null;
- });
- if (canHandleAuthData || hasUsernameAndPassword || this.auth.isMaster || this.getUserId()) {
- return this.handleAuthData(authData);
- }
- }
- throw new Parse.Error(Parse.Error.UNSUPPORTED_SERVICE, 'This authentication method is unsupported.');
- };
- RestWrite.prototype.filteredObjectsByACL = function (objects) {
- if (this.auth.isMaster || this.auth.isMaintenance) {
- return objects;
- }
- return objects.filter(object => {
- if (!object.ACL) {
- return true;
- }
-
- return object.ACL && Object.keys(object.ACL).length > 0;
- });
- };
- RestWrite.prototype.getUserId = function () {
- if (this.query && this.query.objectId && this.className === '_User') {
- return this.query.objectId;
- } else if (this.auth && this.auth.user && this.auth.user.id) {
- return this.auth.user.id;
- }
- };
- RestWrite.prototype.ensureUniqueAuthDataId = async function () {
- if (this.className !== '_User' || !this.data.authData) {
- return;
- }
- const hasAuthDataId = Object.keys(this.data.authData).some(key => this.data.authData[key] && this.data.authData[key].id);
- if (!hasAuthDataId) return;
- const r = await Auth.findUsersWithAuthData(this.config, this.data.authData);
- const results = this.filteredObjectsByACL(r);
- if (results.length > 1) {
- throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used');
- }
-
- const userId = this.getUserId() || this.data.objectId;
- if (results.length === 1 && userId !== results[0].objectId) {
- throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used');
- }
- };
- RestWrite.prototype.handleAuthData = async function (authData) {
- const r = await Auth.findUsersWithAuthData(this.config, authData);
- const results = this.filteredObjectsByACL(r);
- const userId = this.getUserId();
- const userResult = results[0];
- const foundUserIsNotCurrentUser = userId && userResult && userId !== userResult.objectId;
- if (results.length > 1 || foundUserIsNotCurrentUser) {
-
-
- await Auth.handleAuthDataValidation(authData, this, userResult);
- throw new Parse.Error(Parse.Error.ACCOUNT_ALREADY_LINKED, 'this auth is already used');
- }
-
- if (!results.length) {
- const {
- authData: validatedAuthData,
- authDataResponse
- } = await Auth.handleAuthDataValidation(authData, this);
- this.authDataResponse = authDataResponse;
-
- this.data.authData = validatedAuthData;
- return;
- }
-
- if (results.length === 1) {
- this.storage.authProvider = Object.keys(authData).join(',');
- const {
- hasMutatedAuthData,
- mutatedAuthData
- } = Auth.hasMutatedAuthData(authData, userResult.authData);
- const isCurrentUserLoggedOrMaster = this.auth && this.auth.user && this.auth.user.id === userResult.objectId || this.auth.isMaster;
- const isLogin = !userId;
- if (isLogin || isCurrentUserLoggedOrMaster) {
-
-
-
- delete results[0].password;
-
- this.data.objectId = userResult.objectId;
- if (!this.query || !this.query.objectId) {
- this.response = {
- response: userResult,
- location: this.location()
- };
-
-
-
- await this.runBeforeLoginTrigger(deepcopy(userResult));
-
-
-
- Auth.checkIfUserHasProvidedConfiguredProvidersForLogin({
- config: this.config,
- auth: this.auth
- }, authData, userResult.authData, this.config);
- }
-
- if (!hasMutatedAuthData && isCurrentUserLoggedOrMaster) {
- return;
- }
-
-
- if (hasMutatedAuthData || !this.config.allowExpiredAuthDataToken) {
- const res = await Auth.handleAuthDataValidation(isLogin ? authData : mutatedAuthData, this, userResult);
- this.data.authData = res.authData;
- this.authDataResponse = res.authDataResponse;
- }
-
-
-
-
- if (this.response) {
-
- Object.keys(mutatedAuthData).forEach(provider => {
- this.response.response.authData[provider] = mutatedAuthData[provider];
- });
-
-
-
-
- if (Object.keys(this.data.authData).length) {
- await this.config.database.update(this.className, {
- objectId: this.data.objectId
- }, {
- authData: this.data.authData
- }, {});
- }
- }
- }
- }
- };
- RestWrite.prototype.checkRestrictedFields = async function () {
- if (this.className !== '_User') {
- return;
- }
- if (!this.auth.isMaintenance && !this.auth.isMaster && 'emailVerified' in this.data) {
- const error = `Clients aren't allowed to manually update email verification.`;
- throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, error);
- }
- };
- RestWrite.prototype.transformUser = async function () {
- var promise = Promise.resolve();
- if (this.className !== '_User') {
- return promise;
- }
-
- if (this.query && this.objectId()) {
-
-
- const query = await (0, _RestQuery.default)({
- method: _RestQuery.default.Method.find,
- config: this.config,
- auth: Auth.master(this.config),
- className: '_Session',
- runBeforeFind: false,
- restWhere: {
- user: {
- __type: 'Pointer',
- className: '_User',
- objectId: this.objectId()
- }
- }
- });
- promise = query.execute().then(results => {
- results.results.forEach(session => this.config.cacheController.user.del(session.sessionToken));
- });
- }
- return promise.then(() => {
-
- if (this.data.password === undefined) {
-
- return Promise.resolve();
- }
- if (this.query) {
- this.storage['clearSessions'] = true;
-
- if (!this.auth.isMaster && !this.auth.isMaintenance) {
- this.storage['generateNewSession'] = true;
- }
- }
- return this._validatePasswordPolicy().then(() => {
- return passwordCrypto.hash(this.data.password).then(hashedPassword => {
- this.data._hashed_password = hashedPassword;
- delete this.data.password;
- });
- });
- }).then(() => {
- return this._validateUserName();
- }).then(() => {
- return this._validateEmail();
- });
- };
- RestWrite.prototype._validateUserName = function () {
-
- if (!this.data.username) {
- if (!this.query) {
- this.data.username = cryptoUtils.randomString(25);
- this.responseShouldHaveUsername = true;
- }
- return Promise.resolve();
- }
-
- return this.config.database.find(this.className, {
- username: this.data.username,
- objectId: {
- $ne: this.objectId()
- }
- }, {
- limit: 1,
- caseInsensitive: true
- }, {}, this.validSchemaController).then(results => {
- if (results.length > 0) {
- throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.');
- }
- return;
- });
- };
- RestWrite.prototype._validateEmail = function () {
- if (!this.data.email || this.data.email.__op === 'Delete') {
- return Promise.resolve();
- }
-
- if (!this.data.email.match(/^.+@.+$/)) {
- return Promise.reject(new Parse.Error(Parse.Error.INVALID_EMAIL_ADDRESS, 'Email address format is invalid.'));
- }
-
- return this.config.database.find(this.className, {
- email: this.data.email,
- objectId: {
- $ne: this.objectId()
- }
- }, {
- limit: 1,
- caseInsensitive: true
- }, {}, this.validSchemaController).then(results => {
- if (results.length > 0) {
- throw new Parse.Error(Parse.Error.EMAIL_TAKEN, 'Account already exists for this email address.');
- }
- if (!this.data.authData || !Object.keys(this.data.authData).length || Object.keys(this.data.authData).length === 1 && Object.keys(this.data.authData)[0] === 'anonymous') {
-
- const {
- originalObject,
- updatedObject
- } = this.buildParseObjects();
- const request = {
- original: originalObject,
- object: updatedObject,
- master: this.auth.isMaster,
- ip: this.config.ip,
- installationId: this.auth.installationId
- };
- return this.config.userController.setEmailVerifyToken(this.data, request, this.storage);
- }
- });
- };
- RestWrite.prototype._validatePasswordPolicy = function () {
- if (!this.config.passwordPolicy) return Promise.resolve();
- return this._validatePasswordRequirements().then(() => {
- return this._validatePasswordHistory();
- });
- };
- RestWrite.prototype._validatePasswordRequirements = function () {
-
-
-
-
-
-
-
-
- const policyError = this.config.passwordPolicy.validationError ? this.config.passwordPolicy.validationError : 'Password does not meet the Password Policy requirements.';
- const containsUsernameError = 'Password cannot contain your username.';
-
- if (this.config.passwordPolicy.patternValidator && !this.config.passwordPolicy.patternValidator(this.data.password) || this.config.passwordPolicy.validatorCallback && !this.config.passwordPolicy.validatorCallback(this.data.password)) {
- return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, policyError));
- }
-
- if (this.config.passwordPolicy.doNotAllowUsername === true) {
- if (this.data.username) {
-
- if (this.data.password.indexOf(this.data.username) >= 0) return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, containsUsernameError));
- } else {
-
- return this.config.database.find('_User', {
- objectId: this.objectId()
- }).then(results => {
- if (results.length != 1) {
- throw undefined;
- }
- if (this.data.password.indexOf(results[0].username) >= 0) return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, containsUsernameError));
- return Promise.resolve();
- });
- }
- }
- return Promise.resolve();
- };
- RestWrite.prototype._validatePasswordHistory = function () {
-
- if (this.query && this.config.passwordPolicy.maxPasswordHistory) {
- return this.config.database.find('_User', {
- objectId: this.objectId()
- }, {
- keys: ['_password_history', '_hashed_password']
- }, Auth.maintenance(this.config)).then(results => {
- if (results.length != 1) {
- throw undefined;
- }
- const user = results[0];
- let oldPasswords = [];
- if (user._password_history) oldPasswords = _lodash.default.take(user._password_history, this.config.passwordPolicy.maxPasswordHistory - 1);
- oldPasswords.push(user.password);
- const newPassword = this.data.password;
-
- const promises = oldPasswords.map(function (hash) {
- return passwordCrypto.compare(newPassword, hash).then(result => {
- if (result)
-
- return Promise.reject('REPEAT_PASSWORD');
- return Promise.resolve();
- });
- });
-
- return Promise.all(promises).then(() => {
- return Promise.resolve();
- }).catch(err => {
- if (err === 'REPEAT_PASSWORD')
-
- return Promise.reject(new Parse.Error(Parse.Error.VALIDATION_ERROR, `New password should not be the same as last ${this.config.passwordPolicy.maxPasswordHistory} passwords.`));
- throw err;
- });
- });
- }
- return Promise.resolve();
- };
- RestWrite.prototype.createSessionTokenIfNeeded = async function () {
- if (this.className !== '_User') {
- return;
- }
-
- if (this.query && !this.data.authData) {
- return;
- }
-
- if (this.auth.user && this.data.authData) {
- return;
- }
-
- if (!this.storage.authProvider) {
-
- const {
- originalObject,
- updatedObject
- } = this.buildParseObjects();
- const request = {
- original: originalObject,
- object: updatedObject,
- master: this.auth.isMaster,
- ip: this.config.ip,
- installationId: this.auth.installationId
- };
-
-
-
- const verifyUserEmails = async () => this.config.verifyUserEmails === true || typeof this.config.verifyUserEmails === 'function' && (await Promise.resolve(this.config.verifyUserEmails(request))) === true;
- const preventLoginWithUnverifiedEmail = async () => this.config.preventLoginWithUnverifiedEmail === true || typeof this.config.preventLoginWithUnverifiedEmail === 'function' && (await Promise.resolve(this.config.preventLoginWithUnverifiedEmail(request))) === true;
-
- if ((await verifyUserEmails()) && (await preventLoginWithUnverifiedEmail())) {
- this.storage.rejectSignup = true;
- return;
- }
- }
- return this.createSessionToken();
- };
- RestWrite.prototype.createSessionToken = async function () {
-
-
- if (this.auth.installationId && this.auth.installationId === 'cloud') {
- return;
- }
- if (this.storage.authProvider == null && this.data.authData) {
- this.storage.authProvider = Object.keys(this.data.authData).join(',');
- }
- const {
- sessionData,
- createSession
- } = RestWrite.createSession(this.config, {
- userId: this.objectId(),
- createdWith: {
- action: this.storage.authProvider ? 'login' : 'signup',
- authProvider: this.storage.authProvider || 'password'
- },
- installationId: this.auth.installationId
- });
- if (this.response && this.response.response) {
- this.response.response.sessionToken = sessionData.sessionToken;
- }
- return createSession();
- };
- RestWrite.createSession = function (config, {
- userId,
- createdWith,
- installationId,
- additionalSessionData
- }) {
- const token = 'r:' + cryptoUtils.newToken();
- const expiresAt = config.generateSessionExpiresAt();
- const sessionData = {
- sessionToken: token,
- user: {
- __type: 'Pointer',
- className: '_User',
- objectId: userId
- },
- createdWith,
- expiresAt: Parse._encode(expiresAt)
- };
- if (installationId) {
- sessionData.installationId = installationId;
- }
- Object.assign(sessionData, additionalSessionData);
- return {
- sessionData,
- createSession: () => new RestWrite(config, Auth.master(config), '_Session', null, sessionData).execute()
- };
- };
- RestWrite.prototype.deleteEmailResetTokenIfNeeded = function () {
- if (this.className !== '_User' || this.query === null) {
-
- return;
- }
- if ('password' in this.data || 'email' in this.data) {
- const addOps = {
- _perishable_token: {
- __op: 'Delete'
- },
- _perishable_token_expires_at: {
- __op: 'Delete'
- }
- };
- this.data = Object.assign(this.data, addOps);
- }
- };
- RestWrite.prototype.destroyDuplicatedSessions = function () {
-
- if (this.className != '_Session' || this.query) {
- return;
- }
-
- const {
- user,
- installationId,
- sessionToken
- } = this.data;
- if (!user || !installationId) {
- return;
- }
- if (!user.objectId) {
- return;
- }
- this.config.database.destroy('_Session', {
- user,
- installationId,
- sessionToken: {
- $ne: sessionToken
- }
- }, {}, this.validSchemaController);
- };
- RestWrite.prototype.handleFollowup = function () {
- if (this.storage && this.storage['clearSessions'] && this.config.revokeSessionOnPasswordReset) {
- var sessionQuery = {
- user: {
- __type: 'Pointer',
- className: '_User',
- objectId: this.objectId()
- }
- };
- delete this.storage['clearSessions'];
- return this.config.database.destroy('_Session', sessionQuery).then(this.handleFollowup.bind(this));
- }
- if (this.storage && this.storage['generateNewSession']) {
- delete this.storage['generateNewSession'];
- return this.createSessionToken().then(this.handleFollowup.bind(this));
- }
- if (this.storage && this.storage['sendVerificationEmail']) {
- delete this.storage['sendVerificationEmail'];
-
- this.config.userController.sendVerificationEmail(this.data, {
- auth: this.auth
- });
- return this.handleFollowup.bind(this);
- }
- };
- RestWrite.prototype.handleSession = function () {
- if (this.response || this.className !== '_Session') {
- return;
- }
- if (!this.auth.user && !this.auth.isMaster && !this.auth.isMaintenance) {
- throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'Session token required.');
- }
-
- if (this.data.ACL) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Cannot set ' + 'ACL on a Session.');
- }
- if (this.query) {
- if (this.data.user && !this.auth.isMaster && this.data.user.objectId != this.auth.user.id) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME);
- } else if (this.data.installationId) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME);
- } else if (this.data.sessionToken) {
- throw new Parse.Error(Parse.Error.INVALID_KEY_NAME);
- }
- if (!this.auth.isMaster) {
- this.query = {
- $and: [this.query, {
- user: {
- __type: 'Pointer',
- className: '_User',
- objectId: this.auth.user.id
- }
- }]
- };
- }
- }
- if (!this.query && !this.auth.isMaster && !this.auth.isMaintenance) {
- const additionalSessionData = {};
- for (var key in this.data) {
- if (key === 'objectId' || key === 'user') {
- continue;
- }
- additionalSessionData[key] = this.data[key];
- }
- const {
- sessionData,
- createSession
- } = RestWrite.createSession(this.config, {
- userId: this.auth.user.id,
- createdWith: {
- action: 'create'
- },
- additionalSessionData
- });
- return createSession().then(results => {
- if (!results.response) {
- throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Error creating session.');
- }
- sessionData['objectId'] = results.response['objectId'];
- this.response = {
- status: 201,
- location: results.location,
- response: sessionData
- };
- });
- }
- };
- RestWrite.prototype.handleInstallation = function () {
- if (this.response || this.className !== '_Installation') {
- return;
- }
- if (!this.query && !this.data.deviceToken && !this.data.installationId && !this.auth.installationId) {
- throw new Parse.Error(135, 'at least one ID field (deviceToken, installationId) ' + 'must be specified in this operation');
- }
-
-
- if (this.data.deviceToken && this.data.deviceToken.length == 64) {
- this.data.deviceToken = this.data.deviceToken.toLowerCase();
- }
-
- if (this.data.installationId) {
- this.data.installationId = this.data.installationId.toLowerCase();
- }
- let installationId = this.data.installationId;
-
- if (!installationId && !this.auth.isMaster && !this.auth.isMaintenance) {
- installationId = this.auth.installationId;
- }
- if (installationId) {
- installationId = installationId.toLowerCase();
- }
-
- if (this.query && !this.data.deviceToken && !installationId && !this.data.deviceType) {
- return;
- }
- var promise = Promise.resolve();
- var idMatch;
- var objectIdMatch;
- var installationIdMatch;
- var deviceTokenMatches = [];
-
- const orQueries = [];
- if (this.query && this.query.objectId) {
- orQueries.push({
- objectId: this.query.objectId
- });
- }
- if (installationId) {
- orQueries.push({
- installationId: installationId
- });
- }
- if (this.data.deviceToken) {
- orQueries.push({
- deviceToken: this.data.deviceToken
- });
- }
- if (orQueries.length == 0) {
- return;
- }
- promise = promise.then(() => {
- return this.config.database.find('_Installation', {
- $or: orQueries
- }, {});
- }).then(results => {
- results.forEach(result => {
- if (this.query && this.query.objectId && result.objectId == this.query.objectId) {
- objectIdMatch = result;
- }
- if (result.installationId == installationId) {
- installationIdMatch = result;
- }
- if (result.deviceToken == this.data.deviceToken) {
- deviceTokenMatches.push(result);
- }
- });
-
- if (this.query && this.query.objectId) {
- if (!objectIdMatch) {
- throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Object not found for update.');
- }
- if (this.data.installationId && objectIdMatch.installationId && this.data.installationId !== objectIdMatch.installationId) {
- throw new Parse.Error(136, 'installationId may not be changed in this ' + 'operation');
- }
- if (this.data.deviceToken && objectIdMatch.deviceToken && this.data.deviceToken !== objectIdMatch.deviceToken && !this.data.installationId && !objectIdMatch.installationId) {
- throw new Parse.Error(136, 'deviceToken may not be changed in this ' + 'operation');
- }
- if (this.data.deviceType && this.data.deviceType && this.data.deviceType !== objectIdMatch.deviceType) {
- throw new Parse.Error(136, 'deviceType may not be changed in this ' + 'operation');
- }
- }
- if (this.query && this.query.objectId && objectIdMatch) {
- idMatch = objectIdMatch;
- }
- if (installationId && installationIdMatch) {
- idMatch = installationIdMatch;
- }
-
- if (!this.query && !this.data.deviceType && !idMatch) {
- throw new Parse.Error(135, 'deviceType must be specified in this operation');
- }
- }).then(() => {
- if (!idMatch) {
- if (!deviceTokenMatches.length) {
- return;
- } else if (deviceTokenMatches.length == 1 && (!deviceTokenMatches[0]['installationId'] || !installationId)) {
-
-
-
- return deviceTokenMatches[0]['objectId'];
- } else if (!this.data.installationId) {
- throw new Parse.Error(132, 'Must specify installationId when deviceToken ' + 'matches multiple Installation objects');
- } else {
-
-
-
-
-
- var delQuery = {
- deviceToken: this.data.deviceToken,
- installationId: {
- $ne: installationId
- }
- };
- if (this.data.appIdentifier) {
- delQuery['appIdentifier'] = this.data.appIdentifier;
- }
- this.config.database.destroy('_Installation', delQuery).catch(err => {
- if (err.code == Parse.Error.OBJECT_NOT_FOUND) {
-
- return;
- }
-
- throw err;
- });
- return;
- }
- } else {
- if (deviceTokenMatches.length == 1 && !deviceTokenMatches[0]['installationId']) {
-
-
-
- const delQuery = {
- objectId: idMatch.objectId
- };
- return this.config.database.destroy('_Installation', delQuery).then(() => {
- return deviceTokenMatches[0]['objectId'];
- }).catch(err => {
- if (err.code == Parse.Error.OBJECT_NOT_FOUND) {
-
- return;
- }
-
- throw err;
- });
- } else {
- if (this.data.deviceToken && idMatch.deviceToken != this.data.deviceToken) {
-
-
-
- const delQuery = {
- deviceToken: this.data.deviceToken
- };
-
-
- if (this.data.installationId) {
- delQuery['installationId'] = {
- $ne: this.data.installationId
- };
- } else if (idMatch.objectId && this.data.objectId && idMatch.objectId == this.data.objectId) {
-
- delQuery['objectId'] = {
- $ne: idMatch.objectId
- };
- } else {
-
- return idMatch.objectId;
- }
- if (this.data.appIdentifier) {
- delQuery['appIdentifier'] = this.data.appIdentifier;
- }
- this.config.database.destroy('_Installation', delQuery).catch(err => {
- if (err.code == Parse.Error.OBJECT_NOT_FOUND) {
-
- return;
- }
-
- throw err;
- });
- }
-
- return idMatch.objectId;
- }
- }
- }).then(objId => {
- if (objId) {
- this.query = {
- objectId: objId
- };
- delete this.data.objectId;
- delete this.data.createdAt;
- }
-
- });
- return promise;
- };
- RestWrite.prototype.expandFilesForExistingObjects = async function () {
-
- if (this.response && this.response.response) {
- await this.config.filesController.expandFilesInObject(this.config, this.response.response);
- }
- };
- RestWrite.prototype.runDatabaseOperation = function () {
- if (this.response) {
- return;
- }
- if (this.className === '_Role') {
- this.config.cacheController.role.clear();
- if (this.config.liveQueryController) {
- this.config.liveQueryController.clearCachedRoles(this.auth.user);
- }
- }
- if (this.className === '_User' && this.query && this.auth.isUnauthenticated()) {
- throw new Parse.Error(Parse.Error.SESSION_MISSING, `Cannot modify user ${this.query.objectId}.`);
- }
- if (this.className === '_Product' && this.data.download) {
- this.data.downloadName = this.data.download.name;
- }
-
-
- if (this.data.ACL && this.data.ACL['*unresolved']) {
- throw new Parse.Error(Parse.Error.INVALID_ACL, 'Invalid ACL.');
- }
- if (this.query) {
-
-
- if (this.className === '_User' && this.data.ACL && this.auth.isMaster !== true && this.auth.isMaintenance !== true) {
- this.data.ACL[this.query.objectId] = {
- read: true,
- write: true
- };
- }
-
- if (this.className === '_User' && this.data._hashed_password && this.config.passwordPolicy && this.config.passwordPolicy.maxPasswordAge) {
- this.data._password_changed_at = Parse._encode(new Date());
- }
-
- delete this.data.createdAt;
- let defer = Promise.resolve();
-
- if (this.className === '_User' && this.data._hashed_password && this.config.passwordPolicy && this.config.passwordPolicy.maxPasswordHistory) {
- defer = this.config.database.find('_User', {
- objectId: this.objectId()
- }, {
- keys: ['_password_history', '_hashed_password']
- }, Auth.maintenance(this.config)).then(results => {
- if (results.length != 1) {
- throw undefined;
- }
- const user = results[0];
- let oldPasswords = [];
- if (user._password_history) {
- oldPasswords = _lodash.default.take(user._password_history, this.config.passwordPolicy.maxPasswordHistory);
- }
-
- while (oldPasswords.length > Math.max(0, this.config.passwordPolicy.maxPasswordHistory - 2)) {
- oldPasswords.shift();
- }
- oldPasswords.push(user.password);
- this.data._password_history = oldPasswords;
- });
- }
- return defer.then(() => {
-
- return this.config.database.update(this.className, this.query, this.data, this.runOptions, false, false, this.validSchemaController).then(response => {
- response.updatedAt = this.updatedAt;
- this._updateResponseWithData(response, this.data);
- this.response = {
- response
- };
- });
- });
- } else {
-
- if (this.className === '_User') {
- var ACL = this.data.ACL;
-
- if (!ACL) {
- ACL = {};
- if (!this.config.enforcePrivateUsers) {
- ACL['*'] = {
- read: true,
- write: false
- };
- }
- }
-
- ACL[this.data.objectId] = {
- read: true,
- write: true
- };
- this.data.ACL = ACL;
-
- if (this.config.passwordPolicy && this.config.passwordPolicy.maxPasswordAge) {
- this.data._password_changed_at = Parse._encode(new Date());
- }
- }
-
- return this.config.database.create(this.className, this.data, this.runOptions, false, this.validSchemaController).catch(error => {
- if (this.className !== '_User' || error.code !== Parse.Error.DUPLICATE_VALUE) {
- throw error;
- }
-
- if (error && error.userInfo && error.userInfo.duplicated_field === 'username') {
- throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.');
- }
- if (error && error.userInfo && error.userInfo.duplicated_field === 'email') {
- throw new Parse.Error(Parse.Error.EMAIL_TAKEN, 'Account already exists for this email address.');
- }
-
-
-
-
- return this.config.database.find(this.className, {
- username: this.data.username,
- objectId: {
- $ne: this.objectId()
- }
- }, {
- limit: 1
- }).then(results => {
- if (results.length > 0) {
- throw new Parse.Error(Parse.Error.USERNAME_TAKEN, 'Account already exists for this username.');
- }
- return this.config.database.find(this.className, {
- email: this.data.email,
- objectId: {
- $ne: this.objectId()
- }
- }, {
- limit: 1
- });
- }).then(results => {
- if (results.length > 0) {
- throw new Parse.Error(Parse.Error.EMAIL_TAKEN, 'Account already exists for this email address.');
- }
- throw new Parse.Error(Parse.Error.DUPLICATE_VALUE, 'A duplicate value for a field with unique values was provided');
- });
- }).then(response => {
- response.objectId = this.data.objectId;
- response.createdAt = this.data.createdAt;
- if (this.responseShouldHaveUsername) {
- response.username = this.data.username;
- }
- this._updateResponseWithData(response, this.data);
- this.response = {
- status: 201,
- response,
- location: this.location()
- };
- });
- }
- };
- RestWrite.prototype.runAfterSaveTrigger = function () {
- if (!this.response || !this.response.response || this.runOptions.many) {
- return;
- }
-
- const hasAfterSaveHook = triggers.triggerExists(this.className, triggers.Types.afterSave, this.config.applicationId);
- const hasLiveQuery = this.config.liveQueryController.hasLiveQuery(this.className);
- if (!hasAfterSaveHook && !hasLiveQuery) {
- return Promise.resolve();
- }
- const {
- originalObject,
- updatedObject
- } = this.buildParseObjects();
- updatedObject._handleSaveResponse(this.response.response, this.response.status || 200);
- if (hasLiveQuery) {
- this.config.database.loadSchema().then(schemaController => {
-
- const perms = schemaController.getClassLevelPermissions(updatedObject.className);
- this.config.liveQueryController.onAfterSave(updatedObject.className, updatedObject, originalObject, perms);
- });
- }
- if (!hasAfterSaveHook) {
- return Promise.resolve();
- }
-
- return triggers.maybeRunTrigger(triggers.Types.afterSave, this.auth, updatedObject, originalObject, this.config, this.context).then(result => {
- const jsonReturned = result && !result._toFullJSON;
- if (jsonReturned) {
- this.pendingOps.operations = {};
- this.response.response = result;
- } else {
- this.response.response = this._updateResponseWithData((result || updatedObject).toJSON(), this.data);
- }
- }).catch(function (err) {
- _logger.default.warn('afterSave caught an error', err);
- });
- };
- RestWrite.prototype.location = function () {
- var middle = this.className === '_User' ? '/users/' : '/classes/' + this.className + '/';
- const mount = this.config.mount || this.config.serverURL;
- return mount + middle + this.data.objectId;
- };
- RestWrite.prototype.objectId = function () {
- return this.data.objectId || this.query.objectId;
- };
- RestWrite.prototype.sanitizedData = function () {
- const data = Object.keys(this.data).reduce((data, key) => {
-
- if (!/^[A-Za-z][0-9A-Za-z_]*$/.test(key)) {
- delete data[key];
- }
- return data;
- }, deepcopy(this.data));
- return Parse._decode(undefined, data);
- };
- RestWrite.prototype.buildParseObjects = function () {
- var _this$query;
- const extraData = {
- className: this.className,
- objectId: (_this$query = this.query) === null || _this$query === void 0 ? void 0 : _this$query.objectId
- };
- let originalObject;
- if (this.query && this.query.objectId) {
- originalObject = triggers.inflate(extraData, this.originalData);
- }
- const className = Parse.Object.fromJSON(extraData);
- const readOnlyAttributes = className.constructor.readOnlyAttributes ? className.constructor.readOnlyAttributes() : [];
- if (!this.originalData) {
- for (const attribute of readOnlyAttributes) {
- extraData[attribute] = this.data[attribute];
- }
- }
- const updatedObject = triggers.inflate(extraData, this.originalData);
- Object.keys(this.data).reduce(function (data, key) {
- if (key.indexOf('.') > 0) {
- if (typeof data[key].__op === 'string') {
- if (!readOnlyAttributes.includes(key)) {
- updatedObject.set(key, data[key]);
- }
- } else {
-
- const splittedKey = key.split('.');
- const parentProp = splittedKey[0];
- let parentVal = updatedObject.get(parentProp);
- if (typeof parentVal !== 'object') {
- parentVal = {};
- }
- parentVal[splittedKey[1]] = data[key];
- updatedObject.set(parentProp, parentVal);
- }
- delete data[key];
- }
- return data;
- }, deepcopy(this.data));
- const sanitized = this.sanitizedData();
- for (const attribute of readOnlyAttributes) {
- delete sanitized[attribute];
- }
- updatedObject.set(sanitized);
- return {
- updatedObject,
- originalObject
- };
- };
- RestWrite.prototype.cleanUserAuthData = function () {
- if (this.response && this.response.response && this.className === '_User') {
- const user = this.response.response;
- if (user.authData) {
- Object.keys(user.authData).forEach(provider => {
- if (user.authData[provider] === null) {
- delete user.authData[provider];
- }
- });
- if (Object.keys(user.authData).length == 0) {
- delete user.authData;
- }
- }
- }
- };
- RestWrite.prototype._updateResponseWithData = function (response, data) {
- const stateController = Parse.CoreManager.getObjectStateController();
- const [pending] = stateController.getPendingOps(this.pendingOps.identifier);
- for (const key in this.pendingOps.operations) {
- if (!pending[key]) {
- data[key] = this.originalData ? this.originalData[key] : {
- __op: 'Delete'
- };
- this.storage.fieldsChangedByTrigger.push(key);
- }
- }
- const skipKeys = [...(_SchemaController.requiredColumns.read[this.className] || [])];
- if (!this.query) {
- skipKeys.push('objectId', 'createdAt');
- } else {
- skipKeys.push('updatedAt');
- delete response.objectId;
- }
- for (const key in response) {
- if (skipKeys.includes(key)) {
- continue;
- }
- const value = response[key];
- if (value == null || value.__type && value.__type === 'Pointer' || util.isDeepStrictEqual(data[key], value) || util.isDeepStrictEqual((this.originalData || {})[key], value)) {
- delete response[key];
- }
- }
- if (_lodash.default.isEmpty(this.storage.fieldsChangedByTrigger)) {
- return response;
- }
- const clientSupportsDelete = ClientSDK.supportsForwardDelete(this.clientSDK);
- this.storage.fieldsChangedByTrigger.forEach(fieldName => {
- const dataValue = data[fieldName];
- if (!Object.prototype.hasOwnProperty.call(response, fieldName)) {
- response[fieldName] = dataValue;
- }
-
- if (response[fieldName] && response[fieldName].__op) {
- delete response[fieldName];
- if (clientSupportsDelete && dataValue.__op == 'Delete') {
- response[fieldName] = dataValue;
- }
- }
- });
- return response;
- };
- var _default = exports.default = RestWrite;
- module.exports = RestWrite;
|