UNPKG

formiojs

Version:

Common js library for client side interaction with <form.io>

1,283 lines (1,248 loc) • 65.8 kB
"use strict"; require("core-js/modules/es.symbol.to-primitive.js"); require("core-js/modules/es.date.to-primitive.js"); require("core-js/modules/es.object.define-property.js"); require("core-js/modules/es.array.slice.js"); require("core-js/modules/es.function.name.js"); require("core-js/modules/es.array.from.js"); Object.defineProperty(exports, "__esModule", { value: true }); exports["default"] = exports.GlobalFormio = void 0; require("core-js/modules/es.array.is-array.js"); require("core-js/modules/es.regexp.exec.js"); require("core-js/modules/es.string.match.js"); require("core-js/modules/es.string.search.js"); require("core-js/modules/es.array.index-of.js"); require("core-js/modules/es.array.concat.js"); require("core-js/modules/es.regexp.constructor.js"); require("core-js/modules/es.regexp.to-string.js"); require("core-js/modules/es.string.replace.js"); require("core-js/modules/es.array.join.js"); require("core-js/modules/es.array.includes.js"); require("core-js/modules/es.string.includes.js"); require("core-js/modules/es.parse-int.js"); require("core-js/modules/es.object.assign.js"); require("core-js/modules/es.array.for-each.js"); require("core-js/modules/es.object.to-string.js"); require("core-js/modules/web.dom-collections.for-each.js"); require("core-js/modules/es.number.constructor.js"); require("core-js/modules/es.array.filter.js"); require("core-js/modules/es.array.sort.js"); require("core-js/modules/es.array.map.js"); require("core-js/modules/es.array.reduce.js"); require("core-js/modules/es.date.to-string.js"); require("core-js/modules/web.timers.js"); require("core-js/modules/es.symbol.js"); require("core-js/modules/es.symbol.description.js"); require("core-js/modules/es.symbol.iterator.js"); require("core-js/modules/es.array.iterator.js"); require("core-js/modules/es.string.iterator.js"); require("core-js/modules/web.dom-collections.iterator.js"); var _nativePromiseOnly = _interopRequireDefault(require("native-promise-only")); var _fetchPonyfill2 = _interopRequireDefault(require("fetch-ponyfill")); var _EventEmitter = _interopRequireDefault(require("./EventEmitter")); var _browserCookies = _interopRequireDefault(require("browser-cookies")); var _providers = _interopRequireDefault(require("./providers")); var _intersection2 = _interopRequireDefault(require("lodash/intersection")); var _get2 = _interopRequireDefault(require("lodash/get")); var _cloneDeep2 = _interopRequireDefault(require("lodash/cloneDeep")); var _defaults2 = _interopRequireDefault(require("lodash/defaults")); var _utils = require("./utils/utils"); var _jwtDecode = _interopRequireDefault(require("jwt-decode")); require("./polyfills"); var _CDN = _interopRequireDefault(require("./CDN")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i["return"] && (_r = _i["return"](), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; } function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); } function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); } function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } var _fetchPonyfill = (0, _fetchPonyfill2["default"])({ Promise: _nativePromiseOnly["default"] }), fetch = _fetchPonyfill.fetch, Headers = _fetchPonyfill.Headers; var isBoolean = function isBoolean(val) { return _typeof(val) === _typeof(true); }; var isNil = function isNil(val) { return val === null || val === undefined; }; var isObject = function isObject(val) { return val && _typeof(val) === 'object'; }; function cloneResponse(response) { var copy = (0, _cloneDeep2["default"])(response); if (Array.isArray(response)) { copy.skip = response.skip; copy.limit = response.limit; copy.serverCount = response.serverCount; } return copy; } /** * The Formio interface class. * * let formio = new Formio('https://examples.form.io/example'); */ var Formio = /*#__PURE__*/function () { /* eslint-disable max-statements */ function Formio(path) { var _this = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; _classCallCheck(this, Formio); // Ensure we have an instance of Formio. if (!(this instanceof Formio)) { return new Formio(path); } // Initialize our variables. this.base = ''; this.projectsUrl = ''; this.projectUrl = ''; this.projectId = ''; this.roleUrl = ''; this.rolesUrl = ''; this.roleId = ''; this.formUrl = ''; this.formsUrl = ''; this.formId = ''; this.submissionsUrl = ''; this.submissionUrl = ''; this.submissionId = ''; this.actionsUrl = ''; this.actionId = ''; this.actionUrl = ''; this.vsUrl = ''; this.vId = ''; this.vUrl = ''; this.query = ''; // Store the original path and options. this.path = path; this.options = options; if (options.useSessionToken) { Formio.useSessionToken(options); } if (options.hasOwnProperty('base')) { this.base = options.base; } else if (Formio.baseUrl) { this.base = Formio.baseUrl; } else if (typeof window !== 'undefined') { this.base = window.location.href.match(/http[s]?:\/\/api./)[0]; } if (!path) { // Allow user to create new projects if this was instantiated without // a url this.projectUrl = Formio.projectUrl || "".concat(this.base, "/project"); this.projectsUrl = "".concat(this.base, "/project"); this.projectId = false; this.query = ''; return; } if (options.hasOwnProperty('project')) { this.projectUrl = options.project; } var project = this.projectUrl || Formio.projectUrl; var projectRegEx = /(^|\/)(project)($|\/[^/]+)/; var isProjectUrl = path.search(projectRegEx) !== -1; // The baseURL is the same as the projectUrl, and does not contain "/project/MONGO_ID" in // its domain. This is almost certainly against the Open Source server. if (project && this.base === project && !isProjectUrl) { this.noProject = true; this.projectUrl = this.base; } // Normalize to an absolute path. if (path.indexOf('http') !== 0 && path.indexOf('//') !== 0) { path = this.base + path; } var hostparts = this.getUrlParts(path); var parts = []; var hostName = hostparts[1] + hostparts[2]; path = hostparts.length > 3 ? hostparts[3] : ''; var queryparts = path.split('?'); if (queryparts.length > 1) { path = queryparts[0]; this.query = "?".concat(queryparts[1]); } // Register a specific path. var registerPath = function registerPath(name, base) { _this["".concat(name, "sUrl")] = "".concat(base, "/").concat(name); var regex = new RegExp("/".concat(name, "/([^/]+)")); if (path.search(regex) !== -1) { parts = path.match(regex); _this["".concat(name, "Url")] = parts ? base + parts[0] : ''; _this["".concat(name, "Id")] = parts.length > 1 ? parts[1] : ''; base += parts[0]; } return base; }; // Register an array of items. var registerItems = function registerItems(items, base, staticBase) { for (var i in items) { if (items.hasOwnProperty(i)) { var item = items[i]; if (Array.isArray(item)) { registerItems(item, base, true); } else { var newBase = registerPath(item, base); base = staticBase ? base : newBase; } } } }; if (!this.projectUrl || this.projectUrl === this.base) { // If a project uses Subdirectories path type, we need to specify a projectUrl if (!this.projectUrl && !isProjectUrl && Formio.pathType === 'Subdirectories') { var regex = "^".concat(hostName.replace(/\//g, '\\/'), ".[^/]+"); var match = project.match(new RegExp(regex)); this.projectUrl = match ? match[0] : hostName; } else { this.projectUrl = hostName; } } // Check if we have a specified path type. var isNotSubdomainType = false; if (Formio.pathType) { isNotSubdomainType = Formio.pathType !== 'Subdomains'; } if (!this.noProject) { // Determine the projectUrl and projectId if (isProjectUrl) { // Get project id as project/:projectId. registerItems(['project'], hostName); path = path.replace(projectRegEx, ''); } else if (hostName === this.base) { // Get project id as first part of path (subdirectory). if (hostparts.length > 3 && path.split('/').length > 1) { var isFile = path.match(/.json/); var pathParts = path.split('/'); if (isFile) { this.projectUrl = hostName; } else { pathParts.shift(); // Throw away the first /. this.projectId = pathParts.shift(); path = "/".concat(pathParts.join('/')); this.projectUrl = "".concat(hostName, "/").concat(this.projectId); } } } else { // Get project id from subdomain. if (hostparts.length > 2 && (hostparts[2].split('.').length > 2 || hostName.includes('localhost')) && !isNotSubdomainType) { this.projectUrl = hostName; this.projectId = hostparts[2].split('.')[0]; } } this.projectsUrl = this.projectsUrl || "".concat(this.base, "/project"); } // Configure Role urls and role ids. registerItems(['role'], this.projectUrl); // Configure Form urls and form ids. if (/(^|\/)(form)($|\/)/.test(path)) { registerItems(['form', ['submission', 'action', 'v']], this.projectUrl); } else { var subRegEx = new RegExp('/(submission|action|v)($|/.*)'); var subs = path.match(subRegEx); this.pathType = subs && subs.length > 1 ? subs[1] : ''; path = path.replace(subRegEx, ''); path = path.replace(/\/$/, ''); this.formsUrl = "".concat(this.projectUrl, "/form"); this.formUrl = path ? this.projectUrl + path : ''; this.formId = path.replace(/^\/+|\/+$/g, ''); var items = ['submission', 'action', 'v']; for (var i in items) { if (items.hasOwnProperty(i)) { var item = items[i]; this["".concat(item, "sUrl")] = "".concat(this.projectUrl + path, "/").concat(item); if (this.pathType === item && subs.length > 2 && subs[2]) { this["".concat(item, "Id")] = subs[2].replace(/^\/+|\/+$/g, ''); this["".concat(item, "Url")] = this.projectUrl + path + subs[0]; } } } } // Set the app url if it is not set. if (!Formio.projectUrlSet) { Formio.projectUrl = this.projectUrl; } } /* eslint-enable max-statements */ _createClass(Formio, [{ key: "delete", value: function _delete(type, opts) { var _id = "".concat(type, "Id"); var _url = "".concat(type, "Url"); if (!this[_id]) { return _nativePromiseOnly["default"].reject('Nothing to delete'); } Formio.cache = {}; return this.makeRequest(type, this[_url], 'delete', null, opts); } }, { key: "index", value: function index(type, query, opts) { var _url = "".concat(type, "Url"); query = query || ''; if (query && isObject(query)) { query = "?".concat(Formio.serialize(query.params)); } return this.makeRequest(type, this[_url] + query, 'get', null, opts); } }, { key: "save", value: function save(type, data, opts) { var _id = "".concat(type, "Id"); var _url = "".concat(type, "Url"); var method = this[_id] || data._id ? 'put' : 'post'; var reqUrl = this[_id] ? this[_url] : this["".concat(type, "sUrl")]; if (!this[_id] && data._id && method === 'put' && !reqUrl.includes(data._id)) { reqUrl += "/".concat(data._id); } Formio.cache = {}; return this.makeRequest(type, reqUrl + this.query, method, data, opts); } }, { key: "load", value: function load(type, query, opts) { var _id = "".concat(type, "Id"); var _url = "".concat(type, "Url"); if (query && isObject(query)) { query = Formio.serialize(query.params); } if (query) { query = this.query ? "".concat(this.query, "&").concat(query) : "?".concat(query); } else { query = this.query; } if (!this[_id]) { return _nativePromiseOnly["default"].reject("Missing ".concat(_id)); } var url = this[_url] + query; if (type === 'form' && !isNaN(parseInt(this.vId)) && parseInt(this.vId) !== 0) { url += url.match(/\?/) ? '&' : '?'; url += "formRevision=".concat(this.vId); } return this.makeRequest(type, url, 'get', null, opts); } }, { key: "makeRequest", value: function makeRequest() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return Formio.makeRequest.apply(Formio, [this].concat(args)); } }, { key: "loadProject", value: function loadProject(query, opts) { return this.load('project', query, opts); } }, { key: "saveProject", value: function saveProject(data, opts) { return this.save('project', data, opts); } }, { key: "deleteProject", value: function deleteProject(opts) { return this["delete"]('project', opts); } }, { key: "loadRole", value: function loadRole(opts) { return this.load('role', null, opts); } }, { key: "saveRole", value: function saveRole(data, opts) { return this.save('role', data, opts); } }, { key: "deleteRole", value: function deleteRole(opts) { return this["delete"]('role', opts); } }, { key: "loadRoles", value: function loadRoles(opts) { return this.index('roles', null, opts); } }, { key: "loadForm", value: function loadForm(query, opts) { var _this2 = this; return this.load('form', query, opts).then(function (currentForm) { // Check to see if there isn't a number in vId. if (!currentForm.revisions || isNaN(parseInt(_this2.vId))) { return currentForm; } // If a submission already exists but form is marked to load current version of form. if (currentForm.revisions === 'current' && _this2.submissionId) { return currentForm; } // eslint-disable-next-line eqeqeq if (currentForm._vid == _this2.vId || currentForm.revisionId === _this2.vId) { return currentForm; } // If they specified a revision form, load the revised form components. if (query && isObject(query)) { query = Formio.serialize(query.params); } if (query) { query = _this2.query ? "".concat(_this2.query, "&").concat(query) : "?".concat(query); } else { query = _this2.query; } return _this2.makeRequest('form', _this2.vUrl + query, 'get', null, opts).then(function (revisionForm) { currentForm._vid = revisionForm._vid; currentForm.components = revisionForm.components; currentForm.settings = revisionForm.settings; currentForm.revisionId = revisionForm.revisionId; // Using object.assign so we don't cross polinate multiple form loads. return Object.assign({}, currentForm); }) // If we couldn't load the revision, just return the original form. ["catch"](function () { return Object.assign({}, currentForm); }); }); } }, { key: "saveForm", value: function saveForm(data, opts) { return this.save('form', data, opts); } }, { key: "deleteForm", value: function deleteForm(opts) { return this["delete"]('form', opts); } }, { key: "loadForms", value: function loadForms(query, opts) { return this.index('forms', query, opts); } }, { key: "loadSubmission", value: function loadSubmission(query, opts) { var _this3 = this; return this.load('submission', query, opts).then(function (submission) { _this3.vId = submission._frid || submission._fvid; _this3.vUrl = "".concat(_this3.formUrl, "/v/").concat(_this3.vId); return submission; }); } }, { key: "saveSubmission", value: function saveSubmission(data, opts) { if (!isNaN(parseInt(this.vId))) { data._fvid = this.vId; } return this.save('submission', data, opts); } }, { key: "deleteSubmission", value: function deleteSubmission(opts) { return this["delete"]('submission', opts); } }, { key: "loadSubmissions", value: function loadSubmissions(query, opts) { return this.index('submissions', query, opts); } }, { key: "loadAction", value: function loadAction(query, opts) { return this.load('action', query, opts); } }, { key: "saveAction", value: function saveAction(data, opts) { return this.save('action', data, opts); } }, { key: "deleteAction", value: function deleteAction(opts) { return this["delete"]('action', opts); } }, { key: "loadActions", value: function loadActions(query, opts) { return this.index('actions', query, opts); } }, { key: "availableActions", value: function availableActions() { return this.makeRequest('availableActions', "".concat(this.formUrl, "/actions")); } }, { key: "actionInfo", value: function actionInfo(name) { return this.makeRequest('actionInfo', "".concat(this.formUrl, "/actions/").concat(name)); } }, { key: "isObjectId", value: function isObjectId(id) { var checkForHexRegExp = new RegExp('^[0-9a-fA-F]{24}$'); return checkForHexRegExp.test(id); } }, { key: "getProjectId", value: function getProjectId() { if (!this.projectId) { return _nativePromiseOnly["default"].resolve(''); } if (this.isObjectId(this.projectId)) { return _nativePromiseOnly["default"].resolve(this.projectId); } else { return this.loadProject().then(function (project) { return project._id; }); } } }, { key: "getFormId", value: function getFormId() { if (!this.formId) { return _nativePromiseOnly["default"].resolve(''); } if (this.isObjectId(this.formId)) { return _nativePromiseOnly["default"].resolve(this.formId); } else { return this.loadForm().then(function (form) { return form._id; }); } } }, { key: "currentUser", value: function currentUser(options) { return Formio.currentUser(this, options); } }, { key: "accessInfo", value: function accessInfo() { return Formio.accessInfo(this); } /** * Sets OAuth Logout URL. * * @return {*} */ }, { key: "oauthLogoutURI", value: function oauthLogoutURI(uri, options) { return Formio.oauthLogoutURI(uri, Object.assign({ formio: this }, this.options, options)); } /** * Returns the JWT token for this instance. * * @return {*} */ }, { key: "getToken", value: function getToken(options) { return Formio.getToken(Object.assign({ formio: this }, this.options, options)); } /** * Sets the JWT token for this instance. * * @return {*} */ }, { key: "setToken", value: function setToken(token, options) { return Formio.setToken(token, Object.assign({ formio: this }, this.options, options)); } /** * Returns a temporary authentication token for single purpose token generation. */ }, { key: "getTempToken", value: function getTempToken(expire, allowed, options) { var token = Formio.getToken(options); if (!token) { return _nativePromiseOnly["default"].reject('You must be authenticated to generate a temporary auth token.'); } var authUrl = Formio.authUrl || this.projectUrl; return this.makeRequest('tempToken', "".concat(authUrl, "/token"), 'GET', null, { ignoreCache: true, header: new Headers({ 'x-expire': expire, 'x-allow': allowed }) }); } /** * Get a download url for a submission PDF of this submission. * * @return {*} */ }, { key: "getDownloadUrl", value: function getDownloadUrl(form) { var _this4 = this; if (!this.submissionId) { return _nativePromiseOnly["default"].resolve(''); } if (!form) { // Make sure to load the form first. return this.loadForm().then(function (_form) { if (!_form) { return ''; } return _this4.getDownloadUrl(_form); }); } var apiUrl = "/project/".concat(form.project); apiUrl += "/form/".concat(form._id); apiUrl += "/submission/".concat(this.submissionId); var postfix = form.submissionRevisions && form.settings.changeLog ? '/download/changelog' : '/download'; apiUrl += postfix; var download = this.base + apiUrl; return new _nativePromiseOnly["default"](function (resolve, reject) { _this4.getTempToken(3600, "GET:".concat(apiUrl)).then(function (tempToken) { download += "?token=".concat(tempToken.key); resolve(download); }, function () { resolve(download); })["catch"](reject); }); } }, { key: "uploadFile", value: function uploadFile(storage, file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, uploadStartCallback, abortCallback, multipartOptions) { var _this5 = this; var requestArgs = { provider: storage, method: 'upload', file: file, fileName: fileName, dir: dir }; fileKey = fileKey || 'file'; var request = Formio.pluginWait('preRequest', requestArgs).then(function () { return Formio.pluginGet('fileRequest', requestArgs).then(function (result) { if (storage && isNil(result)) { var Provider = _providers["default"].getProvider('storage', storage); if (Provider) { var provider = new Provider(_this5); if (uploadStartCallback) { uploadStartCallback(); } return provider.uploadFile(file, fileName, dir, progressCallback, url, options, fileKey, groupPermissions, groupId, abortCallback, multipartOptions); } else { throw 'Storage provider not found'; } } return result || { url: '' }; }); }); return Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs); } }, { key: "downloadFile", value: function downloadFile(file, options) { var _this6 = this; var requestArgs = { method: 'download', file: file }; var request = Formio.pluginWait('preRequest', requestArgs).then(function () { return Formio.pluginGet('fileRequest', requestArgs).then(function (result) { if (file.storage && isNil(result)) { var Provider = _providers["default"].getProvider('storage', file.storage); if (Provider) { var provider = new Provider(_this6); return provider.downloadFile(file, options); } else { throw 'Storage provider not found'; } } return result || { url: '' }; }); }); return Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs); } }, { key: "deleteFile", value: function deleteFile(file, options) { var _this7 = this; var requestArgs = { method: 'delete', file: file }; var request = Formio.pluginWait('preRequest', requestArgs).then(function () { return Formio.pluginGet('fileRequest', requestArgs).then(function (result) { if (file.storage && isNil(result)) { var Provider = _providers["default"].getProvider('storage', file.storage); if (Provider) { var provider = new Provider(_this7); return provider.deleteFile(file, options); } else { throw 'Storage provider not found'; } } return result || { url: '' }; }); }); return Formio.pluginAlter('wrapFileRequestPromise', request, requestArgs); } /** * Returns the user permissions to a form and submission. * * @param user - The user or current user if undefined. For anonymous, use "null" * @param form - The form or current form if undefined. For no form check, use "null" * @param submission - The submisison or "index" if undefined. * * @return {create: boolean, read: boolean, edit: boolean, delete: boolean} */ }, { key: "userPermissions", value: function userPermissions(user, form, submission) { return _nativePromiseOnly["default"].all([form !== undefined ? _nativePromiseOnly["default"].resolve(form) : this.loadForm(), user !== undefined ? _nativePromiseOnly["default"].resolve(user) : this.currentUser(), submission !== undefined || !this.submissionId ? _nativePromiseOnly["default"].resolve(submission) : this.loadSubmission(), this.accessInfo()]).then(function (results) { var form = results.shift(); var user = results.shift() || { _id: false, roles: [] }; var submission = results.shift(); var access = results.shift(); var permMap = { create: 'create', read: 'read', update: 'edit', "delete": 'delete' }; var perms = { user: user, form: form, access: access, create: false, read: false, edit: false, "delete": false }; for (var roleName in access.roles) { if (access.roles.hasOwnProperty(roleName)) { var role = access.roles[roleName]; if (role["default"] && user._id === false) { // User is anonymous. Add the anonymous role. user.roles.push(role._id); } else if (role.admin && user.roles.indexOf(role._id) !== -1) { perms.create = true; perms.read = true; perms["delete"] = true; perms.edit = true; return perms; } } } if (form && form.submissionAccess) { for (var i = 0; i < form.submissionAccess.length; i++) { var permission = form.submissionAccess[i]; var _permission$type$spli = permission.type.split('_'), _permission$type$spli2 = _slicedToArray(_permission$type$spli, 2), perm = _permission$type$spli2[0], scope = _permission$type$spli2[1]; if (['create', 'read', 'update', 'delete'].includes(perm)) { if ((0, _intersection2["default"])(permission.roles, user.roles).length) { perms[permMap[perm]] = scope === 'all' || !submission || user._id === submission.owner; } } } } // check for Group Permissions if (submission) { // we would anyway need to loop through components for create permission, so we'll do that for all of them (0, _utils.eachComponent)(form.components, function (component, path) { if (component && component.defaultPermission) { var value = (0, _get2["default"])(submission.data, path); // make it work for single-select Group and multi-select Group var groups = Array.isArray(value) ? value : [value]; groups.forEach(function (group) { if (group && group._id && // group id is present user.roles.indexOf(group._id) > -1 // user has group id in his roles ) { if (component.defaultPermission === 'read') { perms[permMap.read] = true; } if (component.defaultPermission === 'create') { perms[permMap.create] = true; perms[permMap.read] = true; } if (component.defaultPermission === 'write') { perms[permMap.create] = true; perms[permMap.read] = true; perms[permMap.update] = true; } if (component.defaultPermission === 'admin') { perms[permMap.create] = true; perms[permMap.read] = true; perms[permMap.update] = true; perms[permMap["delete"]] = true; } } }); } }); } return perms; }); } /** * Determine if the current user can submit a form. * @return {*} */ }, { key: "canSubmit", value: function canSubmit() { var _this8 = this; return this.userPermissions().then(function (perms) { // If there is user and they cannot create, then check anonymous user permissions. if (!perms.create && Formio.getUser()) { return _this8.userPermissions(null).then(function (anonPerms) { if (anonPerms.create) { Formio.setUser(null); return true; } return false; }); } return perms.create; }); } }, { key: "getUrlParts", value: function getUrlParts(url) { return Formio.getUrlParts(url, this); } }], [{ key: "useSessionToken", value: function useSessionToken(options) { var tokenName = "".concat(options.namespace || Formio.namespace || 'formio', "Token"); var token = localStorage.getItem(tokenName); if (token) { localStorage.removeItem(tokenName); sessionStorage.setItem(tokenName, token); } var userName = "".concat(options.namespace || Formio.namespace || 'formio', "User"); var user = localStorage.getItem(userName); if (user) { localStorage.removeItem(userName); sessionStorage.setItem(userName, user); } localStorage.setItem('useSessionToken', true); } }, { key: "loadProjects", value: function loadProjects(query, opts) { query = query || ''; if (isObject(query)) { query = "?".concat(Formio.serialize(query.params)); } return Formio.makeStaticRequest("".concat(Formio.baseUrl, "/project").concat(query), 'GET', null, opts); } }, { key: "getUrlParts", value: function getUrlParts(url, formio) { var base = formio && formio.base ? formio.base : Formio.baseUrl; var regex = '^(http[s]?:\\/\\/)'; if (base && url.indexOf(base) === 0) { regex += "(".concat(base.replace(/^http[s]?:\/\//, ''), ")"); } else { regex += '([^/]+)'; } regex += '($|\\/.*)'; return url.match(new RegExp(regex)); } }, { key: "serialize", value: function serialize(obj, _interpolate) { var str = []; var interpolate = function interpolate(item) { return _interpolate ? _interpolate(item) : item; }; for (var p in obj) { if (obj.hasOwnProperty(p)) { str.push("".concat(encodeURIComponent(p), "=").concat(encodeURIComponent(interpolate(obj[p])))); } } return str.join('&'); } }, { key: "getRequestArgs", value: function getRequestArgs(formio, type, url, method, data, opts) { method = (method || 'GET').toUpperCase(); if (!opts || !isObject(opts)) { opts = {}; } var requestArgs = { url: url, method: method, data: data || null, opts: opts }; if (type) { requestArgs.type = type; } if (formio) { requestArgs.formio = formio; } return requestArgs; } }, { key: "makeStaticRequest", value: function makeStaticRequest(url, method, data, opts) { var requestArgs = Formio.getRequestArgs(null, '', url, method, data, opts); var request = Formio.pluginWait('preRequest', requestArgs).then(function () { return Formio.pluginGet('staticRequest', requestArgs).then(function (result) { if (isNil(result)) { return Formio.request(requestArgs.url, requestArgs.method, requestArgs.data, requestArgs.opts.header, requestArgs.opts); } return result; }); }); return Formio.pluginAlter('wrapStaticRequestPromise', request, requestArgs); } }, { key: "makeRequest", value: function makeRequest(formio, type, url, method, data, opts) { if (!formio) { return Formio.makeStaticRequest(url, method, data, opts); } var requestArgs = Formio.getRequestArgs(formio, type, url, method, data, opts); requestArgs.opts = requestArgs.opts || {}; requestArgs.opts.formio = formio; //for Formio requests default Accept and Content-type headers if (!requestArgs.opts.headers) { requestArgs.opts.headers = {}; } requestArgs.opts.headers = (0, _defaults2["default"])(requestArgs.opts.headers, { 'Accept': 'application/json', 'Content-type': 'application/json' }); var request = Formio.pluginWait('preRequest', requestArgs).then(function () { return Formio.pluginGet('request', requestArgs).then(function (result) { if (isNil(result)) { return Formio.request(requestArgs.url, requestArgs.method, requestArgs.data, requestArgs.opts.header, requestArgs.opts); } return result; }); }); return Formio.pluginAlter('wrapRequestPromise', request, requestArgs); } }, { key: "request", value: function request(url, method, data, header, opts) { if (!url) { return _nativePromiseOnly["default"].reject('No url provided'); } var _Formio = Formio; method = (method || 'GET').toUpperCase(); // For reverse compatibility, if they provided the ignoreCache parameter, // then change it back to the options format where that is a parameter. if (isBoolean(opts)) { opts = { ignoreCache: opts }; } if (!opts || !isObject(opts)) { opts = {}; } // Generate a cachekey. var cacheKey = btoa(encodeURI(url)); // Get the cached promise to save multiple loads. if (!opts.ignoreCache && method === 'GET' && _Formio.cache.hasOwnProperty(cacheKey)) { return _nativePromiseOnly["default"].resolve(cloneResponse(_Formio.cache[cacheKey])); } // Set up and fetch request var headers = header || new Headers(opts.headers || { 'Accept': 'application/json', 'Content-type': 'application/json' }); var token = _Formio.getToken(opts); if (token && !opts.noToken) { headers.append('x-jwt-token', token); } // The fetch-ponyfill can't handle a proper Headers class anymore. Change it back to an object. var headerObj = {}; headers.forEach(function (value, name) { headerObj[name] = value; }); var options = { method: method, headers: headerObj, mode: 'cors' }; if (data) { options.body = JSON.stringify(data); } // Allow plugins to alter the options. options = _Formio.pluginAlter('requestOptions', options, url); if (options.namespace || _Formio.namespace) { opts.namespace = options.namespace || _Formio.namespace; } var requestToken = options.headers['x-jwt-token']; var result = _Formio.pluginAlter('wrapFetchRequestPromise', _Formio.fetch(url, options), { url: url, method: method, data: data, opts: opts }).then(function (response) { // Allow plugins to respond. response = _Formio.pluginAlter('requestResponse', response, _Formio, data); if (!response.ok) { if (response.status === 440) { _Formio.setToken(null, opts); _Formio.events.emit('formio.sessionExpired', response.body); } else if (response.status === 401) { _Formio.events.emit('formio.unauthorized', response.body); } else if (response.status === 416) { _Formio.events.emit('formio.rangeIsNotSatisfiable', response.body); } else if (response.status === 504) { return _nativePromiseOnly["default"].reject(new Error('Network request failed')); } // Parse and return the error as a rejected promise to reject this promise return (response.headers.get('content-type').includes('application/json') ? response.json() : response.text()).then(function (error) { return _nativePromiseOnly["default"].reject(error); }); } // Handle fetch results var token = response.headers.get('x-jwt-token'); // In some strange cases, the fetch library will return an x-jwt-token without sending // one to the server. This has even been debugged on the server to verify that no token // was introduced with the request, but the response contains a token. This is an Invalid // case where we do not send an x-jwt-token and get one in return for any GET request. var tokenIntroduced = false; if (method === 'GET' && !requestToken && token && !opts.external && !url.includes('token=') && !url.includes('x-jwt-token=')) { console.warn('Token was introduced in request.'); tokenIntroduced = true; } if (response.status >= 200 && response.status < 300 && token && token !== '' && !tokenIntroduced) { _Formio.setToken(token, opts); } // 204 is no content. Don't try to .json() it. if (response.status === 204) { return {}; } var getResult = response.headers.get('content-type').includes('application/json') ? response.json() : response.text(); return getResult.then(function (result) { // Add some content-range metadata to the result here var range = response.headers.get('content-range'); if (range && isObject(result)) { range = range.split('/'); if (range[0] !== '*') { var skipLimit = range[0].split('-'); result.skip = Number(skipLimit[0]); result.limit = skipLimit[1] - skipLimit[0] + 1; } result.serverCount = range[1] === '*' ? range[1] : Number(range[1]); } if (!opts.getHeaders) { return result; } var headers = {}; response.headers.forEach(function (item, key) { headers[key] = item; }); // Return the result with the headers. return { result: result, headers: headers }; }); }).then(function (result) { if (opts.getHeaders) { return result; } // Cache the response. if (method === 'GET') { _Formio.cache[cacheKey] = result; } return cloneResponse(result); })["catch"](function (err) { if (err === 'Bad Token') { _Formio.setToken(null, opts); _Formio.events.emit('formio.badToken', err); } if (err.message) { err = new Error("Could not connect to API server (".concat(err.message, "): ").concat(url)); err.networkError = true; } if (method === 'GET') { delete _Formio.cache[cacheKey]; } return _nativePromiseOnly["default"].reject(err); }); return result; } // Needed to maintain reverse compatability... }, { key: "token", get: function get() { if (!Formio.tokens) { Formio.tokens = {}; } return Formio.tokens.formioToken || ''; } // Needed to maintain reverse compatability... , set: function set(token) { if (!Formio.tokens) { Formio.tokens = {}; } Formio.tokens.formioToken = token || ''; } }, { key: "setToken", value: function setToken() { var token = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var opts = arguments.length > 1 ? arguments[1] : undefined; token = token || ''; opts = typeof opts === 'string' ? { namespace: opts } : opts || {}; var tokenName = "".concat(opts.namespace || Formio.namespace || 'formio', "Token"); if (!Formio.tokens) { Formio.tokens = {}; } var storage = localStorage.getItem('useSessionToken') ? sessionStorage : localStorage; if (!token) { if (!opts.fromUser) { opts.fromToken = true; Formio.setUser(null, opts); } // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode. try { storage.removeItem(tokenName); } catch (err) { _browserCookies["default"].erase(tokenName, { path: '/' }); } Formio.tokens[tokenName] = token; return _nativePromiseOnly["default"].resolve(null); } if (Formio.tokens[tokenName] !== token) { Formio.tokens[tokenName] = token; // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode. try { storage.setItem(tokenName, token); } catch (err) { _browserCookies["default"].set(tokenName, token, { path: '/' }); } } // Return or updates the current user return this.currentUserResolved ? Formio.currentUser(opts.formio, opts) : _nativePromiseOnly["default"].resolve(null); } }, { key: "getToken", value: function getToken(options) { options = typeof options === 'string' ? { namespace: options } : options || {}; var tokenName = "".concat(options.namespace || Formio.namespace || 'formio', "Token"); var decodedTokenName = options.decode ? "".concat(tokenName, "Decoded") : tokenName; if (!Formio.tokens) { Formio.tokens = {}; } if (Formio.tokens[decodedTokenName]) { return Formio.tokens[decodedTokenName]; } try { var token = localStorage.getItem('useSessionToken') ? sessionStorage.getItem(tokenName) : localStorage.getItem(tokenName); Formio.tokens[tokenName] = token || ''; if (options.decode) { Formio.tokens[decodedTokenName] = Formio.tokens[tokenName] ? (0, _jwtDecode["default"])(Formio.tokens[tokenName]) : {}; return Formio.tokens[decodedTokenName]; } return Formio.tokens[tokenName]; } catch (e) { Formio.tokens[tokenName] = _browserCookies["default"].get(tokenName); return Formio.tokens[tokenName]; } } }, { key: "oauthLogoutURI", value: function oauthLogoutURI(uri, options) { options = typeof options === 'string' ? { namespace: options } : options || {}; var logoutURIName = "".concat(options.namespace || Formio.namespace || 'formio', "LogoutAuthUrl"); Formio.tokens[logoutURIName]; localStorage.setItem(logoutURIName, uri); return Formio.tokens[logoutURIName]; } }, { key: "setUser", value: function setUser(user) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var userName = "".concat(opts.namespace || Formio.namespace || 'formio', "User"); var storage = localStorage.getItem('useSessionToken') ? sessionStorage : localStorage; if (!user) { if (!opts.fromToken) { opts.fromUser = true; Formio.setToken(null, opts); } // Emit an event on the cleared user. Formio.events.emit('formio.user', null); // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode. try { return storage.removeItem(userName); } catch (err) { return _browserCookies["default"].erase(userName, { path: '/' }); } } // iOS in private browse mode will throw an error but we can't detect ahead of time that we are in private mode. try { storage.setItem(userName, JSON.stringify(user)); } catch (err) { _browserCookies["default"].set(userName, JSON.stringify(user), { path: '/' }); } // Emit an event on the authenticated user. Formio.events.emit('formio.user', user); } }, { key: "getUser", value: function getUser(options) { options = options || {}; var userName = "".concat(options.namespace || Formio.namespace || 'formio', "User"); try { return JSON.parse((localStorage.getItem('useSessionToken') ? sessionStorage : localStorage).getItem(userName) || null); } catch (e) { return JSON.parse(_browserCookies["default"].get(userName)); } } }, { key: "setBaseUrl", value: function setBaseUrl(url) { Formio.baseUrl = url; if