Clean up tests

This commit is contained in:
Maxime Rainville 2020-06-12 00:55:12 +12:00
parent df120133ab
commit 25978d3c58
7 changed files with 511 additions and 805 deletions

View File

@ -1 +1 @@
!function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={i:o,l:!1,exports:{}};return e[o].call(n.exports,n,n.exports,t),n.l=!0,n.exports}var r={};t.m=e,t.c=r,t.i=function(e){return e},t.d=function(e,r,o){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle-cms.js")}({"./client/src/bundles/ConfirmFolder.js":function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},s=r(4),i=o(s),a=r(0),l=o(a),h=r(2),u=o(h),c=r(3),d=o(c),f=r(1),p=r("./node_modules/url/url.js"),m=o(p),v=r(5),F=o(v),g=(0,f.loadComponent)("FormBuilderModal");l.default.entwine("ss",function(e){function t(t,r,o){t?(e(r).show(),e(o).hide()):(e(o).show(),e(r).hide())}e("#Form_EditForm_Fields").entwine({onmatch:function(){var e=this;this._super(),this.on("addnewinline",function(){e.one("reload",function(){e.find(".ss-gridfield-item").last().find(".col-ClassName select").attr("data-folderconfirmed",0)})})}}),e("#Form_ConfirmFolderForm_FolderOptions-new").entwine({onmatch:function(){e("#Form_ConfirmFolderForm_CreateFolder_Holder").detach().appendTo(e("#Form_ConfirmFolderForm_FolderOptions-new").parent().parent()),t(e(this).prop("checked"),"#Form_ConfirmFolderForm_CreateFolder_Holder","#Form_ConfirmFolderForm_FolderID_Holder")},onchange:function(){t(e(this).prop("checked"),"#Form_ConfirmFolderForm_CreateFolder_Holder","#Form_ConfirmFolderForm_FolderID_Holder")}}),e("#Form_ConfirmFolderForm_FolderOptions-existing").entwine({onmatch:function(){e("#Form_ConfirmFolderForm_FolderID_Holder").detach().appendTo(e("#Form_ConfirmFolderForm_FolderOptions-existing").parent().parent()),t(e(this).prop("checked"),"#Form_ConfirmFolderForm_FolderID_Holder","#Form_ConfirmFolderForm_CreateFolder_Holder")},onchange:function(){t(e(this).prop("checked"),"#Form_ConfirmFolderForm_FolderID_Holder","#Form_ConfirmFolderForm_CreateFolder_Holder")}}),e("#Form_ConfirmFolderForm_FolderID_Holder .treedropdownfield.is-open,#Form_ItemEditForm_FolderID .treedropdownfield.is-open").entwine({onunmatch:function(){var t=this,r=m.default.parse("UserDefinedFormController/getfoldergrouppermissions"),o=F.default.parse(r.query);o.FolderID=e(this).find("input[name=FolderID]").val();var s=m.default.format(n({},r,{search:F.default.stringify(o)}));return fetch(s,{credentials:"same-origin"}).then(function(e){return e.json()}).then(function(r){return e(t).siblings(".form__field-description").html(r),e(t).parent().siblings(".form__field-description").html(r),r}).catch(function(e){l.default.noticeAdd({text:e.message,stay:!1,type:"error"})})}}),e(".uf-field-editor .ss-gridfield-items .dropdown.editable-column-field.form-group--no-label:not([data-folderconfirmed='1'])").entwine({onchange:function(){if("SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFileField"===this.get(0).value&&!e(".uf-field-editor .ss-gridfield-items .dropdown.editable-column-field.form-group--no-label[data-folderconfirmed='1']").length){var t=e("#confirm-folder__dialog-wrapper");t.length&&t.remove(),t=e('<div id="confirm-folder__dialog-wrapper" />');var r=e(this).closest("tr").data("id");t.data("id",r),e("body").append(t),t.open()}}}),e("#confirm-folder__dialog-wrapper").entwine({onunmatch:function(){this._clearModal()},open:function(){this._renderModal(!0)},close:function(t){if(!t){var r=e("#confirm-folder__dialog-wrapper").data("id");e(".ss-gridfield-item[data-id='"+r+"'] .dropdown.editable-column-field.form-group--no-label[data-folderconfirmed='0']").val("SilverStripe\\UserForms\\Model\\EditableFormField\\EditableTextField")}this._renderModal(!1)},_renderModal:function(t){var r=this,o=function(){return r._handleHideModal.apply(r,arguments)},s=function(){return r._handleSubmitModal.apply(r,arguments)},a=i.default._t("UserForms.FILE_CONFIRMATION_TITLE","Select file upload folder"),l=e(this).data("id"),h=m.default.parse("admin/user-forms/confirmfolderformschema"),c=F.default.parse(h.query);c.ID=l;var f=m.default.format(n({},h,{search:F.default.stringify(c)}));d.default.render(u.default.createElement(g,{title:a,isOpen:t,onSubmit:s,onClosed:o,schemaUrl:f,bodyClassName:"modal__dialog",className:"confirm-folder-modal",responseClassBad:"modal__response modal__response--error",responseClassGood:"modal__response modal__response--good",identifier:"UserForms.ConfirmFolder"}),this[0])},_clearModal:function(){d.default.unmountComponentAtNode(this[0])},_handleHideModal:function(){return this.close()},_handleSubmitModal:function(t,r,o){var n=this;return o().then(function(){l.default.noticeAdd({text:i.default._t("UserForms.FILE_CONFIRMATION_CONFIRMATION","Folder confirmed successfully."),stay:!1,type:"success"}),n.close(!0),e("[name=action_doSave], [name=action_save]").click()}).catch(function(e){l.default.noticeAdd({text:e.message,stay:!1,type:"error"})})}}),e("#Form_ConfirmFolderForm_action_cancel").entwine({onclick:function(){e("#confirm-folder__dialog-wrapper").close()}})})},"./client/src/bundles/FieldEditor.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t=null;e(".uf-field-editor .ss-gridfield-items").entwine({onmatch:function(){var r=0,o=0,n=e(".uf-field-editor .ss-gridfield-buttonrow").addClass("sticky-buttons"),s=e(".cms-content-header.north").first().height()+parseInt(e(".sticky-buttons").css("padding-top"),10),i=e(".uf-field-editor");this._super(),this.find(".ss-gridfield-item").each(function(t,n){switch(e(n).data("class")){case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFormStep":return void(o=0);case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroup":o+=1,r=o;break;case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd":r=o,o-=1;break;default:r=o}e(n).toggleClass("infieldgroup",r>0);for(var s=1;s<=5;s++)e(n).toggleClass("infieldgroup-level-"+s,r>=s)}),t=setInterval(function(){var e=i.offset().top;n.width("100%"),e>s||0===e?n.removeClass("sticky-buttons"):n.addClass("sticky-buttons")},300)},onunmatch:function(){this._super(),clearInterval(t)}}),e(".uf-field-editor .ss-gridfield-buttonrow .action").entwine({onclick:function(e){this._super(e),this.trigger("addnewinline")}}),e(".uf-field-editor").entwine({onmatch:function(){var t=this;this._super(),this.on("addnewinline",function(){t.one("reload",function(){var r=t.find(".ss-gridfield-item").last(),o=null;"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd"===r.attr("data-class")?(o=r,o.prev().find(".col-Title input").focus(),r=o.add(o.prev()),o.css("visibility","hidden")):r.find(".col-Title input").focus(),r.addClass("flashBackground");var n=e(".cms-content-fields");n.length>0&&n.scrollTop(n[0].scrollHeight),o&&o.css("visibility","visible")})})},onummatch:function(){this._super()}})})},"./client/src/bundles/Recipient.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t={updateFormatSpecificFields:function(){var t=e('input[name="SendPlain"]').is(":checked");e(".field.toggle-html-only")[t?"hide":"show"](),e(".field.toggle-plain-only")[t?"show":"hide"]()}};e("#Form_ItemEditForm .EmailRecipientForm").entwine({onmatch:function(){t.updateFormatSpecificFields()},onunmatch:function(){(void 0)._super()}}),e('#Form_ItemEditForm .EmailRecipientForm input[name="SendPlain"]').entwine({onchange:function(){t.updateFormatSpecificFields()}})})},"./client/src/bundles/bundle-cms.js":function(e,t,r){"use strict";r("./client/src/bundles/FieldEditor.js"),r("./client/src/bundles/ConfirmFolder.js"),r("./client/src/bundles/Recipient.js")},"./node_modules/punycode/punycode.js":function(e,t,r){(function(e,o){var n;!function(o){function s(e){throw new RangeError(E[e])}function i(e,t){for(var r=e.length,o=[];r--;)o[r]=t(e[r]);return o}function a(e,t){var r=e.split("@"),o="";return r.length>1&&(o=r[0]+"@",e=r[1]),e=e.replace(A,"."),o+i(e.split("."),t).join(".")}function l(e){for(var t,r,o=[],n=0,s=e.length;n<s;)t=e.charCodeAt(n++),t>=55296&&t<=56319&&n<s?(r=e.charCodeAt(n++),56320==(64512&r)?o.push(((1023&t)<<10)+(1023&r)+65536):(o.push(t),n--)):o.push(t);return o}function h(e){return i(e,function(e){var t="";return e>65535&&(e-=65536,t+=U(e>>>10&1023|55296),e=56320|1023&e),t+=U(e)}).join("")}function u(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:_}function c(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function d(e,t,r){var o=0;for(e=r?k(e/w):e>>1,e+=k(e/t);e>q*y>>1;o+=_)e=k(e/q);return k(o+(q+1)*e/(e+j))}function f(e){var t,r,o,n,i,a,l,c,f,p,m=[],v=e.length,F=0,j=O,w=C;for(r=e.lastIndexOf(x),r<0&&(r=0),o=0;o<r;++o)e.charCodeAt(o)>=128&&s("not-basic"),m.push(e.charCodeAt(o));for(n=r>0?r+1:0;n<v;){for(i=F,a=1,l=_;n>=v&&s("invalid-input"),c=u(e.charCodeAt(n++)),(c>=_||c>k((g-F)/a))&&s("overflow"),F+=c*a,f=l<=w?b:l>=w+y?y:l-w,!(c<f);l+=_)p=_-f,a>k(g/p)&&s("overflow"),a*=p;t=m.length+1,w=d(F-i,t,0==i),k(F/t)>g-j&&s("overflow"),j+=k(F/t),F%=t,m.splice(F++,0,j)}return h(m)}function p(e){var t,r,o,n,i,a,h,u,f,p,m,v,F,j,w,I=[];for(e=l(e),v=e.length,t=O,r=0,i=C,a=0;a<v;++a)(m=e[a])<128&&I.push(U(m));for(o=n=I.length,n&&I.push(x);o<v;){for(h=g,a=0;a<v;++a)(m=e[a])>=t&&m<h&&(h=m);for(F=o+1,h-t>k((g-r)/F)&&s("overflow"),r+=(h-t)*F,t=h,a=0;a<v;++a)if(m=e[a],m<t&&++r>g&&s("overflow"),m==t){for(u=r,f=_;p=f<=i?b:f>=i+y?y:f-i,!(u<p);f+=_)w=u-p,j=_-p,I.push(U(c(p+w%j,0))),u=k(w/j);I.push(U(c(u,0))),i=d(r,F,o==n),r=0,++o}++r,++t}return I.join("")}function m(e){return a(e,function(e){return I.test(e)?f(e.slice(4).toLowerCase()):e})}function v(e){return a(e,function(e){return S.test(e)?"xn--"+p(e):e})}var F,g=("object"==typeof t&&t&&t.nodeType,"object"==typeof e&&e&&e.nodeType,2147483647),_=36,b=1,y=26,j=38,w=700,C=72,O=128,x="-",I=/^xn--/,S=/[^\x20-\x7E]/,A=/[\x2E\u3002\uFF0E\uFF61]/g,E={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},q=_-b,k=Math.floor,U=String.fromCharCode;F={version:"1.4.1",ucs2:{decode:l,encode:h},decode:f,encode:p,toASCII:v,toUnicode:m},void 0!==(n=function(){return F}.call(t,r,t,e))&&(e.exports=n)}()}).call(t,r("./node_modules/webpack/buildin/module.js")(e),r("./node_modules/webpack/buildin/global.js"))},"./node_modules/querystring-es3/decode.js":function(e,t,r){"use strict";function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,r,s){t=t||"&",r=r||"=";var i={};if("string"!=typeof e||0===e.length)return i;var a=/\+/g;e=e.split(t);var l=1e3;s&&"number"==typeof s.maxKeys&&(l=s.maxKeys);var h=e.length;l>0&&h>l&&(h=l);for(var u=0;u<h;++u){var c,d,f,p,m=e[u].replace(a,"%20"),v=m.indexOf(r);v>=0?(c=m.substr(0,v),d=m.substr(v+1)):(c=m,d=""),f=decodeURIComponent(c),p=decodeURIComponent(d),o(i,f)?n(i[f])?i[f].push(p):i[f]=[i[f],p]:i[f]=p}return i};var n=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},"./node_modules/querystring-es3/encode.js":function(e,t,r){"use strict";function o(e,t){if(e.map)return e.map(t);for(var r=[],o=0;o<e.length;o++)r.push(t(e[o],o));return r}var n=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,r,a){return t=t||"&",r=r||"=",null===e&&(e=void 0),"object"==typeof e?o(i(e),function(i){var a=encodeURIComponent(n(i))+r;return s(e[i])?o(e[i],function(e){return a+encodeURIComponent(n(e))}).join(t):a+encodeURIComponent(n(e[i]))}).join(t):a?encodeURIComponent(n(a))+r+encodeURIComponent(n(e)):""};var s=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},i=Object.keys||function(e){var t=[];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.push(r);return t}},"./node_modules/querystring-es3/index.js":function(e,t,r){"use strict";t.decode=t.parse=r("./node_modules/querystring-es3/decode.js"),t.encode=t.stringify=r("./node_modules/querystring-es3/encode.js")},"./node_modules/url/url.js":function(e,t,r){"use strict";function o(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}function n(e,t,r){if(e&&h.isObject(e)&&e instanceof o)return e;var n=new o;return n.parse(e,t,r),n}function s(e){return h.isString(e)&&(e=n(e)),e instanceof o?e.format():o.prototype.format.call(e)}function i(e,t){return n(e,!1,!0).resolve(t)}function a(e,t){return e?n(e,!1,!0).resolveObject(t):t}var l=r("./node_modules/punycode/punycode.js"),h=r("./node_modules/url/util.js");t.parse=n,t.resolve=i,t.resolveObject=a,t.format=s,t.Url=o;var u=/^([a-z0-9.+-]+:)/i,c=/:[0-9]*$/,d=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,f=["<",">",'"',"`"," ","\r","\n","\t"],p=["{","}","|","\\","^","`"].concat(f),m=["'"].concat(p),v=["%","/","?",";","#"].concat(m),F=["/","?","#"],g=/^[+a-z0-9A-Z_-]{0,63}$/,_=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},j={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=r("./node_modules/querystring-es3/index.js");o.prototype.parse=function(e,t,r){if(!h.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),n=-1!==o&&o<e.indexOf("#")?"?":"#",s=e.split(n),i=/\\/g;s[0]=s[0].replace(i,"/"),e=s.join(n);var a=e;if(a=a.trim(),!r&&1===e.split("#").length){var c=d.exec(a);if(c)return this.path=a,this.href=a,this.pathname=c[1],c[2]?(this.search=c[2],this.query=t?w.parse(this.search.substr(1)):this.search.substr(1)):t&&(this.search="",this.query={}),this}var f=u.exec(a);if(f){f=f[0];var p=f.toLowerCase();this.protocol=p,a=a.substr(f.length)}if(r||f||a.match(/^\/\/[^@\/]+@[^@\/]+/)){var C="//"===a.substr(0,2);!C||f&&y[f]||(a=a.substr(2),this.slashes=!0)}if(!y[f]&&(C||f&&!j[f])){for(var O=-1,x=0;x<F.length;x++){var I=a.indexOf(F[x]);-1!==I&&(-1===O||I<O)&&(O=I)}var S,A;A=-1===O?a.lastIndexOf("@"):a.lastIndexOf("@",O),-1!==A&&(S=a.slice(0,A),a=a.slice(A+1),this.auth=decodeURIComponent(S)),O=-1;for(var x=0;x<v.length;x++){var I=a.indexOf(v[x]);-1!==I&&(-1===O||I<O)&&(O=I)}-1===O&&(O=a.length),this.host=a.slice(0,O),a=a.slice(O),this.parseHost(),this.hostname=this.hostname||"";var E="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!E)for(var q=this.hostname.split(/\./),x=0,k=q.length;x<k;x++){var U=q[x];if(U&&!U.match(g)){for(var M="",R=0,N=U.length;R<N;R++)U.charCodeAt(R)>127?M+="x":M+=U[R];if(!M.match(g)){var H=q.slice(0,x),T=q.slice(x+1),D=U.match(_);D&&(H.push(D[1]),T.unshift(D[2])),T.length&&(a="/"+T.join(".")+a),this.hostname=H.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),E||(this.hostname=l.toASCII(this.hostname));var P=this.port?":"+this.port:"",L=this.hostname||"";this.host=L+P,this.href+=this.host,E&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==a[0]&&(a="/"+a))}if(!b[p])for(var x=0,k=m.length;x<k;x++){var G=m[x];if(-1!==a.indexOf(G)){var $=encodeURIComponent(G);$===G&&($=escape(G)),a=a.split(G).join($)}}var z=a.indexOf("#");-1!==z&&(this.hash=a.substr(z),a=a.slice(0,z));var B=a.indexOf("?");if(-1!==B?(this.search=a.substr(B),this.query=a.substr(B+1),t&&(this.query=w.parse(this.query)),a=a.slice(0,B)):t&&(this.search="",this.query={}),a&&(this.pathname=a),j[p]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){var P=this.pathname||"",K=this.search||"";this.path=P+K}return this.href=this.format(),this},o.prototype.format=function(){var e=this.auth||"";e&&(e=encodeURIComponent(e),e=e.replace(/%3A/i,":"),e+="@");var t=this.protocol||"",r=this.pathname||"",o=this.hash||"",n=!1,s="";this.host?n=e+this.host:this.hostname&&(n=e+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(n+=":"+this.port)),this.query&&h.isObject(this.query)&&Object.keys(this.query).length&&(s=w.stringify(this.query));var i=this.search||s&&"?"+s||"";return t&&":"!==t.substr(-1)&&(t+=":"),this.slashes||(!t||j[t])&&!1!==n?(n="//"+(n||""),r&&"/"!==r.charAt(0)&&(r="/"+r)):n||(n=""),o&&"#"!==o.charAt(0)&&(o="#"+o),i&&"?"!==i.charAt(0)&&(i="?"+i),r=r.replace(/[?#]/g,function(e){return encodeURIComponent(e)}),i=i.replace("#","%23"),t+n+r+i+o},o.prototype.resolve=function(e){return this.resolveObject(n(e,!1,!0)).format()},o.prototype.resolveObject=function(e){if(h.isString(e)){var t=new o;t.parse(e,!1,!0),e=t}for(var r=new o,n=Object.keys(this),s=0;s<n.length;s++){var i=n[s];r[i]=this[i]}if(r.hash=e.hash,""===e.href)return r.href=r.format(),r;if(e.slashes&&!e.protocol){for(var a=Object.keys(e),l=0;l<a.length;l++){var u=a[l];"protocol"!==u&&(r[u]=e[u])}return j[r.protocol]&&r.hostname&&!r.pathname&&(r.path=r.pathname="/"),r.href=r.format(),r}if(e.protocol&&e.protocol!==r.protocol){if(!j[e.protocol]){for(var c=Object.keys(e),d=0;d<c.length;d++){var f=c[d];r[f]=e[f]}return r.href=r.format(),r}if(r.protocol=e.protocol,e.host||y[e.protocol])r.pathname=e.pathname;else{for(var p=(e.pathname||"").split("/");p.length&&!(e.host=p.shift()););e.host||(e.host=""),e.hostname||(e.hostname=""),""!==p[0]&&p.unshift(""),p.length<2&&p.unshift(""),r.pathname=p.join("/")}if(r.search=e.search,r.query=e.query,r.host=e.host||"",r.auth=e.auth,r.hostname=e.hostname||e.host,r.port=e.port,r.pathname||r.search){var m=r.pathname||"",v=r.search||"";r.path=m+v}return r.slashes=r.slashes||e.slashes,r.href=r.format(),r}var F=r.pathname&&"/"===r.pathname.charAt(0),g=e.host||e.pathname&&"/"===e.pathname.charAt(0),_=g||F||r.host&&e.pathname,b=_,w=r.pathname&&r.pathname.split("/")||[],p=e.pathname&&e.pathname.split("/")||[],C=r.protocol&&!j[r.protocol];if(C&&(r.hostname="",r.port=null,r.host&&(""===w[0]?w[0]=r.host:w.unshift(r.host)),r.host="",e.protocol&&(e.hostname=null,e.port=null,e.host&&(""===p[0]?p[0]=e.host:p.unshift(e.host)),e.host=null),_=_&&(""===p[0]||""===w[0])),g)r.host=e.host||""===e.host?e.host:r.host,r.hostname=e.hostname||""===e.hostname?e.hostname:r.hostname,r.search=e.search,r.query=e.query,w=p;else if(p.length)w||(w=[]),w.pop(),w=w.concat(p),r.search=e.search,r.query=e.query;else if(!h.isNullOrUndefined(e.search)){if(C){r.hostname=r.host=w.shift();var O=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return r.search=e.search,r.query=e.query,h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!w.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var x=w.slice(-1)[0],I=(r.host||e.host||w.length>1)&&("."===x||".."===x)||""===x,S=0,A=w.length;A>=0;A--)x=w[A],"."===x?w.splice(A,1):".."===x?(w.splice(A,1),S++):S&&(w.splice(A,1),S--);if(!_&&!b)for(;S--;S)w.unshift("..");!_||""===w[0]||w[0]&&"/"===w[0].charAt(0)||w.unshift(""),I&&"/"!==w.join("/").substr(-1)&&w.push("");var E=""===w[0]||w[0]&&"/"===w[0].charAt(0);if(C){r.hostname=r.host=E?"":w.length?w.shift():"";var O=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return _=_||r.host&&w.length,_&&!E&&w.unshift(""),w.length?r.pathname=w.join("/"):(r.pathname=null,r.path=null),h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=e.auth||r.auth,r.slashes=r.slashes||e.slashes,r.href=r.format(),r},o.prototype.parseHost=function(){var e=this.host,t=c.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},"./node_modules/url/util.js":function(e,t,r){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},"./node_modules/webpack/buildin/global.js":function(e,t){var r;r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(r=window)}e.exports=r},"./node_modules/webpack/buildin/module.js":function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=Injector},2:function(e,t){e.exports=React},3:function(e,t){e.exports=ReactDom},4:function(e,t){e.exports=i18n},5:function(e,t){e.exports=qs}});
!function(e){function t(o){if(r[o])return r[o].exports;var n=r[o]={i:o,l:!1,exports:{}};return e[o].call(n.exports,n,n.exports,t),n.l=!0,n.exports}var r={};t.m=e,t.c=r,t.i=function(e){return e},t.d=function(e,r,o){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s="./client/src/bundles/bundle-cms.js")}({"./client/src/bundles/ConfirmFolder.js":function(e,t,r){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var n=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var o in r)Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o])}return e},s=r(4),i=o(s),a=r(0),l=o(a),h=r(2),u=o(h),c=r(3),d=o(c),f=r(1),p=r("./node_modules/url/url.js"),m=o(p),v=r(5),F=o(v),g=(0,f.loadComponent)("FormBuilderModal");l.default.entwine("ss",function(e){function t(t,r,o){t?(e(r).show(),e(o).hide()):(e(o).show(),e(r).hide())}e("#Form_EditForm_Fields").entwine({onmatch:function(){var e=this;this._super(),this.on("addnewinline",function(){e.one("reload",function(){e.find(".ss-gridfield-item").last().find(".col-ClassName select").attr("data-folderconfirmed",0)})})}}),e("#Form_ConfirmFolderForm_FolderOptions-new").entwine({onmatch:function(){e("#Form_ConfirmFolderForm_CreateFolder_Holder").detach().appendTo(e("#Form_ConfirmFolderForm_FolderOptions-new").parent().parent()),t(e(this).prop("checked"),"#Form_ConfirmFolderForm_CreateFolder_Holder","#Form_ConfirmFolderForm_FolderID_Holder")},onchange:function(){t(e(this).prop("checked"),"#Form_ConfirmFolderForm_CreateFolder_Holder","#Form_ConfirmFolderForm_FolderID_Holder")}}),e("#Form_ConfirmFolderForm_FolderOptions-existing").entwine({onmatch:function(){e("#Form_ConfirmFolderForm_FolderID_Holder").detach().appendTo(e("#Form_ConfirmFolderForm_FolderOptions-existing").parent().parent()),t(e(this).prop("checked"),"#Form_ConfirmFolderForm_FolderID_Holder","#Form_ConfirmFolderForm_CreateFolder_Holder")},onchange:function(){t(e(this).prop("checked"),"#Form_ConfirmFolderForm_FolderID_Holder","#Form_ConfirmFolderForm_CreateFolder_Holder")}}),e("#Form_ConfirmFolderForm_FolderID_Holder .treedropdownfield.is-open,#Form_ItemEditForm_FolderID .treedropdownfield.is-open").entwine({onunmatch:function(){var t=this,r=m.default.parse("admin/user-forms/getfoldergrouppermissions"),o=F.default.parse(r.query);o.FolderID=e(this).find("input[name=FolderID]").val();var s=m.default.format(n({},r,{search:F.default.stringify(o)}));return fetch(s,{credentials:"same-origin"}).then(function(e){return e.json()}).then(function(r){return e(t).siblings(".form__field-description").html(r),e(t).parent().siblings(".form__field-description").html(r),r}).catch(function(e){l.default.noticeAdd({text:e.message,stay:!1,type:"error"})})}}),e(".uf-field-editor .ss-gridfield-items .dropdown.editable-column-field.form-group--no-label:not([data-folderconfirmed='1'])").entwine({onchange:function(){if("SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFileField"===this.get(0).value&&!e(".uf-field-editor .ss-gridfield-items .dropdown.editable-column-field.form-group--no-label[data-folderconfirmed='1']").length){var t=e("#confirm-folder__dialog-wrapper");t.length&&t.remove(),t=e('<div id="confirm-folder__dialog-wrapper" />');var r=e(this).closest("tr").data("id");t.data("id",r),e("body").append(t),t.open()}}}),e("#confirm-folder__dialog-wrapper").entwine({onunmatch:function(){this._clearModal()},open:function(){this._renderModal(!0)},close:function(t){if(!t){var r=e("#confirm-folder__dialog-wrapper").data("id");e(".ss-gridfield-item[data-id='"+r+"'] .dropdown.editable-column-field.form-group--no-label[data-folderconfirmed='0']").val("SilverStripe\\UserForms\\Model\\EditableFormField\\EditableTextField")}this._renderModal(!1)},_renderModal:function(t){var r=this,o=function(){return r._handleHideModal.apply(r,arguments)},s=function(){return r._handleSubmitModal.apply(r,arguments)},a=i.default._t("UserForms.FILE_CONFIRMATION_TITLE","Select file upload folder"),l=e(this).data("id"),h=m.default.parse("admin/user-forms/confirmfolderformschema"),c=F.default.parse(h.query);c.ID=l;var f=m.default.format(n({},h,{search:F.default.stringify(c)}));d.default.render(u.default.createElement(g,{title:a,isOpen:t,onSubmit:s,onClosed:o,schemaUrl:f,bodyClassName:"modal__dialog",className:"confirm-folder-modal",responseClassBad:"modal__response modal__response--error",responseClassGood:"modal__response modal__response--good",identifier:"UserForms.ConfirmFolder"}),this[0])},_clearModal:function(){d.default.unmountComponentAtNode(this[0])},_handleHideModal:function(){return this.close()},_handleSubmitModal:function(t,r,o){var n=this;return o().then(function(){l.default.noticeAdd({text:i.default._t("UserForms.FILE_CONFIRMATION_CONFIRMATION","Folder confirmed successfully."),stay:!1,type:"success"}),n.close(!0),e("[name=action_doSave], [name=action_save]").click()}).catch(function(e){l.default.noticeAdd({text:e.message,stay:!1,type:"error"})})}}),e("#Form_ConfirmFolderForm_action_cancel").entwine({onclick:function(){e("#confirm-folder__dialog-wrapper").close()}})})},"./client/src/bundles/FieldEditor.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t=null;e(".uf-field-editor .ss-gridfield-items").entwine({onmatch:function(){var r=0,o=0,n=e(".uf-field-editor .ss-gridfield-buttonrow").addClass("sticky-buttons"),s=e(".cms-content-header.north").first().height()+parseInt(e(".sticky-buttons").css("padding-top"),10),i=e(".uf-field-editor");this._super(),this.find(".ss-gridfield-item").each(function(t,n){switch(e(n).data("class")){case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFormStep":return void(o=0);case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroup":o+=1,r=o;break;case"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd":r=o,o-=1;break;default:r=o}e(n).toggleClass("infieldgroup",r>0);for(var s=1;s<=5;s++)e(n).toggleClass("infieldgroup-level-"+s,r>=s)}),t=setInterval(function(){var e=i.offset().top;n.width("100%"),e>s||0===e?n.removeClass("sticky-buttons"):n.addClass("sticky-buttons")},300)},onunmatch:function(){this._super(),clearInterval(t)}}),e(".uf-field-editor .ss-gridfield-buttonrow .action").entwine({onclick:function(e){this._super(e),this.trigger("addnewinline")}}),e(".uf-field-editor").entwine({onmatch:function(){var t=this;this._super(),this.on("addnewinline",function(){t.one("reload",function(){var r=t.find(".ss-gridfield-item").last(),o=null;"SilverStripe\\UserForms\\Model\\EditableFormField\\EditableFieldGroupEnd"===r.attr("data-class")?(o=r,o.prev().find(".col-Title input").focus(),r=o.add(o.prev()),o.css("visibility","hidden")):r.find(".col-Title input").focus(),r.addClass("flashBackground");var n=e(".cms-content-fields");n.length>0&&n.scrollTop(n[0].scrollHeight),o&&o.css("visibility","visible")})})},onummatch:function(){this._super()}})})},"./client/src/bundles/Recipient.js":function(e,t,r){"use strict";var o=r(0);(function(e){return e&&e.__esModule?e:{default:e}})(o).default.entwine("ss",function(e){var t={updateFormatSpecificFields:function(){var t=e('input[name="SendPlain"]').is(":checked");e(".field.toggle-html-only")[t?"hide":"show"](),e(".field.toggle-plain-only")[t?"show":"hide"]()}};e("#Form_ItemEditForm .EmailRecipientForm").entwine({onmatch:function(){t.updateFormatSpecificFields()},onunmatch:function(){(void 0)._super()}}),e('#Form_ItemEditForm .EmailRecipientForm input[name="SendPlain"]').entwine({onchange:function(){t.updateFormatSpecificFields()}})})},"./client/src/bundles/bundle-cms.js":function(e,t,r){"use strict";r("./client/src/bundles/FieldEditor.js"),r("./client/src/bundles/ConfirmFolder.js"),r("./client/src/bundles/Recipient.js")},"./node_modules/punycode/punycode.js":function(e,t,r){(function(e,o){var n;!function(o){function s(e){throw new RangeError(E[e])}function i(e,t){for(var r=e.length,o=[];r--;)o[r]=t(e[r]);return o}function a(e,t){var r=e.split("@"),o="";return r.length>1&&(o=r[0]+"@",e=r[1]),e=e.replace(A,"."),o+i(e.split("."),t).join(".")}function l(e){for(var t,r,o=[],n=0,s=e.length;n<s;)t=e.charCodeAt(n++),t>=55296&&t<=56319&&n<s?(r=e.charCodeAt(n++),56320==(64512&r)?o.push(((1023&t)<<10)+(1023&r)+65536):(o.push(t),n--)):o.push(t);return o}function h(e){return i(e,function(e){var t="";return e>65535&&(e-=65536,t+=U(e>>>10&1023|55296),e=56320|1023&e),t+=U(e)}).join("")}function u(e){return e-48<10?e-22:e-65<26?e-65:e-97<26?e-97:_}function c(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function d(e,t,r){var o=0;for(e=r?k(e/w):e>>1,e+=k(e/t);e>q*y>>1;o+=_)e=k(e/q);return k(o+(q+1)*e/(e+j))}function f(e){var t,r,o,n,i,a,l,c,f,p,m=[],v=e.length,F=0,j=O,w=C;for(r=e.lastIndexOf(x),r<0&&(r=0),o=0;o<r;++o)e.charCodeAt(o)>=128&&s("not-basic"),m.push(e.charCodeAt(o));for(n=r>0?r+1:0;n<v;){for(i=F,a=1,l=_;n>=v&&s("invalid-input"),c=u(e.charCodeAt(n++)),(c>=_||c>k((g-F)/a))&&s("overflow"),F+=c*a,f=l<=w?b:l>=w+y?y:l-w,!(c<f);l+=_)p=_-f,a>k(g/p)&&s("overflow"),a*=p;t=m.length+1,w=d(F-i,t,0==i),k(F/t)>g-j&&s("overflow"),j+=k(F/t),F%=t,m.splice(F++,0,j)}return h(m)}function p(e){var t,r,o,n,i,a,h,u,f,p,m,v,F,j,w,I=[];for(e=l(e),v=e.length,t=O,r=0,i=C,a=0;a<v;++a)(m=e[a])<128&&I.push(U(m));for(o=n=I.length,n&&I.push(x);o<v;){for(h=g,a=0;a<v;++a)(m=e[a])>=t&&m<h&&(h=m);for(F=o+1,h-t>k((g-r)/F)&&s("overflow"),r+=(h-t)*F,t=h,a=0;a<v;++a)if(m=e[a],m<t&&++r>g&&s("overflow"),m==t){for(u=r,f=_;p=f<=i?b:f>=i+y?y:f-i,!(u<p);f+=_)w=u-p,j=_-p,I.push(U(c(p+w%j,0))),u=k(w/j);I.push(U(c(u,0))),i=d(r,F,o==n),r=0,++o}++r,++t}return I.join("")}function m(e){return a(e,function(e){return I.test(e)?f(e.slice(4).toLowerCase()):e})}function v(e){return a(e,function(e){return S.test(e)?"xn--"+p(e):e})}var F,g=("object"==typeof t&&t&&t.nodeType,"object"==typeof e&&e&&e.nodeType,2147483647),_=36,b=1,y=26,j=38,w=700,C=72,O=128,x="-",I=/^xn--/,S=/[^\x20-\x7E]/,A=/[\x2E\u3002\uFF0E\uFF61]/g,E={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},q=_-b,k=Math.floor,U=String.fromCharCode;F={version:"1.4.1",ucs2:{decode:l,encode:h},decode:f,encode:p,toASCII:v,toUnicode:m},void 0!==(n=function(){return F}.call(t,r,t,e))&&(e.exports=n)}()}).call(t,r("./node_modules/webpack/buildin/module.js")(e),r("./node_modules/webpack/buildin/global.js"))},"./node_modules/querystring-es3/decode.js":function(e,t,r){"use strict";function o(e,t){return Object.prototype.hasOwnProperty.call(e,t)}e.exports=function(e,t,r,s){t=t||"&",r=r||"=";var i={};if("string"!=typeof e||0===e.length)return i;var a=/\+/g;e=e.split(t);var l=1e3;s&&"number"==typeof s.maxKeys&&(l=s.maxKeys);var h=e.length;l>0&&h>l&&(h=l);for(var u=0;u<h;++u){var c,d,f,p,m=e[u].replace(a,"%20"),v=m.indexOf(r);v>=0?(c=m.substr(0,v),d=m.substr(v+1)):(c=m,d=""),f=decodeURIComponent(c),p=decodeURIComponent(d),o(i,f)?n(i[f])?i[f].push(p):i[f]=[i[f],p]:i[f]=p}return i};var n=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)}},"./node_modules/querystring-es3/encode.js":function(e,t,r){"use strict";function o(e,t){if(e.map)return e.map(t);for(var r=[],o=0;o<e.length;o++)r.push(t(e[o],o));return r}var n=function(e){switch(typeof e){case"string":return e;case"boolean":return e?"true":"false";case"number":return isFinite(e)?e:"";default:return""}};e.exports=function(e,t,r,a){return t=t||"&",r=r||"=",null===e&&(e=void 0),"object"==typeof e?o(i(e),function(i){var a=encodeURIComponent(n(i))+r;return s(e[i])?o(e[i],function(e){return a+encodeURIComponent(n(e))}).join(t):a+encodeURIComponent(n(e[i]))}).join(t):a?encodeURIComponent(n(a))+r+encodeURIComponent(n(e)):""};var s=Array.isArray||function(e){return"[object Array]"===Object.prototype.toString.call(e)},i=Object.keys||function(e){var t=[];for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&t.push(r);return t}},"./node_modules/querystring-es3/index.js":function(e,t,r){"use strict";t.decode=t.parse=r("./node_modules/querystring-es3/decode.js"),t.encode=t.stringify=r("./node_modules/querystring-es3/encode.js")},"./node_modules/url/url.js":function(e,t,r){"use strict";function o(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}function n(e,t,r){if(e&&h.isObject(e)&&e instanceof o)return e;var n=new o;return n.parse(e,t,r),n}function s(e){return h.isString(e)&&(e=n(e)),e instanceof o?e.format():o.prototype.format.call(e)}function i(e,t){return n(e,!1,!0).resolve(t)}function a(e,t){return e?n(e,!1,!0).resolveObject(t):t}var l=r("./node_modules/punycode/punycode.js"),h=r("./node_modules/url/util.js");t.parse=n,t.resolve=i,t.resolveObject=a,t.format=s,t.Url=o;var u=/^([a-z0-9.+-]+:)/i,c=/:[0-9]*$/,d=/^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,f=["<",">",'"',"`"," ","\r","\n","\t"],p=["{","}","|","\\","^","`"].concat(f),m=["'"].concat(p),v=["%","/","?",";","#"].concat(m),F=["/","?","#"],g=/^[+a-z0-9A-Z_-]{0,63}$/,_=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,b={javascript:!0,"javascript:":!0},y={javascript:!0,"javascript:":!0},j={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},w=r("./node_modules/querystring-es3/index.js");o.prototype.parse=function(e,t,r){if(!h.isString(e))throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var o=e.indexOf("?"),n=-1!==o&&o<e.indexOf("#")?"?":"#",s=e.split(n),i=/\\/g;s[0]=s[0].replace(i,"/"),e=s.join(n);var a=e;if(a=a.trim(),!r&&1===e.split("#").length){var c=d.exec(a);if(c)return this.path=a,this.href=a,this.pathname=c[1],c[2]?(this.search=c[2],this.query=t?w.parse(this.search.substr(1)):this.search.substr(1)):t&&(this.search="",this.query={}),this}var f=u.exec(a);if(f){f=f[0];var p=f.toLowerCase();this.protocol=p,a=a.substr(f.length)}if(r||f||a.match(/^\/\/[^@\/]+@[^@\/]+/)){var C="//"===a.substr(0,2);!C||f&&y[f]||(a=a.substr(2),this.slashes=!0)}if(!y[f]&&(C||f&&!j[f])){for(var O=-1,x=0;x<F.length;x++){var I=a.indexOf(F[x]);-1!==I&&(-1===O||I<O)&&(O=I)}var S,A;A=-1===O?a.lastIndexOf("@"):a.lastIndexOf("@",O),-1!==A&&(S=a.slice(0,A),a=a.slice(A+1),this.auth=decodeURIComponent(S)),O=-1;for(var x=0;x<v.length;x++){var I=a.indexOf(v[x]);-1!==I&&(-1===O||I<O)&&(O=I)}-1===O&&(O=a.length),this.host=a.slice(0,O),a=a.slice(O),this.parseHost(),this.hostname=this.hostname||"";var E="["===this.hostname[0]&&"]"===this.hostname[this.hostname.length-1];if(!E)for(var q=this.hostname.split(/\./),x=0,k=q.length;x<k;x++){var U=q[x];if(U&&!U.match(g)){for(var M="",R=0,N=U.length;R<N;R++)U.charCodeAt(R)>127?M+="x":M+=U[R];if(!M.match(g)){var H=q.slice(0,x),T=q.slice(x+1),P=U.match(_);P&&(H.push(P[1]),T.unshift(P[2])),T.length&&(a="/"+T.join(".")+a),this.hostname=H.join(".");break}}}this.hostname.length>255?this.hostname="":this.hostname=this.hostname.toLowerCase(),E||(this.hostname=l.toASCII(this.hostname));var D=this.port?":"+this.port:"",L=this.hostname||"";this.host=L+D,this.href+=this.host,E&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),"/"!==a[0]&&(a="/"+a))}if(!b[p])for(var x=0,k=m.length;x<k;x++){var G=m[x];if(-1!==a.indexOf(G)){var $=encodeURIComponent(G);$===G&&($=escape(G)),a=a.split(G).join($)}}var z=a.indexOf("#");-1!==z&&(this.hash=a.substr(z),a=a.slice(0,z));var B=a.indexOf("?");if(-1!==B?(this.search=a.substr(B),this.query=a.substr(B+1),t&&(this.query=w.parse(this.query)),a=a.slice(0,B)):t&&(this.search="",this.query={}),a&&(this.pathname=a),j[p]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){var D=this.pathname||"",K=this.search||"";this.path=D+K}return this.href=this.format(),this},o.prototype.format=function(){var e=this.auth||"";e&&(e=encodeURIComponent(e),e=e.replace(/%3A/i,":"),e+="@");var t=this.protocol||"",r=this.pathname||"",o=this.hash||"",n=!1,s="";this.host?n=e+this.host:this.hostname&&(n=e+(-1===this.hostname.indexOf(":")?this.hostname:"["+this.hostname+"]"),this.port&&(n+=":"+this.port)),this.query&&h.isObject(this.query)&&Object.keys(this.query).length&&(s=w.stringify(this.query));var i=this.search||s&&"?"+s||"";return t&&":"!==t.substr(-1)&&(t+=":"),this.slashes||(!t||j[t])&&!1!==n?(n="//"+(n||""),r&&"/"!==r.charAt(0)&&(r="/"+r)):n||(n=""),o&&"#"!==o.charAt(0)&&(o="#"+o),i&&"?"!==i.charAt(0)&&(i="?"+i),r=r.replace(/[?#]/g,function(e){return encodeURIComponent(e)}),i=i.replace("#","%23"),t+n+r+i+o},o.prototype.resolve=function(e){return this.resolveObject(n(e,!1,!0)).format()},o.prototype.resolveObject=function(e){if(h.isString(e)){var t=new o;t.parse(e,!1,!0),e=t}for(var r=new o,n=Object.keys(this),s=0;s<n.length;s++){var i=n[s];r[i]=this[i]}if(r.hash=e.hash,""===e.href)return r.href=r.format(),r;if(e.slashes&&!e.protocol){for(var a=Object.keys(e),l=0;l<a.length;l++){var u=a[l];"protocol"!==u&&(r[u]=e[u])}return j[r.protocol]&&r.hostname&&!r.pathname&&(r.path=r.pathname="/"),r.href=r.format(),r}if(e.protocol&&e.protocol!==r.protocol){if(!j[e.protocol]){for(var c=Object.keys(e),d=0;d<c.length;d++){var f=c[d];r[f]=e[f]}return r.href=r.format(),r}if(r.protocol=e.protocol,e.host||y[e.protocol])r.pathname=e.pathname;else{for(var p=(e.pathname||"").split("/");p.length&&!(e.host=p.shift()););e.host||(e.host=""),e.hostname||(e.hostname=""),""!==p[0]&&p.unshift(""),p.length<2&&p.unshift(""),r.pathname=p.join("/")}if(r.search=e.search,r.query=e.query,r.host=e.host||"",r.auth=e.auth,r.hostname=e.hostname||e.host,r.port=e.port,r.pathname||r.search){var m=r.pathname||"",v=r.search||"";r.path=m+v}return r.slashes=r.slashes||e.slashes,r.href=r.format(),r}var F=r.pathname&&"/"===r.pathname.charAt(0),g=e.host||e.pathname&&"/"===e.pathname.charAt(0),_=g||F||r.host&&e.pathname,b=_,w=r.pathname&&r.pathname.split("/")||[],p=e.pathname&&e.pathname.split("/")||[],C=r.protocol&&!j[r.protocol];if(C&&(r.hostname="",r.port=null,r.host&&(""===w[0]?w[0]=r.host:w.unshift(r.host)),r.host="",e.protocol&&(e.hostname=null,e.port=null,e.host&&(""===p[0]?p[0]=e.host:p.unshift(e.host)),e.host=null),_=_&&(""===p[0]||""===w[0])),g)r.host=e.host||""===e.host?e.host:r.host,r.hostname=e.hostname||""===e.hostname?e.hostname:r.hostname,r.search=e.search,r.query=e.query,w=p;else if(p.length)w||(w=[]),w.pop(),w=w.concat(p),r.search=e.search,r.query=e.query;else if(!h.isNullOrUndefined(e.search)){if(C){r.hostname=r.host=w.shift();var O=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return r.search=e.search,r.query=e.query,h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.href=r.format(),r}if(!w.length)return r.pathname=null,r.search?r.path="/"+r.search:r.path=null,r.href=r.format(),r;for(var x=w.slice(-1)[0],I=(r.host||e.host||w.length>1)&&("."===x||".."===x)||""===x,S=0,A=w.length;A>=0;A--)x=w[A],"."===x?w.splice(A,1):".."===x?(w.splice(A,1),S++):S&&(w.splice(A,1),S--);if(!_&&!b)for(;S--;S)w.unshift("..");!_||""===w[0]||w[0]&&"/"===w[0].charAt(0)||w.unshift(""),I&&"/"!==w.join("/").substr(-1)&&w.push("");var E=""===w[0]||w[0]&&"/"===w[0].charAt(0);if(C){r.hostname=r.host=E?"":w.length?w.shift():"";var O=!!(r.host&&r.host.indexOf("@")>0)&&r.host.split("@");O&&(r.auth=O.shift(),r.host=r.hostname=O.shift())}return _=_||r.host&&w.length,_&&!E&&w.unshift(""),w.length?r.pathname=w.join("/"):(r.pathname=null,r.path=null),h.isNull(r.pathname)&&h.isNull(r.search)||(r.path=(r.pathname?r.pathname:"")+(r.search?r.search:"")),r.auth=e.auth||r.auth,r.slashes=r.slashes||e.slashes,r.href=r.format(),r},o.prototype.parseHost=function(){var e=this.host,t=c.exec(e);t&&(t=t[0],":"!==t&&(this.port=t.substr(1)),e=e.substr(0,e.length-t.length)),e&&(this.hostname=e)}},"./node_modules/url/util.js":function(e,t,r){"use strict";e.exports={isString:function(e){return"string"==typeof e},isObject:function(e){return"object"==typeof e&&null!==e},isNull:function(e){return null===e},isNullOrUndefined:function(e){return null==e}}},"./node_modules/webpack/buildin/global.js":function(e,t){var r;r=function(){return this}();try{r=r||Function("return this")()||(0,eval)("this")}catch(e){"object"==typeof window&&(r=window)}e.exports=r},"./node_modules/webpack/buildin/module.js":function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},0:function(e,t){e.exports=jQuery},1:function(e,t){e.exports=Injector},2:function(e,t){e.exports=React},3:function(e,t){e.exports=ReactDom},4:function(e,t){e.exports=i18n},5:function(e,t){e.exports=qs}});

View File

@ -60,7 +60,7 @@ jQuery.entwine('ss', ($) => {
$('#Form_ConfirmFolderForm_FolderID_Holder .treedropdownfield.is-open,#Form_ItemEditForm_FolderID .treedropdownfield.is-open').entwine({
onunmatch() {
// Build url
const parsedURL = url.parse('UserDefinedFormController/getfoldergrouppermissions');
const parsedURL = url.parse('admin/user-forms/getfoldergrouppermissions');
const parsedQs = qs.parse(parsedURL.query);
parsedQs.FolderID = $(this).find('input[name=FolderID]').val();
const fetchURL = url.format({ ...parsedURL, search: qs.stringify(parsedQs) });

View File

@ -2,22 +2,12 @@
namespace SilverStripe\UserForms\Control;
use PageController;
use Psr\Log\LoggerInterface;
use SilverStripe\AssetAdmin\Controller\AssetAdmin;
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Folder;
use SilverStripe\Assets\Upload;
use SilverStripe\CMS\Controllers\CMSMain;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Email\Email;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Core\Extension;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FormAction;
@ -28,43 +18,33 @@ use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\Schema\FormSchema;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\ValidationException;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Group;
use SilverStripe\Security\InheritedPermissions;
use SilverStripe\Security\Permission;
use SilverStripe\Security\PermissionFailureException;
use SilverStripe\Security\Security;
use SilverStripe\UserForms\Extension\UserFormFileExtension;
use SilverStripe\UserForms\Form\UserForm;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\EditableFormField\EditableFileField;
use SilverStripe\UserForms\Model\Submission\SubmittedForm;
use SilverStripe\UserForms\Model\UserDefinedForm;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\View\SSViewer;
use SilverStripe\View\ViewableData;
use Swift_RfcComplianceException;
/**
* Controller for the {@link UserDefinedForm} page type.
* Provides a few endpoints the user form CMS UI targets with some AJAX request.
*
* @package userforms
* @note While this is a LeftAndMain controller, it doesn't actually appear in the Left side CMS navigation.
*/
class UserDefinedFormAdmin extends LeftAndMain
{
private static $allowed_actions = [
'confirmfolderformschema' => 'CMS_ACCESS_CMSMain',
'ConfirmFolderForm' => 'CMS_ACCESS_CMSMain',
'confirmfolder' => 'CMS_ACCESS_CMSMain',
'getfoldergrouppermissions' => 'CMS_ACCESS_CMSMain',
'confirmfolderformschema',
'ConfirmFolderForm',
'confirmfolder',
'getfoldergrouppermissions',
];
private static $required_permission_codes = 'CMS_ACCESS_CMSMain';
private static $url_segment = 'user-forms';
/**
@ -99,13 +79,15 @@ class UserDefinedFormAdmin extends LeftAndMain
return $textField;
}
public function index($request)
{
// Don't serve anythign under the main URL.
return $this->httpError(404);
}
/**
* This returns a Confirm Folder form used to verify the upload folder for EditableFileFields
* This returns a Confirm Folder form schema used to verify the upload folder for EditableFileFields
* @param HTTPRequest $request
* @return HTTPResponse
*/
@ -143,6 +125,7 @@ class UserDefinedFormAdmin extends LeftAndMain
$folder = Folder::get()->byID($folderId);
if (!$folder) {
$folder = $this->getFormSubmissionFolder();
$folderId = $folder->ID;
}
$form = $this->buildConfirmFolderForm(
@ -168,11 +151,21 @@ class UserDefinedFormAdmin extends LeftAndMain
return $response;
}
/**
* Return the ConfirmFolderForm. This is only exposed so the treeview has somewhere to direct it's AJAX calss.
* @return Form
*/
public function ConfirmFolderForm(): Form
{
return $this->buildConfirmFolderForm();
}
/**
* Build the ConfirmFolderForm
* @param string $suggestedFolderName Suggested name for the folder name field
* @param string $permissionFolderString Description to append to the treeview field
* @return Form
*/
private function buildConfirmFolderForm(string $suggestedFolderName = '', string $permissionFolderString = ''): Form
{
// Build our Field list for the Form we will return to the front end.
@ -192,8 +185,7 @@ class UserDefinedFormAdmin extends LeftAndMain
], "new"),
TreeDropdownField::create('FolderID', '', Folder::class)
->addExtraClass('pt-1')
->setDescription($permissionFolderString)
,
->setDescription($permissionFolderString),
HiddenField::create('ID')
);
@ -207,15 +199,16 @@ class UserDefinedFormAdmin extends LeftAndMain
);
return Form::create($this, 'ConfirmFolderForm', $fields, $actions, RequiredFields::create('ID'))
->setFormAction('UserDefinedFormController/ConfirmFolderForm')
->setFormAction($this->Link('ConfirmFolderForm'))
->addExtraClass('form--no-dividers');
}
/**
* Sets the selected folder as the upload folder for an EditableFileField
* @return HTTPResponse
* @param array $data
* @param Form $form
* @param HTTPRequest $request
* @return HTTPResponse
* @throws ValidationException
*/
public function confirmfolder(array $data, Form $form, HTTPRequest $request)
@ -251,7 +244,7 @@ class UserDefinedFormAdmin extends LeftAndMain
}
// check if we're creating a new folder or using an existing folder
$option = $data['FolderOptions'];
$option = isset($data['FolderOptions']) ? $data['FolderOptions'] : '';
if ($option === 'existing') {
// set existing folder
$folderID = $data['FolderID'];
@ -276,6 +269,7 @@ class UserDefinedFormAdmin extends LeftAndMain
}
/**
* Get the permission for a specific folder
* @return HTTPResponse
*/
public function getfoldergrouppermissions()
@ -301,6 +295,7 @@ class UserDefinedFormAdmin extends LeftAndMain
}
/**
* Set the permission for the default submisison folder.
* @throws ValidationException
*/
private static function updateFormSubmissionFolderPermissions()

View File

@ -5,36 +5,20 @@ namespace SilverStripe\UserForms\Control;
use PageController;
use Psr\Log\LoggerInterface;
use SilverStripe\AssetAdmin\Controller\AssetAdmin;
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Folder;
use SilverStripe\Assets\Upload;
use SilverStripe\CMS\Controllers\CMSMain;
use SilverStripe\Control\Controller;
use SilverStripe\Control\Email\Email;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Manifest\ModuleLoader;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\HiddenField;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\OptionsetField;
use SilverStripe\Forms\Schema\FormSchema;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\i18n\i18n;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\ValidationException;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Group;
use SilverStripe\Security\InheritedPermissions;
use SilverStripe\Security\Permission;
use SilverStripe\Security\PermissionFailureException;
use SilverStripe\Security\Security;
use SilverStripe\UserForms\Extension\UserFormFileExtension;
use SilverStripe\UserForms\Form\UserForm;
@ -42,7 +26,6 @@ use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\EditableFormField\EditableFileField;
use SilverStripe\UserForms\Model\Submission\SubmittedForm;
use SilverStripe\UserForms\Model\UserDefinedForm;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\ArrayData;
use SilverStripe\View\Requirements;
use SilverStripe\View\SSViewer;
@ -63,10 +46,6 @@ class UserDefinedFormController extends PageController
'ping',
'Form',
'finished',
'confirmfolderformschema' => 'CMS_ACCESS_CMSMain',
'ConfirmFolderForm' => 'CMS_ACCESS_CMSMain',
'confirmfolder' => 'CMS_ACCESS_CMSMain',
'getfoldergrouppermissions' => 'CMS_ACCESS_CMSMain',
];
/** @var string The name of the folder where form submissions will be placed by default */
@ -547,230 +526,6 @@ JS
]);
}
/**
* Returns a TextField for entering a folder name.
* @param string $folder The current folder to set the field to
* @param string $title The title of the text field
* @return TextField
*/
private static function getRestrictedAccessField(string $folder, string $title)
{
/** @var TextField $textField */
$textField = TextField::create('CreateFolder', '');
/** @var Folder $formSubmissionsFolder */
$formSubmissionsFolder = Folder::find($folder);
$textField->setDescription(EditableFileField::getFolderPermissionString($formSubmissionsFolder));
$textField->addExtraClass('pt-2');
$textField->setSchemaData([
'data' => [
'prefix' => static::config()->get('form_submissions_folder') . '/',
],
'attributes' => [
'placeholder' => $title
]
]);
return $textField;
}
/**
* This returns a Confirm Folder form used to verify the upload folder for EditableFileFields
* @param HTTPRequest $request
* @return HTTPResponse
*/
public function confirmfolderformschema(HTTPRequest $request)
{
// Retrieve editable form field by its ID
$id = $request->requestVar('ID');
if (!$id) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
$editableFormField = EditableFormField::get()->byID($id);
if (!$editableFormField) {
$editableFormField = Versioned::get_by_stage(EditableFormField::class, Versioned::DRAFT)
->byID($id);
}
if (!$editableFormField) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
// Retrieve the editable form fields Parent
$userForm = $editableFormField->Parent();
if (!$userForm) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
if (!$userForm->canEdit()) {
throw new PermissionFailureException();
}
// Get the folder we want to associate to this EditableFileField
$folderId = 0;
if ($editableFormField instanceof EditableFileField) {
$folderId = $editableFormField->FolderID;
}
/** @var Folder $folder */
$folder = Folder::get()->byID($folderId);
if (!$folder) {
$folder = $this->getFormSubmissionFolder();
}
$form = $this->buildConfirmFolderForm(
$userForm->Title ?: '',
EditableFileField::getFolderPermissionString($folder)
);
$form->loadDataFrom(['FolderID' => $folderId, 'ID' => $id]);
// Convert the EditableFormField to an EditableFileField if it's not already one.
if (!$editableFormField instanceof EditableFileField) {
$editableFormField = $editableFormField->newClassInstance(EditableFileField::class);
$editableFormField->write();
}
// create the schema response
$parts = $this->getRequest()->getHeader(LeftAndMain::SCHEMA_HEADER);
$schemaID = $this->getRequest()->getURL();
$data = FormSchema::singleton()->getMultipartSchema($parts, $schemaID, $form);
// return the schema response
$response = HTTPResponse::create(json_encode($data));
$response->addHeader('Content-Type', 'application/json');
return $response;
}
public function ConfirmFolderForm(): Form
{
return $this->buildConfirmFolderForm();
}
private function buildConfirmFolderForm(string $suggestedFolderName = '', string $permissionFolderString = ''): Form
{
// Build our Field list for the Form we will return to the front end.
$fields = FieldList::create(
LiteralField::create(
'LabelA',
_t(__CLASS__.'.CONFIRM_FOLDER_LABEL_A', 'Files that your users upload should be stored carefully to reduce the risk of exposing sensitive data. Ensure the folder you select can only be viewed by appropriate parties. Folder permissions can be managed within the Files area.')
)->addExtraClass(' mb-2'),
LiteralField::create(
'LabelB',
_t(__CLASS__.'.CONFIRM_FOLDER_LABEL_B', 'The folder selected will become the default for this form. This can be changed on an individual basis in the <i>File upload field.</i>')
)->addExtraClass(' mb-3'),
static::getRestrictedAccessField($this->config()->get('form_submissions_folder'), $suggestedFolderName),
OptionsetField::create('FolderOptions', _t(__CLASS__.'.FOLDER_OPTIONS_TITLE', 'Form folder options'), [
"new" => _t(__CLASS__.'.FOLDER_OPTIONS_NEW', 'Create a new folder (recommended)'),
"existing" => _t(__CLASS__.'.FOLDER_OPTIONS_EXISTING', 'Use an existing folder')
], "new"),
TreeDropdownField::create('FolderID', '', Folder::class)
->addExtraClass('pt-1')
->setDescription($permissionFolderString)
,
HiddenField::create('ID')
);
$actions = FieldList::create(
FormAction::create('confirmfolder', _t(__CLASS__.'.FORM_ACTION_CONFIRM', 'Save and continue'))
->setUseButtonTag(false)
->addExtraClass('btn btn-primary'),
FormAction::create("cancel", _t(CMSMain::class . '.Cancel', "Cancel"))
->addExtraClass('btn btn-secondary')
->setUseButtonTag(true)
);
return Form::create($this, 'ConfirmFolderForm', $fields, $actions)
->setFormAction('UserDefinedFormController/ConfirmFolderForm')
->addExtraClass('form--no-dividers');
}
/**
* Sets the selected folder as the upload folder for an EditableFileField
* @return HTTPResponse
* @param HTTPRequest $request
* @throws ValidationException
*/
public function confirmfolder(HTTPRequest $request)
{
if (!Permission::checkMember(null, "CMS_ACCESS_AssetAdmin")) {
throw new PermissionFailureException();
}
// retrieve the EditableFileField
$id = $request->requestVar('ID');
if (!$id) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
/** @var EditableFileField $editableFileField */
$editableFormField = EditableFormField::get()->byID($id);
if (!$editableFormField) {
$editableFormField = Versioned::get_by_stage(EditableFormField::class, Versioned::DRAFT)->byID($id);
}
if (!$editableFormField) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
// change the class if it is incorrect
if (!$editableFormField instanceof EditableFileField) {
$editableFormField = $editableFormField->newClassInstance(EditableFileField::class);
}
if (!$editableFormField) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
$editableFileField = $editableFormField;
if (!$editableFileField->canEdit()) {
throw new PermissionFailureException();
}
// check if we're creating a new folder or using an existing folder
$option = $request->requestVar('FolderOptions');
if ($option === 'existing') {
// set existing folder
$folderID = $request->requestVar('FolderID');
if ($folderID != 0) {
$folder = Folder::get()->byID($folderID);
if (!$folder) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
}
} else {
// create the folder
$createFolder = $request->requestVar('CreateFolder') ?: $editableFormField->Parent()->Title;
$folder = $this->getFormSubmissionFolder($createFolder);
}
// assign the folder
$editableFileField->FolderID = isset($folder) ? $folder->ID : 0;
$editableFileField->write();
// respond
$response = HTTPResponse::create(json_encode([]));
$response->addHeader('Content-Type', 'application/json');
return $response;
}
/**
* @return HTTPResponse
*/
public function getfoldergrouppermissions()
{
$folderID = $this->getRequest()->requestVar('FolderID');
if ($folderID) {
/** @var Folder $folder */
$folder = Folder::get()->byID($folderID);
if (!$folder) {
throw new HTTPResponse_Exception(_t(__CLASS__.'.INVALID_REQUEST', 'This request was invalid.'), 400);
}
if (!$folder->canView()) {
throw new PermissionFailureException();
}
} else {
$folder = null;
}
// respond
$response = HTTPResponse::create(json_encode(EditableFileField::getFolderPermissionString($folder)));
$response->addHeader('Content-Type', 'application/json');
return $response;
}
/**
* Outputs the required JS from the $watch input
*
@ -808,44 +563,4 @@ EOS;
return $result;
}
/**
* @throws ValidationException
*/
private static function updateFormSubmissionFolderPermissions()
{
// ensure the FormSubmissions folder is only accessible to Administrators
$formSubmissionsFolder = Folder::find(self::config()->get('form_submissions_folder'));
$formSubmissionsFolder->CanViewType = InheritedPermissions::ONLY_THESE_USERS;
$formSubmissionsFolder->ViewerGroups()->removeAll();
$formSubmissionsFolder->ViewerGroups()->add(Group::get_one(Group::class, ['"Code"' => 'administrators']));
$formSubmissionsFolder->write();
}
/**
* Returns the form submission folder or a sub folder if provided.
* Creates the form submission folder if it doesn't exist.
* Updates the form submission folder permissions if it is created.
* @param string $subFolder Sub-folder to be created or returned.
* @return Folder
* @throws ValidationException
*/
public static function getFormSubmissionFolder(string $subFolder = null): ?Folder
{
$folderPath = self::config()->get('form_submissions_folder');
if ($subFolder) {
$folderPath .= '/' . $subFolder;
}
$formSubmissionsFolderExists = !!Folder::find(self::config()->get('form_submissions_folder'));
$folder = Folder::find_or_make($folderPath);
// Set default permissions if this is the first time we create the form submission folder
if (!$formSubmissionsFolderExists) {
self::updateFormSubmissionFolderPermissions();
// Make sure we return the folder with the latest permission
$folder = Folder::find($folderPath);
}
return $folder;
}
}

View File

@ -14,6 +14,7 @@ use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Member;
use SilverStripe\Security\InheritedPermissions;
use SilverStripe\UserForms\Control\UserDefinedFormAdmin;
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\Submission\SubmittedFileField;
@ -274,7 +275,7 @@ class EditableFileField extends EditableFormField
if ($inheritableSibling) {
$this->FolderID = $inheritableSibling->FolderID;
} else {
$folder = UserDefinedFormController::getFormSubmissionFolder();
$folder = UserDefinedFormAdmin::getFormSubmissionFolder();
$this->FolderID = $folder->ID;
}
}

View File

@ -0,0 +1,476 @@
<?php
namespace SilverStripe\UserForms\Tests\Control;
use SilverStripe\Assets\Dev\TestAssetStore;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Folder;
use SilverStripe\Assets\Storage\AssetStore;
use SilverStripe\Assets\Upload_Validator;
use InvalidArgumentException;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\Session;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\CSSContentParser;
use SilverStripe\Dev\FunctionalTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\FormAction;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\InheritedPermissions;
use SilverStripe\Security\Security;
use SilverStripe\UserForms\Control\UserDefinedFormAdmin;
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\EditableFormField;
use SilverStripe\UserForms\Model\EditableFormField\EditableFileField;
use SilverStripe\UserForms\Model\EditableFormField\EditableTextField;
use SilverStripe\UserForms\Model\Recipient\EmailRecipient;
use SilverStripe\UserForms\Model\Submission\SubmittedFormField;
use SilverStripe\UserForms\Model\UserDefinedForm;
use SilverStripe\View\ArrayData;
use SilverStripe\View\SSViewer;
/**
* @package userforms
*/
class UserDefinedFormAdminTest extends FunctionalTest
{
protected static $fixture_file = '../UserFormsTest.yml';
protected function setUp()
{
parent::setUp();
$submissionFolder = Folder::find('Form-submissions');
if ($submissionFolder) {
$submissionFolder->delete();
}
foreach (Folder::get() as $folder) {
$folder->publishSingle();
}
}
public function testConfirmfolderformInvalidRequest()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain']);
$url = 'admin/user-forms/confirmfolderformschema?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->get($url);
$this->assertEquals(400, $response->getStatusCode(), 'Request without ID parameter is invalid');
$response = $this->get($url . http_build_query(['ID' => -1]));
$this->assertEquals(400, $response->getStatusCode(), 'Request with unknown ID and known UserFormID is invalid');
}
public function testConfirmfolderformAccessControl()
{
$url = 'admin/user-forms/confirmfolderformschema?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$restrictedFieldID = $this->idFromFixture(EditableFileField::class, 'file-field-2');
$this->logInWithPermission(['CMS_ACCESS_CMSMain']);
$response = $this->get($url . http_build_query(['ID' => $fieldID]));
$this->assertEquals(200, $response->getStatusCode(), 'CMS editors can access confirm folder form ');
$response = $this->get($url . http_build_query(['ID' => $restrictedFieldID]));
$this->assertEquals(
403,
$response->getStatusCode(),
'CMS editors can\'t access confirm folder form for restricted form'
);
$this->logInWithPermission('ADMIN');
$response = $this->get($url . http_build_query(['ID' => $restrictedFieldID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Admins can access confirm folder form for restricted form'
);
}
public function testConfirmfolderformFields()
{
$url = 'admin/user-forms/confirmfolderformschema?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$folderID = $this->idFromFixture(Folder::class, 'unrestricted');
$this->logInWithPermission('ADMIN');
$response = $this->get(
$url . http_build_query(['ID' => $fieldID]),
null,
['X-FormSchema-Request' => 'auto,schema,state,errors']
);
$schemaData = json_decode($response->getBody(), true);
$this->assertEquals('ConfirmFolderForm', $schemaData['schema']['name']);
$this->assertField($schemaData, 'FolderOptions', ['component' => 'OptionsetField']);
$this->assertField($schemaData, 'FolderID', ['component' => 'TreeDropdownField']);
$this->assertField($schemaData, 'ID', ['schemaType' =>'Hidden']);
$this->assertStateValue($schemaData, ['ID' => $fieldID, 'FolderID' => $folderID]);
}
public function testConfirmfolderformDefaultFolder()
{
$url = 'admin/user-forms/confirmfolderformschema?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-2');
$this->logInWithPermission('ADMIN');
$response = $this->get(
$url . http_build_query(['ID' => $fieldID]),
null,
['X-FormSchema-Request' => 'auto,schema,state,errors']
);
$schemaData = json_decode($response->getBody(), true);
$this->assertEquals('ConfirmFolderForm', $schemaData['schema']['name']);
$this->assertField($schemaData, 'FolderOptions', ['component' => 'OptionsetField']);
$this->assertField($schemaData, 'FolderID', ['component' => 'TreeDropdownField']);
$this->assertField($schemaData, 'ID', ['schemaType' =>'Hidden']);
$folder = Folder::find('Form-submissions');
$this->assertNotEmpty($folder, 'Default submission folder has been created');
$this->assertStateValue($schemaData, ['ID' => $fieldID, 'FolderID' => $folder->ID]);
$this->logOut();
$this->assertFalse($folder->canView(), 'Default submission folder is protected');
}
public function testConfirmfolderInvalidRequest()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm';
$response = $this->post($url, ['ID' => -1]);
$this->assertEquals(400, $response->getStatusCode(), 'Request without ID parameter is invalid');
}
public function testConfirmfolderAccessControl()
{
$url = 'admin/user-forms/ConfirmFolderForm';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$restrictedFieldID = $this->idFromFixture(EditableFileField::class, 'file-field-2');
$this->logInWithPermission(['CMS_ACCESS_CMSMain']);
$response = $this->post($url, ['ID' => $fieldID]);
$this->assertEquals(
403,
$response->getStatusCode(),
'Users without CMS_ACCESS_AssetAdmin can\'t confirm folder'
);
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$response = $this->post($url, ['ID' => $fieldID]);
$this->assertEquals(200, $response->getStatusCode(), 'CMS editors can access confirm folder form ');
$response = $this->post($url, ['ID' => $restrictedFieldID]);
$this->assertEquals(
403,
$response->getStatusCode(),
'CMS editors can\'t confirm folder form for restricted form'
);
$this->logInWithPermission('ADMIN');
$response = $this->post($url, ['ID' => $restrictedFieldID]);
$this->assertEquals(
200,
$response->getStatusCode(),
'Admins can confirm folder form for restricted form'
);
}
public function testConfirmfolderExistingFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$folderID = $this->idFromFixture(Folder::class, 'restricted');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'existing', 'FolderID' => $folderID]);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm an existing folder is successful');
$this->assertEquals(
$folderID,
EditableFileField::get()->byID($fieldID)->FolderID,
'FileField points to restricted folder'
);
}
public function testConfirmfolderInexistingFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'existing', 'FolderID' => -1]);
$this->assertEquals(400, $response->getStatusCode(), 'Confirm a non-existant folder fails with 400');
}
public function testConfirmfolderRootFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'existing', 'FolderID' => 0]);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm an root folder is successful');
$this->assertEquals(0, EditableFileField::get()->byID($fieldID)->FolderID, 'FileField points to root folder');
}
public function testConfirmfolderNewFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'new']);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm folder by creating a new one is valid');
$folder = Folder::find('Form-submissions/Form-with-upload-field');
$this->assertNotEmpty($folder, 'New folder has been created based on the UserFormPage\'s title');
$this->logOut();
$this->assertFalse($folder->canView(), 'New folder is restricted');
}
public function testConfirmfolderNewFolderWithSpecificName()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post(
$url,
['ID' => $fieldID, 'FolderOptions' => 'new', 'CreateFolder' => 'My-Custom-Folder->\'Pow']
);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm folder by creating a new one is valid');
$folder = Folder::find('Form-submissions/My-Custom-Folder-Pow');
$this->assertNotEmpty($folder, 'New folder has been created based the provided CreateFolder value');
$this->logOut();
$this->assertFalse($folder->canView(), 'New folder is restricted');
}
public function testConfirmfolderWithFieldTypeConversion()
{
$this->logInWithPermission('ADMIN');
$url = 'admin/user-forms/ConfirmFolderForm?';
$fieldID = $this->idFromFixture(EditableTextField::class, 'become-file-upload');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'new']);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm folder by creating a new one is valid');
$folder = Folder::find('Form-submissions/Form-editable-only-by-admin');
$this->assertNotEmpty($folder, 'New folder has been created based on the UserFormPage\'s title');
$this->logOut();
$this->assertFalse($folder->canView(), 'New folder is restricted');
$field = EditableFormField::get()->byID($fieldID);
$this->assertEquals(
EditableFileField::class,
$field->ClassName,
'EditableTextField has been converted to EditableFileField'
);
}
public function testPreserveSubmissionFolderPermission()
{
$folder = Folder::find_or_make('Form-submissions');
$folder->CanViewType = InheritedPermissions::ANYONE;
$folder->write();
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/ConfirmFolderForm?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'new']);
$folder = Folder::find('Form-submissions');
$this->assertEquals(
InheritedPermissions::ANYONE,
$folder->CanViewType,
'Submission folder permissions are preserved'
);
}
/**
* Assert that a field with the provided attribute exists in $schema.
*
* @param array $schema
* @param string $name
* @param string $component
* @param $value
* @param string $message
*/
private function assertField(array $schema, string $name, array $attributes, $message = '')
{
$message = $message ?: sprintf('A %s field exists with %s', $name, var_export($attributes, true));
$fields = $schema['schema']['fields'];
$state = $schema['state']['fields'];
$this->assertNotEmpty($fields, $message);
$foundField = false;
foreach ($fields as $field) {
if ($field['name'] === $name) {
$foundField = true;
foreach ($attributes as $attr => $expectedValue) {
$this->assertEquals($expectedValue, $field[$attr]);
}
break;
}
}
$this->assertTrue($foundField, $message);
}
private function assertStateValue(array $schema, $values)
{
$fields = $schema['state']['fields'];
$this->assertNotEmpty($fields);
$foundField = false;
foreach ($fields as $field) {
$key = $field['name'];
if (isset($values[$key])) {
$this->assertEquals($values[$key], $field['value'], sprintf('%s is %s', $key, $values[$key]));
}
}
}
public function testGetFolderPermissionAccessControl()
{
$this->logOut();
$url = 'admin/user-forms/getfoldergrouppermissions?';
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$adminOnlyFolder = Folder::find('admin-only');
$response = $this->get($url . http_build_query(['FolderID' => $adminOnlyFolder->ID]));
$this->assertEquals(
403,
$response->getStatusCode(),
'Access denied for getting permission of Folder user does not have read access on'
);
$this->logInWithPermission('ADMIN');
$adminOnlyFolder = Folder::find('admin-only');
$response = $this->get($url . http_build_query(['FolderID' => $adminOnlyFolder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Access denied for getting permission of Folder user does not have read access on'
);
}
public function testGetFolderPermissionNonExistentFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'admin/user-forms/getfoldergrouppermissions?';
$response = $this->get($url . http_build_query(['FolderID' => -1]));
$this->assertEquals(
400,
$response->getStatusCode(),
'Non existent folder should fail'
);
}
public function testGetFolderPermissionValidRequest()
{
$url = 'admin/user-forms/getfoldergrouppermissions?';
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$folder = Folder::find('unrestricted');
$response = $this->get($url . http_build_query(['FolderID' => $folder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request is successfull'
);
$this->assertContains('Unrestricted access, uploads will be visible to anyone', $response->getBody());
$folder = Folder::find('restricted-folder');
$response = $this->get($url . http_build_query(['FolderID' => 0]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request for root folder is successful'
);
$this->assertContains('Unrestricted access, uploads will be visible to anyone', $response->getBody());
$folder = Folder::find('restricted-folder');
$response = $this->get($url . http_build_query(['FolderID' => $folder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request for root folder is successful'
);
$this->assertContains('Restricted access, uploads will be visible to logged-in users ', $response->getBody());
$this->logInWithPermission('ADMIN');
$adminOnlyFolder = Folder::find('admin-only');
$response = $this->get($url . http_build_query(['FolderID' => $adminOnlyFolder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request for folder restricted to group is successful'
);
$this->assertContains('Restricted access, uploads will be visible to the following groups: Administrators', $response->getBody());
}
public function testGetFormSubmissionFolder()
{
$submissionFolder = Folder::find('Form-submissions');
$this->assertEmpty($submissionFolder, 'Submission folder does not exists initially.');
// No parameters
$submissionFolder = UserDefinedFormAdmin::getFormSubmissionFolder();
$this->assertNotEmpty($submissionFolder, 'Submission folder exists after getFormSubmissionFolder call');
$this->assertEquals('Form-submissions/', $submissionFolder->getFilename(), 'Submission folder got created under correct name');
$this->assertEquals(InheritedPermissions::ONLY_THESE_USERS, $submissionFolder->CanViewType, 'Submission folder has correct permissions');
$this->assertNotEmpty($submissionFolder->ViewerGroups()->find('Code', 'administrators'), 'Submission folder is limited to administrators');
// subfolder name
$submissionSubFolder = UserDefinedFormAdmin::getFormSubmissionFolder('test-form');
$this->assertNotEmpty($submissionSubFolder, 'Submission subfolder has been created');
$this->assertEquals('Form-submissions/test-form/', $submissionSubFolder->getFilename(), 'Submission sub folder got created under correct name');
$this->assertEquals(InheritedPermissions::INHERIT, $submissionSubFolder->CanViewType, 'Submission sub folder inherit permission from parent');
// make sure parent folder permission don't get overridden
$submissionFolder = Folder::find('Form-submissions');
$submissionFolder->CanViewType = InheritedPermissions::INHERIT;
$submissionFolder->write();
$submissionSubFolder = UserDefinedFormAdmin::getFormSubmissionFolder('test-form-2');
$submissionFolder = Folder::find('Form-submissions');
$this->assertEquals(InheritedPermissions::INHERIT, $submissionFolder->CanViewType, 'Submission sub folder inherit permission from parent');
// Submission folder get recreated
$submissionFolder->delete();
$submissionFolder = Folder::find('Form-submissions');
$this->assertEmpty($submissionFolder, 'Submission folder does has been deleted.');
$submissionSubFolder = UserDefinedFormAdmin::getFormSubmissionFolder('test-form-3');
$submissionFolder = Folder::find('Form-submissions');
$this->assertNotEmpty($submissionFolder, 'Submission folder got recreated');
$this->assertEquals('Form-submissions/', $submissionFolder->getFilename(), 'Submission folder got recreated under correct name');
$this->assertEquals(InheritedPermissions::ONLY_THESE_USERS, $submissionFolder->CanViewType, 'Submission folder has correct permissions');
$this->assertNotEmpty($submissionFolder->ViewerGroups()->find('Code', 'administrators'), 'Submission folder is limited to administrators');
}
}

View File

@ -48,14 +48,6 @@ class UserDefinedFormControllerTest extends FunctionalTest
TestAssetStore::activate('AssetStoreTest');
Config::modify()->merge(SSViewer::class, 'themes', ['simple', '$default']);
$submissionFolder = Folder::find('Form-submissions');
if ($submissionFolder) {
$submissionFolder->delete();
}
foreach (Folder::get() as $folder) {
$folder->publishSingle();
}
}
public function tearDown()
@ -397,437 +389,6 @@ class UserDefinedFormControllerTest extends FunctionalTest
$this->assertEmailSent('test@example.com', 'no-reply@example.com', 'Email Subject: Basic Value');
}
public function testConfirmfolderformInvalidRequest()
{
$this->logInWithPermission('CMS_ACCESS_CMSMain');
$url = 'UserDefinedFormController/confirmfolderform?';
$userDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'basic-form-page');
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->get($url . http_build_query(['UserFormID' => $userDefinedFormID]));
$this->assertEquals(400, $response->getStatusCode(), 'Request without ID parameter is invalid');
$response = $this->get($url . http_build_query(['ID' => $fieldID]));
$this->assertEquals(400, $response->getStatusCode(), 'Request without UserFormID parameter is invalid');
$response = $this->get($url . http_build_query(['ID' => $fieldID, 'UserFormID' => -1]));
$this->assertEquals(400, $response->getStatusCode(), 'Request with unknown UserFormID is invalid');
$response = $this->get($url . http_build_query(['ID' => -1, 'UserFormID' => $userDefinedFormID]));
$this->assertEquals(400, $response->getStatusCode(), 'Request with unknown ID and known UserFormID is invalid');
}
public function testConfirmfolderformAccessControl()
{
$url = 'UserDefinedFormController/confirmfolderform?';
$userDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'upload-form');
$restrictedUserDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'restricted-user-form');
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$restrictedFieldID = $this->idFromFixture(EditableFileField::class, 'file-field-2');
$this->logOut();
$response = $this->get($url . http_build_query(['ID' => $fieldID, 'UserFormID' => $userDefinedFormID]));
$this->assertEquals(403, $response->getStatusCode(), 'Anonymous users can\'t access confirm folder form ');
$this->logInWithPermission('CMS_ACCESS_CMSMain');
$response = $this->get($url . http_build_query(['ID' => $fieldID, 'UserFormID' => $userDefinedFormID]));
$this->assertEquals(200, $response->getStatusCode(), 'CMS editors can access confirm folder form ');
$response = $this->get($url . http_build_query([
'ID' => $restrictedFieldID,
'UserFormID' => $restrictedUserDefinedFormID
]));
$this->assertEquals(
403,
$response->getStatusCode(),
'CMS editors can\'t access confirm folder form for restricted form'
);
$this->logInWithPermission('ADMIN');
$response = $this->get($url . http_build_query([
'ID' => $restrictedFieldID,
'UserFormID' => $restrictedUserDefinedFormID
]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Admins can access confirm folder form for restricted form'
);
}
public function testConfirmfolderformFields()
{
$url = 'UserDefinedFormController/confirmfolderform?';
$userDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'upload-form');
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$folderID = $this->idFromFixture(Folder::class, 'unrestricted');
$this->logInWithPermission('ADMIN');
$response = $this->get(
$url . http_build_query(['ID' => $fieldID, 'UserFormID' => $userDefinedFormID]),
null,
['X-FormSchema-Request' => 'auto,schema,state,errors']
);
$schemaData = json_decode($response->getBody(), true);
$this->assertEquals('ConfirmFolderForm', $schemaData['schema']['name']);
$this->assertField($schemaData, 'FolderOptions', ['component' => 'OptionsetField']);
$this->assertField($schemaData, 'FolderID', ['component' => 'TreeDropdownField']);
$this->assertField($schemaData, 'ID', ['schemaType' =>'Hidden']);
$this->assertStateValue($schemaData, ['ID' => $fieldID, 'FolderID' => $folderID]);
}
public function testConfirmfolderformDefaultFolder()
{
$url = 'UserDefinedFormController/confirmfolderform?';
$userDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'restricted-user-form');
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-2');
$this->logInWithPermission('ADMIN');
$response = $this->get(
$url . http_build_query(['ID' => $fieldID, 'UserFormID' => $userDefinedFormID]),
null,
['X-FormSchema-Request' => 'auto,schema,state,errors']
);
$schemaData = json_decode($response->getBody(), true);
$this->assertEquals('ConfirmFolderForm', $schemaData['schema']['name']);
$this->assertField($schemaData, 'FolderOptions', ['component' => 'OptionsetField']);
$this->assertField($schemaData, 'FolderID', ['component' => 'TreeDropdownField']);
$this->assertField($schemaData, 'ID', ['schemaType' =>'Hidden']);
$folder = Folder::find('Form-submissions');
$this->assertNotEmpty($folder, 'Default submission folder has been created');
$this->assertStateValue($schemaData, ['ID' => $fieldID, 'FolderID' => $folder->ID]);
$this->logOut();
$this->assertFalse($folder->canView(), 'Default submission folder is protected');
}
public function testConfirmfolderInvalidRequest()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$response = $this->post($url, []);
$this->assertEquals(400, $response->getStatusCode(), 'Request without ID parameter is invalid');
$response = $this->post($url, ['ID' => -1]);
$this->assertEquals(400, $response->getStatusCode(), 'Request without ID parameter is invalid');
}
public function testConfirmfolderAccessControl()
{
$url = 'UserDefinedFormController/confirmfolder?';
$userDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'upload-form');
$restrictedUserDefinedFormID = $this->idFromFixture(UserDefinedForm::class, 'restricted-user-form');
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$restrictedFieldID = $this->idFromFixture(EditableFileField::class, 'file-field-2');
$this->logOut();
$response = $this->post($url, ['ID' => $fieldID]);
$this->assertEquals(403, $response->getStatusCode(), 'Anonymous users can\'t confirm folder ');
$this->logInWithPermission('CMS_ACCESS_CMSMain');
$response = $this->post($url, ['ID' => $fieldID]);
$this->assertEquals(
403,
$response->getStatusCode(),
'Users without CMS_ACCESS_AssetAdmin can\'t confirm folder'
);
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$response = $this->post($url, ['ID' => $fieldID]);
$this->assertEquals(200, $response->getStatusCode(), 'CMS editors can access confirm folder form ');
$response = $this->post($url, ['ID' => $restrictedFieldID]);
$this->assertEquals(
403,
$response->getStatusCode(),
'CMS editors can\'t confirm folder form for restricted form'
);
$this->logInWithPermission('ADMIN');
$response = $this->post($url, ['ID' => $restrictedFieldID]);
$this->assertEquals(
200,
$response->getStatusCode(),
'Admins can confirm folder form for restricted form'
);
}
public function testConfirmfolderExistingFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$folderID = $this->idFromFixture(Folder::class, 'restricted');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'existing', 'FolderID' => $folderID]);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm an existing folder is successful');
$this->assertEquals(
$folderID,
EditableFileField::get()->byID($fieldID)->FolderID,
'FileField points to restricted folder'
);
}
public function testConfirmfolderInexistingFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'existing', 'FolderID' => -1]);
$this->assertEquals(400, $response->getStatusCode(), 'Confirm a non-existant folder fails with 400');
}
public function testConfirmfolderRootFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'existing', 'FolderID' => 0]);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm an root folder is successful');
$this->assertEquals(0, EditableFileField::get()->byID($fieldID)->FolderID, 'FileField points to root folder');
}
public function testConfirmfolderNewFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'new']);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm folder by creating a new one is valid');
$folder = Folder::find('Form-submissions/Form-with-upload-field');
$this->assertNotEmpty($folder, 'New folder has been created based on the UserFormPage\'s title');
$this->logOut();
$this->assertFalse($folder->canView(), 'New folder is restricted');
}
public function testConfirmfolderNewFolderWithSpecificName()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$response = $this->post(
$url,
['ID' => $fieldID, 'FolderOptions' => 'new', 'CreateFolder' => 'My-Custom-Folder->\'Pow']
);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm folder by creating a new one is valid');
$folder = Folder::find('Form-submissions/My-Custom-Folder-Pow');
$this->assertNotEmpty($folder, 'New folder has been created based the provided CreateFolder value');
$this->logOut();
$this->assertFalse($folder->canView(), 'New folder is restricted');
}
public function testConfirmfolderWithFieldTypeConversion()
{
$this->logInWithPermission('ADMIN');
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableTextField::class, 'become-file-upload');
$response = $this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'new']);
$this->assertEquals(200, $response->getStatusCode(), 'Valid request to confirm folder by creating a new one is valid');
$folder = Folder::find('Form-submissions/Form-editable-only-by-admin');
$this->assertNotEmpty($folder, 'New folder has been created based on the UserFormPage\'s title');
$this->logOut();
$this->assertFalse($folder->canView(), 'New folder is restricted');
$field = EditableFormField::get()->byID($fieldID);
$this->assertEquals(
EditableFileField::class,
$field->ClassName,
'EditableTextField has been converted to EditableFileField'
);
}
public function testPreserveSubmissionFolderPermission()
{
$folder = Folder::find_or_make('Form-submissions');
$folder->CanViewType = InheritedPermissions::ANYONE;
$folder->write();
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/confirmfolder?';
$fieldID = $this->idFromFixture(EditableFileField::class, 'file-field-1');
$this->post($url, ['ID' => $fieldID, 'FolderOptions' => 'new']);
$folder = Folder::find('Form-submissions');
$this->assertEquals(
InheritedPermissions::ANYONE,
$folder->CanViewType,
'Submission folder permissions are preserved'
);
}
/**
* Assert that a field with the provided attribute exists in $schema.
*
* @param array $schema
* @param string $name
* @param string $component
* @param $value
* @param string $message
*/
private function assertField(array $schema, string $name, array $attributes, $message = '')
{
$message = $message ?: sprintf('A %s field exists with %s', $name, var_export($attributes, true));
$fields = $schema['schema']['fields'];
$state = $schema['state']['fields'];
$this->assertNotEmpty($fields, $message);
$foundField = false;
foreach ($fields as $field) {
if ($field['name'] === $name) {
$foundField = true;
foreach ($attributes as $attr => $expectedValue) {
$this->assertEquals($expectedValue, $field[$attr]);
}
break;
}
}
$this->assertTrue($foundField, $message);
}
private function assertStateValue(array $schema, $values)
{
$fields = $schema['state']['fields'];
$this->assertNotEmpty($fields);
$foundField = false;
foreach ($fields as $field) {
$key = $field['name'];
if (isset($values[$key])) {
$this->assertEquals($values[$key], $field['value'], sprintf('%s is %s', $key, $values[$key]));
}
}
}
public function testGetFolderPermissionAccessControl()
{
$this->logOut();
$url = 'UserDefinedFormController/getfoldergrouppermissions?';
$folder = Folder::find('unrestricted');
$response = $this->get($url . http_build_query(['FolderID' => $folder->ID]));
$this->assertEquals(
403,
$response->getStatusCode(),
'Access denied for getting permission of folder unauthenticated'
);
$response = $this->get($url . http_build_query(['FolderID' => 0]));
$this->assertEquals(
403,
$response->getStatusCode(),
'Access denied for getting permission of root folder unauthenticated'
);
$response = $this->get($url . http_build_query(['FolderID' => -1]));
$this->assertEquals(
403,
$response->getStatusCode(),
'Access denied for getting permission of non-existent folder unauthenticated'
);
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$adminOnlyFolder = Folder::find('admin-only');
$response = $this->get($url . http_build_query(['FolderID' => $adminOnlyFolder->ID]));
$this->assertEquals(
403,
$response->getStatusCode(),
'Access denied for getting permission of Folder user does not have read access on'
);
$this->logInWithPermission('ADMIN');
$adminOnlyFolder = Folder::find('admin-only');
$response = $this->get($url . http_build_query(['FolderID' => $adminOnlyFolder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Access denied for getting permission of Folder user does not have read access on'
);
}
public function testGetFolderPermissionNonExistentFolder()
{
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$url = 'UserDefinedFormController/getfoldergrouppermissions?';
$response = $this->get($url . http_build_query(['FolderID' => -1]));
$this->assertEquals(
400,
$response->getStatusCode(),
'Non existent folder should fail'
);
}
public function testGetFolderPermissionValidRequest()
{
$url = 'UserDefinedFormController/getfoldergrouppermissions?';
$this->logInWithPermission(['CMS_ACCESS_CMSMain', 'CMS_ACCESS_AssetAdmin']);
$folder = Folder::find('unrestricted');
$response = $this->get($url . http_build_query(['FolderID' => $folder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request is successfull'
);
$this->assertContains('Unrestricted access, uploads will be visible to anyone', $response->getBody());
$folder = Folder::find('restricted-folder');
$response = $this->get($url . http_build_query(['FolderID' => 0]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request for root folder is successful'
);
$this->assertContains('Unrestricted access, uploads will be visible to anyone', $response->getBody());
$folder = Folder::find('restricted-folder');
$response = $this->get($url . http_build_query(['FolderID' => $folder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request for root folder is successful'
);
$this->assertContains('Restricted access, uploads will be visible to logged-in users ', $response->getBody());
$this->logInWithPermission('ADMIN');
$adminOnlyFolder = Folder::find('admin-only');
$response = $this->get($url . http_build_query(['FolderID' => $adminOnlyFolder->ID]));
$this->assertEquals(
200,
$response->getStatusCode(),
'Valid request for folder restricted to group is successful'
);
$this->assertContains('Restricted access, uploads will be visible to the following groups: Administrators', $response->getBody());
}
public function testImageThumbnailCreated()
{
Config::modify()->set(Upload_Validator::class, 'use_is_uploaded_file', false);
@ -863,46 +424,4 @@ class UserDefinedFormControllerTest extends FunctionalTest
$store = Injector::inst()->get(AssetStore::class);
$this->assertTrue($store->exists($image->getFilename(), $image->getHash(), 'FitMaxWzM1MiwyNjRd'));
}
public function testGetFormSubmissionFolder()
{
$submissionFolder = Folder::find('Form-submissions');
$this->assertEmpty($submissionFolder, 'Submission folder does not exists initially.');
// No parameters
$submissionFolder = UserDefinedFormController::getFormSubmissionFolder();
$this->assertNotEmpty($submissionFolder, 'Submission folder exists after getFormSubmissionFolder call');
$this->assertEquals('Form-submissions/', $submissionFolder->getFilename(), 'Submission folder got created under correct name');
$this->assertEquals(InheritedPermissions::ONLY_THESE_USERS, $submissionFolder->CanViewType, 'Submission folder has correct permissions');
$this->assertNotEmpty($submissionFolder->ViewerGroups()->find('Code', 'administrators'), 'Submission folder is limited to administrators');
// subfolder name
$submissionSubFolder = UserDefinedFormController::getFormSubmissionFolder('test-form');
$this->assertNotEmpty($submissionSubFolder, 'Submission subfolder has been created');
$this->assertEquals('Form-submissions/test-form/', $submissionSubFolder->getFilename(), 'Submission sub folder got created under correct name');
$this->assertEquals(InheritedPermissions::INHERIT, $submissionSubFolder->CanViewType, 'Submission sub folder inherit permission from parent');
// make sure parent folder permission don't get overridden
$submissionFolder = Folder::find('Form-submissions');
$submissionFolder->CanViewType = InheritedPermissions::INHERIT;
$submissionFolder->write();
$submissionSubFolder = UserDefinedFormController::getFormSubmissionFolder('test-form-2');
$submissionFolder = Folder::find('Form-submissions');
$this->assertEquals(InheritedPermissions::INHERIT, $submissionFolder->CanViewType, 'Submission sub folder inherit permission from parent');
// Submission folder get recreated
$submissionFolder->delete();
$submissionFolder = Folder::find('Form-submissions');
$this->assertEmpty($submissionFolder, 'Submission folder does has been deleted.');
$submissionSubFolder = UserDefinedFormController::getFormSubmissionFolder('test-form-3');
$submissionFolder = Folder::find('Form-submissions');
$this->assertNotEmpty($submissionFolder, 'Submission folder got recreated');
$this->assertEquals('Form-submissions/', $submissionFolder->getFilename(), 'Submission folder got recreated under correct name');
$this->assertEquals(InheritedPermissions::ONLY_THESE_USERS, $submissionFolder->CanViewType, 'Submission folder has correct permissions');
$this->assertNotEmpty($submissionFolder->ViewerGroups()->find('Code', 'administrators'), 'Submission folder is limited to administrators');
}
}