From 1b8776926e94ef120399b0a6eb691900f1d4b1fd Mon Sep 17 00:00:00 2001 From: Gani Georgiev Date: Mon, 17 Apr 2023 13:28:41 +0300 Subject: [PATCH] updated protected files visualization --- CHANGELOG.md | 2 ++ .../components/records/RecordFileThumb.svelte | 14 ++------ .../records/RecordUpsertPanel.svelte | 5 ++- .../records/fields/AuthFields.svelte | 15 ++++---- .../records/fields/FileField.svelte | 8 ++++- ui/src/stores/collections.js | 10 +++--- ui/src/utils/ApiClient.js | 36 +++++++++++++------ 7 files changed, 54 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44ec4f15..565b6c20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ - Refreshed the OAuth2 Admin UI. +- Added auto "draft" to allow restoring previous record state in case of accidental reload or power outage. + ## v0.14.5 diff --git a/ui/src/components/records/RecordFileThumb.svelte b/ui/src/components/records/RecordFileThumb.svelte index f609ede3..900a82ff 100644 --- a/ui/src/components/records/RecordFileThumb.svelte +++ b/ui/src/components/records/RecordFileThumb.svelte @@ -2,7 +2,6 @@ import ApiClient from "@/utils/ApiClient"; import CommonHelper from "@/utils/CommonHelper"; import PreviewPopup from "@/components/base/PreviewPopup.svelte"; - import { privateFilesCollectionsCache } from "@/stores/collections"; export let record = null; export let filename = ""; @@ -14,16 +13,7 @@ let token = ""; let isLoadingToken = false; - $: withToken = - typeof $privateFilesCollectionsCache[record?.collectionId] !== "undefined" - ? $privateFilesCollectionsCache[record?.collectionId] - : true; - - $: if (withToken) { - loadFileToken(); - } else { - token = ""; - } + loadFileToken(); $: type = CommonHelper.getFileType(filename); @@ -39,7 +29,7 @@ isLoadingToken = true; try { - token = await ApiClient.getAdminFileToken(); + token = await ApiClient.getAdminFileToken(record.collectionId); } catch (err) { console.warn("File token failure:", err); } diff --git a/ui/src/components/records/RecordUpsertPanel.svelte b/ui/src/components/records/RecordUpsertPanel.svelte index edd9daca..ed27479f 100644 --- a/ui/src/components/records/RecordUpsertPanel.svelte +++ b/ui/src/components/records/RecordUpsertPanel.svelte @@ -92,6 +92,9 @@ initialDraft = getDraft(); if (!initialDraft || areRecordsEqual(record, initialDraft)) { initialDraft = null; + } else { + delete initialDraft.password; + delete initialDraft.passwordConfirm; } originalSerializedData = JSON.stringify(record); @@ -482,7 +485,7 @@ {#if collection?.isAuth} - + {#if collection?.schema?.length}
diff --git a/ui/src/components/records/fields/AuthFields.svelte b/ui/src/components/records/fields/AuthFields.svelte index e79d5995..cf2409e4 100644 --- a/ui/src/components/records/fields/AuthFields.svelte +++ b/ui/src/components/records/fields/AuthFields.svelte @@ -9,6 +9,7 @@ export let collection = new Collection(); export let record = new Record(); + export let isNew = record.$isNew; let originalUsername = record.username || null; @@ -28,15 +29,15 @@
- + @@ -69,7 +70,7 @@
- {#if !record.$isNew} + {#if !isNew} {/if} - {#if record.$isNew || changePasswordToggle} + {#if isNew || changePasswordToggle}
@@ -131,7 +132,7 @@ id={uniqueId} bind:checked={record.verified} on:change|preventDefault={(e) => { - if (record.$isNew) { + if (isNew) { return; // no confirmation required } confirm( diff --git a/ui/src/components/records/fields/FileField.svelte b/ui/src/components/records/fields/FileField.svelte index d3c8e263..fb3fa20c 100644 --- a/ui/src/components/records/fields/FileField.svelte +++ b/ui/src/components/records/fields/FileField.svelte @@ -6,6 +6,7 @@ import Field from "@/components/base/Field.svelte"; import UploadedFilePreview from "@/components/base/UploadedFilePreview.svelte"; import RecordFileThumb from "@/components/records/RecordFileThumb.svelte"; + import { onMount } from "svelte"; export let record; export let value = ""; @@ -16,6 +17,7 @@ let fileInput; let filesListElem; let isDragOver = false; + let fileToken = ""; // normalize uploadedFiles type $: if (!Array.isArray(uploadedFiles)) { @@ -93,6 +95,10 @@ uploadedFiles = uploadedFiles; } + + onMount(async () => { + fileToken = await ApiClient.getAdminFileToken(record.collectionId); + });
{ @@ -82,7 +82,7 @@ export async function loadCollections(activeId = null) { } function refreshProtectedFilesCollectionsCache() { - privateFilesCollectionsCache.update((cache) => { + protectedFilesCollectionsCache.update((cache) => { collections.update((current) => { for (let c of current) { cache[c.id] = !!c.schema?.find((f) => f.type == "file" && f.options?.protected); diff --git a/ui/src/utils/ApiClient.js b/ui/src/utils/ApiClient.js index 87d2006b..8ac8ace0 100644 --- a/ui/src/utils/ApiClient.js +++ b/ui/src/utils/ApiClient.js @@ -1,10 +1,13 @@ import PocketBase, { LocalAuthStore, Admin, isTokenExpired } from "pocketbase"; // --- -import CommonHelper from "@/utils/CommonHelper"; -import { replace } from "svelte-spa-router"; -import { addErrorToast } from "@/stores/toasts"; -import { setErrors } from "@/stores/errors"; -import { setAdmin } from "@/stores/admin"; +import CommonHelper from "@/utils/CommonHelper"; +import { replace } from "svelte-spa-router"; +import { get } from "svelte/store"; +import { addErrorToast } from "@/stores/toasts"; +import { setErrors } from "@/stores/errors"; +import { setAdmin } from "@/stores/admin"; +import { protectedFilesCollectionsCache } from "@/stores/collections"; + const adminFileTokenKey = "pb_admin_file_token"; @@ -17,7 +20,7 @@ PocketBase.prototype.logout = function(redirect = true) { this.authStore.clear(); if (redirect) { - replace('/login'); + replace("/login"); } }; @@ -28,7 +31,7 @@ PocketBase.prototype.logout = function(redirect = true) { * @param {Boolean} notify Whether to add a toast notification. * @param {String} defaultMsg Default toast notification message if the error doesn't have one. */ -PocketBase.prototype.errorResponseHandler = function(err, notify = true, defaultMsg = '') { +PocketBase.prototype.errorResponseHandler = function(err, notify = true, defaultMsg = "") { if (!err || !(err instanceof Error) || err.isAbort) { return; } @@ -61,15 +64,28 @@ PocketBase.prototype.errorResponseHandler = function(err, notify = true, default // forbidden if (statusCode === 403) { this.cancelAllRequests(); - return replace('/'); + return replace("/"); } }; /** * @return {Promise} */ -PocketBase.prototype.getAdminFileToken = async function() { - let token = localStorage.getItem(adminFileTokenKey) || ''; +PocketBase.prototype.getAdminFileToken = async function(collectionId = "") { + let needToken = true; + + if (collectionId) { + const protectedCollections = get(protectedFilesCollectionsCache); + needToken = typeof protectedCollections[collectionId] !== "undefined" + ? protectedCollections[collectionId] + : true; + } + + if (!needToken) { + return ""; + } + + let token = localStorage.getItem(adminFileTokenKey) || ""; // request a new token only if the previous one is missing or will expire soon if (!token || isTokenExpired(token, 15)) {