mirror of
https://github.com/pocketbase/pocketbase.git
synced 2026-10-29 00:10:24 +01:00
reload trusted proxy info UI after settings save
This commit is contained in:
1 parent
dbcd95eb62
commit
8d0881db3f
4 files changed
+22
-15
No files matched your search
@@ -4,6 +4,8 @@
|
||||
|
||||
- Added the local time zone name next to the `date` field label.
|
||||
|
||||
- Reload trusted proxy info UI after settings save.
|
||||
|
||||
|
||||
## v0.37.4
|
||||
|
||||
|
||||
@@ -62,8 +62,8 @@ To target the newly submitted ones you can use @request.body.*.`)})],name:`updat
|
||||
{MMM} {DD}`,null,`
|
||||
{MMM} {DD}`,null,null,null,1],[60,`{h}:{mm}{aa}`,`
|
||||
{MMM} {DD}`,null,`
|
||||
{MMM} {DD}`,null,null,null,1]],grid:{show:!0,stroke:o,width:1},ticks:{show:!0,stroke:o,width:1,size:5}},{show:!0,stroke:a,grid:{show:!0,stroke:o,width:1},ticks:{show:!0,stroke:o,width:1,size:5}}],plugins:[Rr(),Ir(r),Lr(r)]};e._uplot?.destroy(),e._uplot=new uPlot(l,n,e)}function Ir(e){let n;return{hooks:{init:r=>{r.over.ondblclick=n=>{e.zoom={}},n=watch(()=>{!e.zoom?.min||!e.zoom?.max?Pr(r):r.setScale(`x`,{min:e.zoom.min,max:e.zoom.max})})},destroy:e=>{n?.unwatch()},setSelect:n=>{n.select.width>0&&(e.zoom={min:n.posToVal(n.select.left,`x`),max:n.posToVal(n.select.left+n.select.width,`x`)})}}}}function Lr(e){let n;return{hooks:{init:r=>{let i=r.root.querySelectorAll(`.u-axis`);if(!i.length){console.warn(`xPanPlugin requires x axis to be defined`);return}i[0].addEventListener(`mousedown`,i=>{if(!e.zoom?.min)return;let a=i.clientX,{min:o,max:s}=r.scales.x,c=r.bbox.width,l=(s-o)/(c/uPlot.pxRatio),u=i=>{let c=(a-i.clientX)*l;r.setScale(`x`,{min:o+c,max:s+c}),clearTimeout(n),n=setTimeout(()=>{r?.scales?.x&&(e.zoom={min:r.scales.x.min,max:r.scales.x.max})},100)},d=e=>{document.removeEventListener(`mousemove`,u),document.removeEventListener(`mouseup`,d)};document.addEventListener(`mousemove`,u),document.addEventListener(`mouseup`,d)})},destroy:e=>{n&&clearTimeout(n)}}}}function Rr(e){let n;return{hooks:{init:e=>{let r=e.over;n=store({date:``,total:0,left:0,top:0,show:!1});let i=t.div({className:()=>`chart-tooltip ${n.show?``:`hidden`}`,onmount(e){e._positionWatcher?.unwatch(),e._positionWatcher=watch(()=>[n.left,n.top],()=>{if(!e)return;let i=e.getBoundingClientRect(),a=n.left;a<0?a=0:a+i.width>r.clientWidth&&(a=r.clientWidth-i.width),e.style.left=a+`px`;let o=n.top-i.height-5;o<0&&(o=n.top+5,o+i.high>r.clientHeight&&(o=r.clientHeight-i.height)),e.style.top=o+`px`})},onunmount(e){e._positionWatcher?.unwatch()}},t.div({className:`content-primary`},()=>`${n.total} ${n.total==1?`request`:`requests`}`),t.div({className:`content-secondary`},()=>n.date));r.appendChild(i),r.addEventListener(`mouseleave`,()=>{n&&(n.show=!1)})},destroy:()=>{n.show=!1},setCursor:e=>{if(!n)return;let r=e.data[0][e.cursor.idx]||0,i=e.data[1][e.cursor.idx]||0;if(r==0||i==0){n.show=!1;return}n.show=!0,n.total=i;let a=new Date(r*1e3),o=new Date(r*1e3+36e5),s=a.toLocaleString(`default`,{month:`short`}),c=a.getDate().toString().padStart(2,`0`);n.date=`${s} ${c} ${zr(a)}-${zr(o)}`,n.left=Math.round(e.valToPos(r,`x`)),n.top=Math.round(e.valToPos(i,`y`))}}}}function zr(e){let n=e.getHours(),r=n>=12?`pm`:`am`;return n=n%12||12,n+r}var Br=50;function Vr(e){let n=store({logs:[],lastLoadCount:0,lastPage:1,bulkSelected:{},get canLoadMore(){return n.lastLoadCount>=Br},get totalSelected(){return Object.keys(n.bulkSelected).length},get areAllSelected(){return n.logs.length&&n.logs.length==n.totalSelected}});async function r(r=!1){e.isListLoading=!0;try{let i=r?1:n.lastPage+1,a=(e.presets||[]).concat(app.utils.normalizeSearchFilter(e.filter,[`level`,`message`,`data`]));if(e.zoom?.min&&e.zoom?.max){let n=new Date(e.zoom.min*1e3);n.setSeconds(0),n.setMilliseconds(0);let r=app.utils.toRFC3339Datetime(n),i=new Date(e.zoom.max*1e3);i.setSeconds(59),i.setMilliseconds(999);let o=app.utils.toRFC3339Datetime(i);a.push(`created >= "${r}" && created <= "${o}"`)}else i>1&&a.push(`created <= "${n.logs[n.logs.length-1].created}"`);let o=await app.pb.logs.getList(i,Br,{skipTotal:1,sort:`-@rowid`,requestKey:`logs_list`,filter:a.filter(Boolean).map(e=>`(`+e+`)`).join(`&&`)});o.page==1&&(n.logs=[],n.bulkSelected={}),n.lastPage=o.page,n.lastLoadCount=o.items.length;for(let e=0;e<o.items.length;e++)app.utils.pushOrReplaceObject(n.logs,o.items[e]),e>1&&e%20==0&&await new Promise(e=>setTimeout(e,20));e.isListLoading=!1,e.isFirstLoadReady||=!0}catch(n){n.isAbort||(e.isListLoading=!1,app.checkApiError(n))}}function i(e=!0){let r={};if(e)for(let e of n.logs)r[e.id]=e;n.bulkSelected=r}function a(e){let n=[];if(!e.data)return n;if(e.data.type==`request`){for(let r of[`status`,`execTime`,`auth`,`authId`,`userIP`])e.data[r]!==void 0&&n.push({key:r});e.data.referer&&!e.data.referer.includes(window.location.host)&&n.push({key:`referer`})}else{let r=Object.keys(e.data);for(let e of r)e!=`error`&&e!=`details`&&n.length<6&&n.push({key:e})}return e.data.error&&n.push({key:`error`,label:`danger`}),e.data.details&&n.push({key:`details`,label:`warning`}),n}let o=/[-:\. ]/gi;function s(){let e=Object.values(n.bulkSelected).sort((e,n)=>e.created<n.created?1:e.created>n.created?-1:0);if(!e.length)return;if(e.length==1)return app.utils.downloadJSON(e[0],`log_`+e[0].created.replaceAll(o,``)+`.json`);let r=e[0].created.replaceAll(o,``),i=e[e.length-1].created.replaceAll(o,``);return app.utils.downloadJSON(e,`${e.length}_logs_${i}_to_${r}.json`)}let c=[];return t.div({pbEvent:`logsList`,className:`page-table-wrapper`,onmount(n){c.push(watch(()=>[e.filter,e.presets?.length],()=>{e.zoom={}}),watch(()=>[e.reset,e.filter,e.presets?.length,e.zoom?.min,e.zoom?.max],()=>{r(!0),n&&(n.scrollTop=0)}))},onunmount()
Line truncated
|
||||
It is recommend to list it as trusted.`,`right`)});if(i.isEnabled&&i.possibleProxyHeader&&!e.formSettings.trustedProxy.headers.includes(i.possibleProxyHeader))return t.i({className:`ri-alert-line txt-hint`,ariaDescription:app.attrs.tooltip(`The configured proxy header doesn't match with the detected one.`,`right`)})},t.div({className:`flex-fill`}),()=>i.isEnabled?t.span({className:`label success`},`Enabled`):t.span({className:`label`},`Disabled`),()=>{if(!app.utils.isEmpty(app.store.errors?.trustedProxy))return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.p({className:`m-t-0`},`Below you should see your real IP. If not - configure the correct proxy header for your environment.`),t.div({hidden:()=>i.isLoading,className:`alert info m-b-sm`},t.div({className:`flex gap-5`},t.span(null,`Resolved user IP:`),t.strong(null,()=>i.realIP||`N/A`)),t.div({className:`flex gap-5`},t.span(null,`Detected proxy header:`),t.strong(null,()=>i.possibleProxyHeader||`N/A`))),t.div({className:`content m-b-sm`},t.p(null,`
|
||||
{MMM} {DD}`,null,null,null,1]],grid:{show:!0,stroke:o,width:1},ticks:{show:!0,stroke:o,width:1,size:5}},{show:!0,stroke:a,grid:{show:!0,stroke:o,width:1},ticks:{show:!0,stroke:o,width:1,size:5}}],plugins:[Rr(),Ir(r),Lr(r)]};e._uplot?.destroy(),e._uplot=new uPlot(l,n,e)}function Ir(e){let n;return{hooks:{init:r=>{r.over.ondblclick=n=>{e.zoom={}},n=watch(()=>{!e.zoom?.min||!e.zoom?.max?Pr(r):r.setScale(`x`,{min:e.zoom.min,max:e.zoom.max})})},destroy:e=>{n?.unwatch()},setSelect:n=>{n.select.width>0&&(e.zoom={min:n.posToVal(n.select.left,`x`),max:n.posToVal(n.select.left+n.select.width,`x`)})}}}}function Lr(e){let n;return{hooks:{init:r=>{let i=r.root.querySelectorAll(`.u-axis`);if(!i.length){console.warn(`xPanPlugin requires x axis to be defined`);return}i[0].addEventListener(`mousedown`,i=>{if(!e.zoom?.min)return;let a=i.clientX,{min:o,max:s}=r.scales.x,c=r.bbox.width,l=(s-o)/(c/uPlot.pxRatio),u=i=>{let c=(a-i.clientX)*l;r.setScale(`x`,{min:o+c,max:s+c}),clearTimeout(n),n=setTimeout(()=>{r?.scales?.x&&(e.zoom={min:r.scales.x.min,max:r.scales.x.max})},100)},d=e=>{document.removeEventListener(`mousemove`,u),document.removeEventListener(`mouseup`,d)};document.addEventListener(`mousemove`,u),document.addEventListener(`mouseup`,d)})},destroy:e=>{n&&clearTimeout(n)}}}}function Rr(e){let n;return{hooks:{init:e=>{let r=e.over;n=store({date:``,total:0,left:0,top:0,show:!1});let i=t.div({className:()=>`chart-tooltip ${n.show?``:`hidden`}`,onmount(e){e._positionWatcher?.unwatch(),e._positionWatcher=watch(()=>[n.left,n.top],()=>{if(!e)return;let i=e.getBoundingClientRect(),a=n.left;a<0?a=0:a+i.width>r.clientWidth&&(a=r.clientWidth-i.width),e.style.left=a+`px`;let o=n.top-i.height-5;o<0&&(o=n.top+5,o+i.high>r.clientHeight&&(o=r.clientHeight-i.height)),e.style.top=o+`px`})},onunmount(e){e._positionWatcher?.unwatch()}},t.div({className:`content-primary`},()=>`${n.total} ${n.total==1?`request`:`requests`}`),t.div({className:`content-secondary`},()=>n.date));r.appendChild(i),r.addEventListener(`mouseleave`,()=>{n&&(n.show=!1)})},destroy:()=>{n.show=!1},setCursor:e=>{if(!n)return;let r=e.data[0][e.cursor.idx]||0,i=e.data[1][e.cursor.idx]||0;if(r==0||i==0){n.show=!1;return}n.show=!0,n.total=i;let a=new Date(r*1e3),o=new Date(r*1e3+36e5),s=a.toLocaleString(`default`,{month:`short`}),c=a.getDate().toString().padStart(2,`0`);n.date=`${s} ${c} ${zr(a)}-${zr(o)}`,n.left=Math.round(e.valToPos(r,`x`)),n.top=Math.round(e.valToPos(i,`y`))}}}}function zr(e){let n=e.getHours(),r=n>=12?`pm`:`am`;return n=n%12||12,n+r}var Br=50;function Vr(e){let n=store({logs:[],lastLoadCount:0,lastPage:1,bulkSelected:{},get canLoadMore(){return n.lastLoadCount>=Br},get totalSelected(){return Object.keys(n.bulkSelected).length},get areAllSelected(){return n.logs.length&&n.logs.length==n.totalSelected}});async function r(r=!1){e.isListLoading=!0;try{let i=r?1:n.lastPage+1,a=(e.presets||[]).concat(app.utils.normalizeSearchFilter(e.filter,[`level`,`message`,`data`]));if(e.zoom?.min&&e.zoom?.max){let n=new Date(e.zoom.min*1e3);n.setSeconds(0),n.setMilliseconds(0);let r=app.utils.toRFC3339Datetime(n),i=new Date(e.zoom.max*1e3);i.setSeconds(59),i.setMilliseconds(999);let o=app.utils.toRFC3339Datetime(i);a.push(`created >= "${r}" && created <= "${o}"`)}else i>1&&a.push(`created <= "${n.logs[n.logs.length-1].created}"`);let o=await app.pb.logs.getList(i,Br,{skipTotal:1,sort:`-@rowid`,requestKey:`logs_list`,filter:a.filter(Boolean).map(e=>`(`+e+`)`).join(`&&`)});o.page==1&&(n.logs=[],n.bulkSelected={}),n.lastPage=o.page,n.lastLoadCount=o.items.length;for(let e=0;e<o.items.length;e++)app.utils.pushOrReplaceObject(n.logs,o.items[e]),e>1&&e%20==0&&await new Promise(e=>setTimeout(e,20));e.isListLoading=!1,e.isFirstLoadReady||=!0}catch(n){n.isAbort||(e.isListLoading=!1,app.checkApiError(n))}}function i(e=!0){let r={};if(e)for(let e of n.logs)r[e.id]=e;n.bulkSelected=r}function a(e){let n=[];if(!e.data)return n;if(e.data.type==`request`){for(let r of[`status`,`execTime`,`auth`,`authId`,`userIP`])e.data[r]!==void 0&&n.push({key:r});e.data.referer&&!e.data.referer.includes(window.location.host)&&n.push({key:`referer`})}else{let r=Object.keys(e.data);for(let e of r)e!=`error`&&e!=`details`&&n.length<6&&n.push({key:e})}return e.data.error&&n.push({key:`error`,label:`danger`}),e.data.details&&n.push({key:`details`,label:`warning`}),n}let o=/[-:\. ]/gi;function s(){let e=Object.values(n.bulkSelected).sort((e,n)=>e.created<n.created?1:e.created>n.created?-1:0);if(!e.length)return;if(e.length==1)return app.utils.downloadJSON(e[0],`log_`+e[0].created.replaceAll(o,``)+`.json`);let r=e[0].created.replaceAll(o,``),i=e[e.length-1].created.replaceAll(o,``);return app.utils.downloadJSON(e,`${e.length}_logs_${i}_to_${r}.json`)}let c=[];return t.div({pbEvent:`logsList`,className:`page-table-wrapper`,onmount(n){c.push(watch(()=>[e.filter,e.presets?.length],()=>{e.zoom={}}),watch(()=>[e.reset,e.filter,e.presets?.length,e.zoom?.min,e.zoom?.max],()=>{r(!0),n&&(n.scrollTop=0)}))},onunmount()
Line truncated
|
||||
It is recommend to list it as trusted.`,`right`)});if(i.isEnabled&&i.possibleProxyHeader&&!e.formSettings.trustedProxy.headers.includes(i.possibleProxyHeader))return t.i({className:`ri-alert-line txt-hint`,ariaDescription:app.attrs.tooltip(`The configured proxy header doesn't match with the detected one.`,`right`)})},t.div({className:`flex-fill`}),()=>i.isEnabled?t.span({className:`label success`},`Enabled`):t.span({className:`label`},`Disabled`),()=>{if(!app.utils.isEmpty(app.store.errors?.trustedProxy))return t.i({className:`ri-error-warning-fill txt-danger`,ariaDescription:app.attrs.tooltip(`Has errors`,`left`)})}),t.p({className:`m-t-0`},`Below you should see your real IP. If not - configure the correct proxy header for your environment.`),t.div({className:`alert info m-b-sm`},t.div({className:`flex gap-5`},t.span(null,`Resolved user IP:`),t.strong(null,()=>i.isLoading?`...`:i.realIP||`N/A`)),t.div({className:`flex gap-5`},t.span(null,`Detected proxy header:`),t.strong(null,()=>i.isLoading?`...`:i.possibleProxyHeader||`N/A`))),t.div({className:`content m-b-sm`},t.p(null,`
|
||||
When PocketBase is deployed on platforms like Fly or it is accessible through proxies such as
|
||||
NGINX, requests from different users will originate from the same IP address (the IP of the proxy
|
||||
connecting to your PocketBase app).
|
||||
@@ -71,7 +71,7 @@ It is recommend to list it as trusted.`,`right`)});if(i.isEnabled&&i.possiblePro
|
||||
In this case to retrieve the actual user IP (used for rate limiting, logging, etc.) you need to
|
||||
properly configure your proxy and list below the trusted headers that PocketBase could use to
|
||||
extract the user IP.
|
||||
`),t.p({className:`txt-bold`},`When using such proxy, to avoid spoofing it is recommended to:`),t.ul({className:`txt-bold`},t.li(null,`use headers that are controlled only by the proxy and cannot be manually set by the users`),t.li(null,`make sure that the PocketBase server can be accessed ONLY through the proxy`)),t.p(null,`You can clear the headers field if PocketBase is not deployed behind a proxy.`)),t.div({className:`grid sm`},t.div({className:`col-lg-9`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`trustedProxy.headers`},`Trusted IP proxy headers`),t.input({type:`text`,id:`trustedProxy.headers`,name:`trustedProxy.headers`,placeholder:`Leave empty to disable`,value:()=>app.utils.joinNonEmpty(e.formSettings.trustedProxy.headers),oninput:n=>{let r=app.utils.splitNonEmpty(n.target.value,`,`),i=app.utils.joinNonEmpty(r);app.utils.joinNonEmpty(e.formSettings.trustedProxy.headers)!=i&&(e.formSettings.trustedProxy.headers=r)}})),t.div({className:`field addon`},t.button({type:`button`,className:()=>`btn sm secondary transparent ${app.utils.isEmpty(e.formSettings.trustedProxy.headers)?`hidden`:``}`,onclick:()=>{e.formSettings.trustedProxy.headers=[]}},t.span({className:`txt`},`Clear`)))),t.div({className:`field-help`},`Comma separated list of headers such as: `,t.div({className:`inline-flex gap-5`},()=>i.suggestedProxyHeaders.map(n=>t.div({type:`button`,className:`label sm link-hint`,onclick:()=>{e.formSettings.trustedProxy.headers=[n]},textContent:n}))))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`trustedProxy.useLeftmostIP`},t.span({className:`txt`},`IP priority`),t.i({className:`ri-information-line tooltip-right`,ariaDescription:app.attrs.tooltip(`This is in case the proxy returns more than 1 IP as header value. The rightmost IP is usually considered to be the more trustworthy but this could vary depending on the proxy.`)})),app.components.select({id:`trustedProxy.useLeftmostIP`,name:`trustedProxy.useLeftmostIP`,options:r,required:!0,value:()=>e.formSettings.trustedProxy.useLeftmostIP||!1,onchange:n=>{e.formSettings.trustedProxy.useLeftmostIP=n?.[0]?.value}})))))}function Xr(){app.store.title=`Application settings`;let e=store({isLoading:!1,isSaving:!1,formSettings:null,originalFormSettings:null,get originalFormSettingsHash(){return JSON.stringify(e.originalFormSettings)},get hasChanges(){return e.originalFormSettingsHash!=JSON.stringify(e.formSettings)}});n();async function n(){e.isLoading=!0;try{i(await app.pb.settings.getAll()),e.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function r(){if(!(e.isSaving||!e.hasChanges)){e.isSaving=!0,e.formSettings.rateLimits.rules=qr(e.formSettings.rateLimits.rules);try{let n=app.utils.filterRedactedProps(e.formSettings);i(await app.pb.settings.update(n)),app.toasts.success(`Successfully saved application settings.`)}catch(e){app.checkApiError(e)}e.isSaving=!1}}function i(n={}){if(app.store.settings=JSON.parse(JSON.stringify(n)),!n.meta?.accentColor){let e=window.getComputedStyle(document.documentElement)?.getPropertyValue(`--accentColor`);e?.startsWith(`#`)&&(n.meta=n.meta||{},n.meta.accentColor=e.toLowerCase()||``)}e.originalFormSettings={meta:n.meta||{},batch:n.batch||{},trustedProxy:n.trustedProxy||{headers:[]},rateLimits:n.rateLimits||{rules:[]}},qr(e.originalFormSettings.rateLimits.rules),e.formSettings=JSON.parse(JSON.stringify(e.originalFormSettings))}function a(){e.formSettings=JSON.parse(e.originalFormSettingsHash)}return t.div({pbEvent:`pageApplicationSettings`,className:`page page-application-settings`},$(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},`Application`))),t.div({className:`wrapper m-b-base`},()=>e.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`applicationSettingsForm`,className:`grid application-settings-form`,inert:()=>e.isSaving,onsubmit:e=>{e.preventDefault(),r()}},t.div({className:`col-md-5`},t.div({className:`field`},t.label({htmlFor:`meta.appName`},`Application name`),t.input({id:`meta.appName`,name:`meta.appName`,type:`text`,required:!0,value:()=>e.formSettings.meta.appName||``,oninput:n=>e.formSettings.meta.appName=n.target.value}))),t.div({className:`col-md-5`},t.div({className:`field`},t.label({htmlFor:`meta.appURL`},`Application URL`),t.input({id:`meta.appURL`,name:`meta.appURL`,type:`url`,required:!0,value:()=>e.formSettings.meta.appURL||``,oninput:n=>e.formSettings.meta.appURL=n.target.value}))),t.div({className:`col-md-2`},()=>Zr(e,e.isSaving)),t.div({className:`col-lg-12`},()=>Yr(e),()=>Jr(e),()=>Ur(e)),t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`meta.hideControls`,name:`meta.hideControls`,type:`checkbox`,className:`switch`,checked:()=>e.formSettings.meta.hideControls,onchange:n=>e.formSettings.meta.hideControls=n.target.checke
Line truncated
|
||||
`),t.p({className:`txt-bold`},`When using such proxy, to avoid spoofing it is recommended to:`),t.ul({className:`txt-bold`},t.li(null,`use headers that are controlled only by the proxy and cannot be manually set by the users`),t.li(null,`make sure that the PocketBase server can be accessed ONLY through the proxy`)),t.p(null,`You can clear the headers field if PocketBase is not deployed behind a proxy.`)),t.div({className:`grid sm`},t.div({className:`col-lg-9`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`trustedProxy.headers`},`Trusted IP proxy headers`),t.input({type:`text`,id:`trustedProxy.headers`,name:`trustedProxy.headers`,placeholder:`Leave empty to disable`,value:()=>app.utils.joinNonEmpty(e.formSettings.trustedProxy.headers),oninput:n=>{let r=app.utils.splitNonEmpty(n.target.value,`,`),i=app.utils.joinNonEmpty(r);app.utils.joinNonEmpty(e.formSettings.trustedProxy.headers)!=i&&(e.formSettings.trustedProxy.headers=r)}})),t.div({className:`field addon`},t.button({type:`button`,className:()=>`btn sm secondary transparent ${app.utils.isEmpty(e.formSettings.trustedProxy.headers)?`hidden`:``}`,onclick:()=>{e.formSettings.trustedProxy.headers=[]}},t.span({className:`txt`},`Clear`)))),t.div({className:`field-help`},`Comma separated list of headers such as: `,t.div({className:`inline-flex gap-5`},()=>i.suggestedProxyHeaders.map(n=>t.div({role:`button`,className:`label sm link-primary`,onclick:()=>{e.formSettings.trustedProxy.headers=[n]},textContent:n}))))),t.div({className:`col-lg-3`},t.div({className:`field`},t.label({htmlFor:`trustedProxy.useLeftmostIP`},t.span({className:`txt`},`IP priority`),t.i({className:`ri-information-line tooltip-right`,ariaDescription:app.attrs.tooltip(`This is in case the proxy returns more than 1 IP as header value. The rightmost IP is usually considered to be the more trustworthy but this could vary depending on the proxy.`)})),app.components.select({id:`trustedProxy.useLeftmostIP`,name:`trustedProxy.useLeftmostIP`,options:r,required:!0,value:()=>e.formSettings.trustedProxy.useLeftmostIP||!1,onchange:n=>{e.formSettings.trustedProxy.useLeftmostIP=n?.[0]?.value}})))))}function Xr(){app.store.title=`Application settings`;let e=store({isLoading:!1,isSaving:!1,formSettings:null,originalFormSettings:null,get originalFormSettingsHash(){return JSON.stringify(e.originalFormSettings)},get hasChanges(){return e.originalFormSettingsHash!=JSON.stringify(e.formSettings)}});n();async function n(){e.isLoading=!0;try{i(await app.pb.settings.getAll()),e.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function r(){if(!(e.isSaving||!e.hasChanges)){e.isSaving=!0,e.formSettings.rateLimits.rules=qr(e.formSettings.rateLimits.rules);try{let n=app.utils.filterRedactedProps(e.formSettings);i(await app.pb.settings.update(n)),app.toasts.success(`Successfully saved application settings.`)}catch(e){app.checkApiError(e)}e.isSaving=!1}}function i(n={}){if(app.store.settings=JSON.parse(JSON.stringify(n)),!n.meta?.accentColor){let e=window.getComputedStyle(document.documentElement)?.getPropertyValue(`--accentColor`);e?.startsWith(`#`)&&(n.meta=n.meta||{},n.meta.accentColor=e.toLowerCase()||``)}e.originalFormSettings={meta:n.meta||{},batch:n.batch||{},trustedProxy:n.trustedProxy||{headers:[]},rateLimits:n.rateLimits||{rules:[]}},qr(e.originalFormSettings.rateLimits.rules),e.formSettings=JSON.parse(JSON.stringify(e.originalFormSettings))}function a(){e.formSettings=JSON.parse(e.originalFormSettingsHash)}return t.div({pbEvent:`pageApplicationSettings`,className:`page page-application-settings`},$(),t.div({className:`page-content full-height`},t.header({className:`page-header`},t.nav({className:`breadcrumbs`},t.div({className:`breadcrumb-item`},`Settings`),t.div({className:`breadcrumb-item`},`Application`))),t.div({className:`wrapper m-b-base`},()=>e.isLoading?t.div({className:`block txt-center`},t.span({className:`loader lg`})):t.form({pbEvent:`applicationSettingsForm`,className:`grid application-settings-form`,inert:()=>e.isSaving,onsubmit:e=>{e.preventDefault(),r()}},t.div({className:`col-md-5`},t.div({className:`field`},t.label({htmlFor:`meta.appName`},`Application name`),t.input({id:`meta.appName`,name:`meta.appName`,type:`text`,required:!0,value:()=>e.formSettings.meta.appName||``,oninput:n=>e.formSettings.meta.appName=n.target.value}))),t.div({className:`col-md-5`},t.div({className:`field`},t.label({htmlFor:`meta.appURL`},`Application URL`),t.input({id:`meta.appURL`,name:`meta.appURL`,type:`url`,required:!0,value:()=>e.formSettings.meta.appURL||``,oninput:n=>e.formSettings.meta.appURL=n.target.value}))),t.div({className:`col-md-2`},()=>Zr(e,e.isSaving)),t.div({className:`col-lg-12`},()=>Yr(e),()=>Jr(e),()=>Ur(e)),t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`meta.hideControls`,name:`meta.hideControls`,type:`checkbox`,className:`switch`,checked:()=>e.formSettings.meta.hideControls,onchange:n=>e.formSettings.meta.hideControls=n.target.che
Line truncated
|
||||
Records update will also require an extra unlock step before save.`)})))),t.div({className:`col-lg-12`},t.hr()),t.div({className:`col-lg-12`},t.div({className:`flex`},t.div({className:`m-r-auto`}),t.button({type:`button`,className:`btn transparent secondary`,disabled:()=>e.isSaving,hidden:()=>!e.hasChanges,onclick:a},t.span({className:`txt`},`Cancel`)),t.button({className:()=>`btn expanded ${e.isSaving?`loading`:``}`,disabled:()=>!e.hasChanges||e.isSaving},t.span({className:`txt`},`Save changes`)))))),t.footer({className:`page-footer`},app.components.credits())))}function Zr(e){let n=`accent_`+app.utils.randomString(),r=store({isTooLight:!1}),i,a;function o(e){clearTimeout(a),document.documentElement.style.setProperty(`--animationSpeed`,`0`),e?document.documentElement.style.setProperty(`--accentColor`,e.toLowerCase()):document.documentElement.style.removeProperty(`--accentColor`),a=setTimeout(()=>{document.documentElement.style.removeProperty(`--animationSpeed`)},100)}let s=[watch(()=>e.formSettings?.meta?.accentColor,e=>{clearTimeout(i),i=setTimeout(()=>{o(e)},100)})];return t.div({className:`field`,ariaDescription:app.attrs.tooltip(()=>r.isTooLight?`Invalid - color is too light`:``),onunmount:()=>{clearTimeout(i),o(e.formSettings.meta.accentColor),s.forEach(e=>e?.unwatch())}},t.label({htmlFor:n},t.span({className:`txt`},`Accent`),t.i({hidden:()=>!r.isTooLight,className:`txt-warning ri-alert-line`})),app.components.colorPicker({id:n,name:`meta.accentColor`,predefinedColors:()=>app.store.predefinedAccentColors,value:()=>e.formSettings.meta.accentColor,onchange:n=>{if(r.isTooLight=!1,!app.utils.isDarkEnoughForWhiteText(n)){r.isTooLight=!0;return}e.formSettings.meta.accentColor=n}}))}function Qr(e={}){let n=store({onsave:null}),r=app.utils.extendStore(n,e),i=[{cron:`0 0 * * *`,label:`Every day at 00:00h`},{cron:`0 0 * * 0`,label:`Every sunday at 00:00h`},{cron:`0 0 * * 1,3`,label:`Every Mon and Wed at 00:00h`},{cron:`0 0 1 * *`,label:`Every first day of the month at 00:00h`}],a=store({showForm:!1,isLoading:!1,isSaving:!1,formSettings:null,initSerialized:`null`,enableAutoBackups:!1,get hasChanges(){return a.initSerialized!=JSON.stringify(a.formSettings)}});async function o(){a.isLoading=!0;try{c(await app.pb.settings.getAll()),a.isLoading=!1}catch(e){e.isAbort||app.checkApiError(e)}}async function s(){if(!(a.isSaving||!a.hasChanges)){a.isSaving=!0;try{let e=app.utils.filterRedactedProps(a.formSettings),r=await app.pb.settings.update(e);n.onsave?.(r),c(r),app.toasts.success(`Successfully saved backups settings.`)}catch(e){app.checkApiError(e)}a.isSaving=!1}}function c(e={}){app.store.settings=JSON.parse(JSON.stringify(e)),a.formSettings={backups:e?.backups||{}},a.enableAutoBackups=!!a.formSettings.backups.cron,a.initSerialized=JSON.stringify(a.formSettings)}function l(){a.formSettings=JSON.parse(a.initSerialized),a.enableAutoBackups=!!a.formSettings.backups.cron}return r.push(watch(()=>{!a.enableAutoBackups&&a.formSettings?.backups?.cron&&(a.formSettings.backups.cron=``)})),t.div({className:`block backups-settings-form-wrapper`,onmount:()=>{o()},onunmount:()=>{r.forEach(e=>e?.unwatch())}},t.button({type:`button`,className:()=>`btn secondary ${a.isLoading?`loading`:``}`,disabled:()=>a.isLoading||a.hasChanges,onclick:()=>a.showForm=!a.showForm},t.span({className:`txt`},`Backup options`),t.i({className:()=>a.showForm?`ri-arrow-up-s-line`:`ri-arrow-down-s-line`,ariaHidden:!0})),app.components.slide(()=>a.showForm,t.form({pbEvent:`backupsSettingsForm`,className:`grid backups-settings-form m-t-base`,inert:()=>a.isSaving,onsubmit:e=>{e.preventDefault(),s()}},()=>a.isLoading?t.div({className:`col-lg-12 txt-center`},t.span({className:`loader lg`})):[t.div({className:`col-lg-12`},t.div({className:`field`},t.input({id:`enableAutoBackupsToggle`,type:`checkbox`,className:`switch`,checked:()=>a.enableAutoBackups,onchange:e=>{a.enableAutoBackups=e.target.checked,a.formSettings.backups.cron||(a.formSettings.backups.cron=i[0].cron)}}),t.label({htmlFor:`enableAutoBackupsToggle`},`Enable auto backups`)),app.components.slide(()=>a.enableAutoBackups,t.div({className:`grid m-t-base m-b-base`},t.div({className:`col-lg-6`},t.div({className:`fields`},t.div({className:`field`},t.label({htmlFor:`backups.cron`},`Cron expression`),t.input({id:`backups.cron`,name:`backups.cron`,className:`txt-code`,type:`text`,placeholder:`e.g. 0 0 * * *`,required:()=>a.enableAutoBackups,value:()=>a.formSettings.backups.cron,oninput:e=>a.formSettings.backups.cron=e.target.value})),t.div({className:`field addon`},t.button({type:`button`,className:`btn outline sm`,"html-popovertarget":`cron-presets-dropdown`},t.span({className:`txt`},`Presets`),t.i({className:`ri-arrow-drop-down-line`,ariaHidden:!0})),t.div({id:`cron-presets-dropdown`,className:`dropdown sm txt-nowrap`,popover:`auto`},()=>i.map(e=>t.button({type:`button`,className:()=>`dropdown-item ${a.formSettings.backups.cron==e.cron?`active`:``}`,textContent:e.label,onclick:n=>{a.formSettings.backups.cro
Line truncated
|
||||
@annually
|
||||
@monthly
|
||||
Vendored
+1
-1
@@ -13,7 +13,7 @@
|
||||
|
||||
<!-- prism -->
|
||||
<script src="./libs/prism/prism.js" data-manual></script>
|
||||
<script type="module" crossorigin src="./assets/index-CDUQtXaP.js"></script>
|
||||
<script type="module" crossorigin src="./assets/index-lWorQJPS.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="./assets/pocketbase.es-B_4DUNUU.js">
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-ouas71Vg.css">
|
||||
</head>
|
||||
|
||||
@@ -24,8 +24,6 @@ export function trustedProxyAccordion(pageData) {
|
||||
},
|
||||
});
|
||||
|
||||
loadProxyInfo();
|
||||
|
||||
async function loadProxyInfo() {
|
||||
proxyInfo.isLoading = true;
|
||||
|
||||
@@ -48,7 +46,17 @@ export function trustedProxyAccordion(pageData) {
|
||||
pbEvent: "trustedProxyAccordion",
|
||||
className: "accordion trusted-proxy-accordion",
|
||||
name: "settingsAccordion",
|
||||
open: () => (proxyInfo.isLoading ? false : null),
|
||||
onmount: (el) => {
|
||||
el._infoWatcher?.unwatch();
|
||||
el._infoWatcher = watch(() => JSON.stringify(app.store.settings?.trustedProxy), (newHash, oldHash) => {
|
||||
if (newHash != oldHash) {
|
||||
loadProxyInfo();
|
||||
}
|
||||
});
|
||||
},
|
||||
onunmount: (el) => {
|
||||
el._infoWatcher?.unwatch();
|
||||
},
|
||||
},
|
||||
t.summary(
|
||||
null,
|
||||
@@ -104,19 +112,16 @@ export function trustedProxyAccordion(pageData) {
|
||||
"Below you should see your real IP. If not - configure the correct proxy header for your environment.",
|
||||
),
|
||||
t.div(
|
||||
{
|
||||
hidden: () => proxyInfo.isLoading,
|
||||
className: "alert info m-b-sm",
|
||||
},
|
||||
{ className: "alert info m-b-sm" },
|
||||
t.div(
|
||||
{ className: "flex gap-5" },
|
||||
t.span(null, "Resolved user IP:"),
|
||||
t.strong(null, () => proxyInfo.realIP || "N/A"),
|
||||
t.strong(null, () => proxyInfo.isLoading ? "..." : (proxyInfo.realIP || "N/A")),
|
||||
),
|
||||
t.div(
|
||||
{ className: "flex gap-5" },
|
||||
t.span(null, "Detected proxy header:"),
|
||||
t.strong(null, () => proxyInfo.possibleProxyHeader || "N/A"),
|
||||
t.strong(null, () => proxyInfo.isLoading ? "..." : (proxyInfo.possibleProxyHeader || "N/A")),
|
||||
),
|
||||
),
|
||||
t.div(
|
||||
@@ -198,8 +203,8 @@ export function trustedProxyAccordion(pageData) {
|
||||
t.div({ className: "inline-flex gap-5" }, () => {
|
||||
return proxyInfo.suggestedProxyHeaders.map((header) => {
|
||||
return t.div({
|
||||
type: "button",
|
||||
className: "label sm link-hint",
|
||||
role: "button",
|
||||
className: "label sm link-primary",
|
||||
onclick: () => {
|
||||
pageData.formSettings.trustedProxy.headers = [header];
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user