added option to auto generate admin and auth record passwords from the Admin UI

This commit is contained in:
Gani Georgiev
2023-08-30 14:58:36 +03:00
parent ccb1c42220
commit e5b5c1f76f
58 changed files with 515 additions and 36525 deletions
@@ -10,6 +10,7 @@
import Field from "@/components/base/Field.svelte";
import Toggler from "@/components/base/Toggler.svelte";
import OverlayPanel from "@/components/base/OverlayPanel.svelte";
import SecretGeneratorButton from "@/components/base/SecretGeneratorButton.svelte";
const dispatch = createEventDispatcher();
const formId = "admin_" + CommonHelper.randomString(5);
@@ -208,6 +209,9 @@
required
bind:value={password}
/>
<div class="form-field-addon">
<SecretGeneratorButton />
</div>
</Field>
</div>
<div class="col-sm-6">
+6 -4
View File
@@ -81,10 +81,12 @@
<div class="flex-fill" />
<button type="button" class="btn btn-expanded" on:click={() => adminUpsertPanel?.show()}>
<i class="ri-add-line" />
<span class="txt">New admin</span>
</button>
<div class="btns-group">
<button type="button" class="btn btn-expanded" on:click={() => adminUpsertPanel?.show()}>
<i class="ri-add-line" />
<span class="txt">New admin</span>
</button>
</div>
</header>
<Searchbar
+1
View File
@@ -36,6 +36,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<i
class={copyTimeout ? successClasses : idleClasses}
aria-label={"Copy"}
use:tooltip={!copyTimeout ? "Copy" : ""}
on:click|stopPropagation={copy}
/>
@@ -0,0 +1,68 @@
<script>
import { createEventDispatcher, tick } from "svelte";
import CommonHelper from "@/utils/CommonHelper";
import Toggler from "@/components/base/Toggler.svelte";
import CopyIcon from "@/components/base/CopyIcon.svelte";
import tooltip from "@/actions/tooltip";
const dispatch = createEventDispatcher();
let classes = "btn-sm btn-hint btn-transparent";
export { classes as class };
export let length = 32;
let secret = "";
let secretElem;
let togglerActive = false;
async function generate() {
secret = CommonHelper.randomSecret(length);
dispatch("generate", secret);
await tick();
if (secretElem) {
let range = document.createRange();
range.selectNode(secretElem);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
}
</script>
<button
tabindex="-1"
type="button"
aria-label="Generate"
use:tooltip={togglerActive ? "" : "Generate"}
class="btn btn-circle {classes}"
>
<i class="ri-sparkling-line" />
<Toggler
class="dropdown dropdown-upside dropdown-center dropdown-nowrap"
bind:active={togglerActive}
on:show={generate}
>
<div class="flex flex-gap-5 p-5">
<span bind:this={secretElem} class="secret">{secret}</span>
<CopyIcon value={secret} />
<!-- svelte-ignore a11y-click-events-have-key-events -->
<i
class="ri-refresh-line txt-sm link-hint"
use:tooltip={"Refresh"}
aria-label="Refresh"
on:click={generate}
/>
</div>
</Toggler>
</button>
<style>
.secret {
font-family: monospace;
font-weight: normal;
user-select: all;
}
</style>
@@ -5,6 +5,7 @@
import { confirm } from "@/stores/confirmation";
import { removeError } from "@/stores/errors";
import Field from "@/components/base/Field.svelte";
import SecretGeneratorButton from "@/components/base/SecretGeneratorButton.svelte";
export let record;
export let collection;
@@ -102,6 +103,9 @@
required
bind:value={record.password}
/>
<div class="form-field-addon">
<SecretGeneratorButton />
</div>
</Field>
</div>
<div class="col-sm-6">
@@ -13,7 +13,7 @@
import SettingsSidebar from "@/components/settings/SettingsSidebar.svelte";
import BackupsList from "@/components/settings/BackupsList.svelte";
import S3Fields from "@/components/settings/S3Fields.svelte";
import BackupUploadBtn from "@/components/settings/BackupUploadBtn.svelte";
import BackupUploadButton from "@/components/settings/BackupUploadButton.svelte";
$pageTitle = "Backups";
@@ -109,7 +109,7 @@
<div class="flex m-b-sm flex-gap-10">
<span class="txt-xl">Backup and restore your PocketBase data</span>
<RefreshButton class="btn-sm" tooltip={"Refresh"} on:refresh={refreshList} />
<BackupUploadBtn class="btn-sm" on:success={refreshList} />
<BackupUploadButton class="btn-sm" on:success={refreshList} />
</div>
<BackupsList bind:this={backupsListComponent} />
+1 -4
View File
@@ -21,10 +21,7 @@
if (secret) {
secret = undefined;
} else {
secret =
typeof crypto != "undefined" && crypto.randomUUID
? crypto.randomUUID() + CommonHelper.randomString(14)
: CommonHelper.randomString(50);
secret = CommonHelper.randomSecret(50);
}
}}
>
+4
View File
@@ -43,6 +43,9 @@ button {
vertical-align: middle;
display: inline-block;
}
.dropdown {
user-select: text;
}
// background layer
&:before {
@@ -549,6 +552,7 @@ select {
// hints
.help-block {
@extend .content;
position: relative;
margin-top: 8px;
font-size: var(--smFontSize);
line-height: var(--smLineHeight);
+269 -1
View File
@@ -1,10 +1,12 @@
/*
* Remix Icon v2.5.0
* Remix Icon v3.5.0
* https://remixicon.com
* https://github.com/Remix-Design/RemixIcon
*
* Copyright RemixIcon.com
* Released under the Apache License Version 2.0
*
* Date: 2023-07-30
*/
i {
@@ -2292,3 +2294,269 @@ i {
.ri-zoom-out-line:before { content: "\f2dd"; }
.ri-zzz-fill:before { content: "\f2de"; }
.ri-zzz-line:before { content: "\f2df"; }
.ri-arrow-down-double-fill:before { content: "\f2e0"; }
.ri-arrow-down-double-line:before { content: "\f2e1"; }
.ri-arrow-left-double-fill:before { content: "\f2e2"; }
.ri-arrow-left-double-line:before { content: "\f2e3"; }
.ri-arrow-right-double-fill:before { content: "\f2e4"; }
.ri-arrow-right-double-line:before { content: "\f2e5"; }
.ri-arrow-turn-back-fill:before { content: "\f2e6"; }
.ri-arrow-turn-back-line:before { content: "\f2e7"; }
.ri-arrow-turn-forward-fill:before { content: "\f2e8"; }
.ri-arrow-turn-forward-line:before { content: "\f2e9"; }
.ri-arrow-up-double-fill:before { content: "\f2ea"; }
.ri-arrow-up-double-line:before { content: "\f2eb"; }
.ri-bard-fill:before { content: "\f2ec"; }
.ri-bard-line:before { content: "\f2ed"; }
.ri-bootstrap-fill:before { content: "\f2ee"; }
.ri-bootstrap-line:before { content: "\f2ef"; }
.ri-box-1-fill:before { content: "\f2f0"; }
.ri-box-1-line:before { content: "\f2f1"; }
.ri-box-2-fill:before { content: "\f2f2"; }
.ri-box-2-line:before { content: "\f2f3"; }
.ri-box-3-fill:before { content: "\f2f4"; }
.ri-box-3-line:before { content: "\f2f5"; }
.ri-brain-fill:before { content: "\f2f6"; }
.ri-brain-line:before { content: "\f2f7"; }
.ri-candle-fill:before { content: "\f2f8"; }
.ri-candle-line:before { content: "\f2f9"; }
.ri-cash-fill:before { content: "\f2fa"; }
.ri-cash-line:before { content: "\f2fb"; }
.ri-contract-left-fill:before { content: "\f2fc"; }
.ri-contract-left-line:before { content: "\f2fd"; }
.ri-contract-left-right-fill:before { content: "\f2fe"; }
.ri-contract-left-right-line:before { content: "\f2ff"; }
.ri-contract-right-fill:before { content: "\f300"; }
.ri-contract-right-line:before { content: "\f301"; }
.ri-contract-up-down-fill:before { content: "\f302"; }
.ri-contract-up-down-line:before { content: "\f303"; }
.ri-copilot-fill:before { content: "\f304"; }
.ri-copilot-line:before { content: "\f305"; }
.ri-corner-down-left-fill:before { content: "\f306"; }
.ri-corner-down-left-line:before { content: "\f307"; }
.ri-corner-down-right-fill:before { content: "\f308"; }
.ri-corner-down-right-line:before { content: "\f309"; }
.ri-corner-left-down-fill:before { content: "\f30a"; }
.ri-corner-left-down-line:before { content: "\f30b"; }
.ri-corner-left-up-fill:before { content: "\f30c"; }
.ri-corner-left-up-line:before { content: "\f30d"; }
.ri-corner-right-down-fill:before { content: "\f30e"; }
.ri-corner-right-down-line:before { content: "\f30f"; }
.ri-corner-right-up-fill:before { content: "\f310"; }
.ri-corner-right-up-line:before { content: "\f311"; }
.ri-corner-up-left-double-fill:before { content: "\f312"; }
.ri-corner-up-left-double-line:before { content: "\f313"; }
.ri-corner-up-left-fill:before { content: "\f314"; }
.ri-corner-up-left-line:before { content: "\f315"; }
.ri-corner-up-right-double-fill:before { content: "\f316"; }
.ri-corner-up-right-double-line:before { content: "\f317"; }
.ri-corner-up-right-fill:before { content: "\f318"; }
.ri-corner-up-right-line:before { content: "\f319"; }
.ri-cross-fill:before { content: "\f31a"; }
.ri-cross-line:before { content: "\f31b"; }
.ri-edge-new-fill:before { content: "\f31c"; }
.ri-edge-new-line:before { content: "\f31d"; }
.ri-equal-fill:before { content: "\f31e"; }
.ri-equal-line:before { content: "\f31f"; }
.ri-expand-left-fill:before { content: "\f320"; }
.ri-expand-left-line:before { content: "\f321"; }
.ri-expand-left-right-fill:before { content: "\f322"; }
.ri-expand-left-right-line:before { content: "\f323"; }
.ri-expand-right-fill:before { content: "\f324"; }
.ri-expand-right-line:before { content: "\f325"; }
.ri-expand-up-down-fill:before { content: "\f326"; }
.ri-expand-up-down-line:before { content: "\f327"; }
.ri-flickr-fill:before { content: "\f328"; }
.ri-flickr-line:before { content: "\f329"; }
.ri-forward-10-fill:before { content: "\f32a"; }
.ri-forward-10-line:before { content: "\f32b"; }
.ri-forward-15-fill:before { content: "\f32c"; }
.ri-forward-15-line:before { content: "\f32d"; }
.ri-forward-30-fill:before { content: "\f32e"; }
.ri-forward-30-line:before { content: "\f32f"; }
.ri-forward-5-fill:before { content: "\f330"; }
.ri-forward-5-line:before { content: "\f331"; }
.ri-graduation-cap-fill:before { content: "\f332"; }
.ri-graduation-cap-line:before { content: "\f333"; }
.ri-home-office-fill:before { content: "\f334"; }
.ri-home-office-line:before { content: "\f335"; }
.ri-hourglass-2-fill:before { content: "\f336"; }
.ri-hourglass-2-line:before { content: "\f337"; }
.ri-hourglass-fill:before { content: "\f338"; }
.ri-hourglass-line:before { content: "\f339"; }
.ri-javascript-fill:before { content: "\f33a"; }
.ri-javascript-line:before { content: "\f33b"; }
.ri-loop-left-fill:before { content: "\f33c"; }
.ri-loop-left-line:before { content: "\f33d"; }
.ri-loop-right-fill:before { content: "\f33e"; }
.ri-loop-right-line:before { content: "\f33f"; }
.ri-memories-fill:before { content: "\f340"; }
.ri-memories-line:before { content: "\f341"; }
.ri-meta-fill:before { content: "\f342"; }
.ri-meta-line:before { content: "\f343"; }
.ri-microsoft-loop-fill:before { content: "\f344"; }
.ri-microsoft-loop-line:before { content: "\f345"; }
.ri-nft-fill:before { content: "\f346"; }
.ri-nft-line:before { content: "\f347"; }
.ri-notion-fill:before { content: "\f348"; }
.ri-notion-line:before { content: "\f349"; }
.ri-openai-fill:before { content: "\f34a"; }
.ri-openai-line:before { content: "\f34b"; }
.ri-overline:before { content: "\f34c"; }
.ri-p2p-fill:before { content: "\f34d"; }
.ri-p2p-line:before { content: "\f34e"; }
.ri-presentation-fill:before { content: "\f34f"; }
.ri-presentation-line:before { content: "\f350"; }
.ri-replay-10-fill:before { content: "\f351"; }
.ri-replay-10-line:before { content: "\f352"; }
.ri-replay-15-fill:before { content: "\f353"; }
.ri-replay-15-line:before { content: "\f354"; }
.ri-replay-30-fill:before { content: "\f355"; }
.ri-replay-30-line:before { content: "\f356"; }
.ri-replay-5-fill:before { content: "\f357"; }
.ri-replay-5-line:before { content: "\f358"; }
.ri-school-fill:before { content: "\f359"; }
.ri-school-line:before { content: "\f35a"; }
.ri-shining-2-fill:before { content: "\f35b"; }
.ri-shining-2-line:before { content: "\f35c"; }
.ri-shining-fill:before { content: "\f35d"; }
.ri-shining-line:before { content: "\f35e"; }
.ri-sketching:before { content: "\f35f"; }
.ri-skip-down-fill:before { content: "\f360"; }
.ri-skip-down-line:before { content: "\f361"; }
.ri-skip-left-fill:before { content: "\f362"; }
.ri-skip-left-line:before { content: "\f363"; }
.ri-skip-right-fill:before { content: "\f364"; }
.ri-skip-right-line:before { content: "\f365"; }
.ri-skip-up-fill:before { content: "\f366"; }
.ri-skip-up-line:before { content: "\f367"; }
.ri-slow-down-fill:before { content: "\f368"; }
.ri-slow-down-line:before { content: "\f369"; }
.ri-sparkling-2-fill:before { content: "\f36a"; }
.ri-sparkling-2-line:before { content: "\f36b"; }
.ri-sparkling-fill:before { content: "\f36c"; }
.ri-sparkling-line:before { content: "\f36d"; }
.ri-speak-fill:before { content: "\f36e"; }
.ri-speak-line:before { content: "\f36f"; }
.ri-speed-up-fill:before { content: "\f370"; }
.ri-speed-up-line:before { content: "\f371"; }
.ri-tiktok-fill:before { content: "\f372"; }
.ri-tiktok-line:before { content: "\f373"; }
.ri-token-swap-fill:before { content: "\f374"; }
.ri-token-swap-line:before { content: "\f375"; }
.ri-unpin-fill:before { content: "\f376"; }
.ri-unpin-line:before { content: "\f377"; }
.ri-wechat-channels-fill:before { content: "\f378"; }
.ri-wechat-channels-line:before { content: "\f379"; }
.ri-wordpress-fill:before { content: "\f37a"; }
.ri-wordpress-line:before { content: "\f37b"; }
.ri-blender-fill:before { content: "\f37c"; }
.ri-blender-line:before { content: "\f37d"; }
.ri-emoji-sticker-fill:before { content: "\f37e"; }
.ri-emoji-sticker-line:before { content: "\f37f"; }
.ri-git-close-pull-request-fill:before { content: "\f380"; }
.ri-git-close-pull-request-line:before { content: "\f381"; }
.ri-instance-fill:before { content: "\f382"; }
.ri-instance-line:before { content: "\f383"; }
.ri-megaphone-fill:before { content: "\f384"; }
.ri-megaphone-line:before { content: "\f385"; }
.ri-pass-expired-fill:before { content: "\f386"; }
.ri-pass-expired-line:before { content: "\f387"; }
.ri-pass-pending-fill:before { content: "\f388"; }
.ri-pass-pending-line:before { content: "\f389"; }
.ri-pass-valid-fill:before { content: "\f38a"; }
.ri-pass-valid-line:before { content: "\f38b"; }
.ri-ai-generate:before { content: "\f38c"; }
.ri-calendar-close-fill:before { content: "\f38d"; }
.ri-calendar-close-line:before { content: "\f38e"; }
.ri-draggable:before { content: "\f38f"; }
.ri-font-family:before { content: "\f390"; }
.ri-font-mono:before { content: "\f391"; }
.ri-font-sans-serif:before { content: "\f392"; }
.ri-font-sans:before { content: "\f393"; }
.ri-hard-drive-3-fill:before { content: "\f394"; }
.ri-hard-drive-3-line:before { content: "\f395"; }
.ri-kick-fill:before { content: "\f396"; }
.ri-kick-line:before { content: "\f397"; }
.ri-list-check-3:before { content: "\f398"; }
.ri-list-indefinite:before { content: "\f399"; }
.ri-list-ordered-2:before { content: "\f39a"; }
.ri-list-radio:before { content: "\f39b"; }
.ri-openbase-fill:before { content: "\f39c"; }
.ri-openbase-line:before { content: "\f39d"; }
.ri-planet-fill:before { content: "\f39e"; }
.ri-planet-line:before { content: "\f39f"; }
.ri-prohibited-fill:before { content: "\f3a0"; }
.ri-prohibited-line:before { content: "\f3a1"; }
.ri-quote-text:before { content: "\f3a2"; }
.ri-seo-fill:before { content: "\f3a3"; }
.ri-seo-line:before { content: "\f3a4"; }
.ri-slash-commands:before { content: "\f3a5"; }
.ri-archive-2-fill:before { content: "\f3a6"; }
.ri-archive-2-line:before { content: "\f3a7"; }
.ri-inbox-2-fill:before { content: "\f3a8"; }
.ri-inbox-2-line:before { content: "\f3a9"; }
.ri-shake-hands-fill:before { content: "\f3aa"; }
.ri-shake-hands-line:before { content: "\f3ab"; }
.ri-supabase-fill:before { content: "\f3ac"; }
.ri-supabase-line:before { content: "\f3ad"; }
.ri-water-percent-fill:before { content: "\f3ae"; }
.ri-water-percent-line:before { content: "\f3af"; }
.ri-yuque-fill:before { content: "\f3b0"; }
.ri-yuque-line:before { content: "\f3b1"; }
.ri-crosshair-2-fill:before { content: "\f3b2"; }
.ri-crosshair-2-line:before { content: "\f3b3"; }
.ri-crosshair-fill:before { content: "\f3b4"; }
.ri-crosshair-line:before { content: "\f3b5"; }
.ri-file-close-fill:before { content: "\f3b6"; }
.ri-file-close-line:before { content: "\f3b7"; }
.ri-infinity-fill:before { content: "\f3b8"; }
.ri-infinity-line:before { content: "\f3b9"; }
.ri-rfid-fill:before { content: "\f3ba"; }
.ri-rfid-line:before { content: "\f3bb"; }
.ri-slash-commands-2:before { content: "\f3bc"; }
.ri-user-forbid-fill:before { content: "\f3bd"; }
.ri-user-forbid-line:before { content: "\f3be"; }
.ri-beer-fill:before { content: "\f3bf"; }
.ri-beer-line:before { content: "\f3c0"; }
.ri-circle-fill:before { content: "\f3c1"; }
.ri-circle-line:before { content: "\f3c2"; }
.ri-dropdown-list:before { content: "\f3c3"; }
.ri-file-image-fill:before { content: "\f3c4"; }
.ri-file-image-line:before { content: "\f3c5"; }
.ri-file-pdf-2-fill:before { content: "\f3c6"; }
.ri-file-pdf-2-line:before { content: "\f3c7"; }
.ri-file-video-fill:before { content: "\f3c8"; }
.ri-file-video-line:before { content: "\f3c9"; }
.ri-folder-image-fill:before { content: "\f3ca"; }
.ri-folder-image-line:before { content: "\f3cb"; }
.ri-folder-video-fill:before { content: "\f3cc"; }
.ri-folder-video-line:before { content: "\f3cd"; }
.ri-hexagon-fill:before { content: "\f3ce"; }
.ri-hexagon-line:before { content: "\f3cf"; }
.ri-menu-search-fill:before { content: "\f3d0"; }
.ri-menu-search-line:before { content: "\f3d1"; }
.ri-octagon-fill:before { content: "\f3d2"; }
.ri-octagon-line:before { content: "\f3d3"; }
.ri-pentagon-fill:before { content: "\f3d4"; }
.ri-pentagon-line:before { content: "\f3d5"; }
.ri-rectangle-fill:before { content: "\f3d6"; }
.ri-rectangle-line:before { content: "\f3d7"; }
.ri-robot-2-fill:before { content: "\f3d8"; }
.ri-robot-2-line:before { content: "\f3d9"; }
.ri-shapes-fill:before { content: "\f3da"; }
.ri-shapes-line:before { content: "\f3db"; }
.ri-square-fill:before { content: "\f3dc"; }
.ri-square-line:before { content: "\f3dd"; }
.ri-tent-fill:before { content: "\f3de"; }
.ri-tent-line:before { content: "\f3df"; }
.ri-threads-fill:before { content: "\f3e0"; }
.ri-threads-line:before { content: "\f3e1"; }
.ri-tree-fill:before { content: "\f3e2"; }
.ri-tree-line:before { content: "\f3e3"; }
.ri-triangle-fill:before { content: "\f3e4"; }
.ri-triangle-line:before { content: "\f3e5"; }
.ri-twitter-x-fill:before { content: "\f3e6"; }
.ri-twitter-x-line:before { content: "\f3e7"; }
.ri-verified-badge-fill:before { content: "\f3e8"; }
.ri-verified-badge-line:before { content: "\f3e9"; }
+27 -3
View File
@@ -424,9 +424,7 @@ export default class CommonHelper {
* @param {Number} [length] Results string length (default 10)
* @return {String}
*/
static randomString(length) {
length = length || 10;
static randomString(length = 10) {
let result = "";
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@@ -437,6 +435,32 @@ export default class CommonHelper {
return result;
}
/**
* Generates cryptographically random secret string
* (if crypto is supported, otherwise fallback to randomString).
*
* @param {Number} [length] Results string length (default 15)
* @return {String}
*/
static randomSecret(length = 15) {
if (typeof crypto === "undefined") {
return CommonHelper.randomString(length)
}
const arr = new Uint8Array(length);
crypto.getRandomValues(arr);
const alphabet = "-_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // 64 to devide "cleanly" 256
let result = "";
for (let i = 0; i < length; i++) {
result += alphabet.charAt(arr[i] % alphabet.length);
}
return result;
}
/**
* Converts and normalizes string into a sentence.
*