|
|
|
|
@@ -1,7 +1,9 @@
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import Button from "layout/Button.svelte";
|
|
|
|
|
import ToggleButton from "layout/ToggleButton.svelte";
|
|
|
|
|
import type { FSPermissions, NodeOptions } from "lib/FilesystemAPI.svelte";
|
|
|
|
|
import PermissionButton from "./PermissionButton.svelte";
|
|
|
|
|
import { formatDate } from "util/Formatting";
|
|
|
|
|
|
|
|
|
|
let {
|
|
|
|
|
options = $bindable()
|
|
|
|
|
@@ -16,7 +18,7 @@ const add_user = (e: SubmitEvent) => {
|
|
|
|
|
if (options.user_permissions === undefined) {
|
|
|
|
|
options.user_permissions = {} as {[index: string]: FSPermissions}
|
|
|
|
|
}
|
|
|
|
|
options.user_permissions[new_user_id] = structuredClone(new_user_perms)
|
|
|
|
|
options.user_permissions[new_user_id] = $state.snapshot(new_user_perms)
|
|
|
|
|
}
|
|
|
|
|
const del_user = (id: string) => {
|
|
|
|
|
delete options.user_permissions[id]
|
|
|
|
|
@@ -24,14 +26,26 @@ const del_user = (id: string) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let new_password = $state("")
|
|
|
|
|
let new_password_label = $state("")
|
|
|
|
|
let new_password_perms = $state(<FSPermissions>{read: true})
|
|
|
|
|
const add_password = (e: SubmitEvent) => {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
if (options.password_permissions === undefined) {
|
|
|
|
|
options.password_permissions = {} as {[index: string]: FSPermissions}
|
|
|
|
|
}
|
|
|
|
|
options.password_permissions[new_password] = structuredClone(new_password_perms)
|
|
|
|
|
options.password_permissions[new_password] = {
|
|
|
|
|
...$state.snapshot(new_password_perms),
|
|
|
|
|
label: new_password_label,
|
|
|
|
|
}
|
|
|
|
|
new_password = ""
|
|
|
|
|
new_password_label = ""
|
|
|
|
|
}
|
|
|
|
|
const generate_password = () => {
|
|
|
|
|
// 32 hexadecimal characters, which any S3 client accepts as secret key
|
|
|
|
|
new_password = crypto.randomUUID().replaceAll("-", "")
|
|
|
|
|
}
|
|
|
|
|
// Passwords stay hidden until their reveal button is pressed
|
|
|
|
|
let revealed: {[password: string]: boolean} = $state({})
|
|
|
|
|
const del_password = (pass: string) => {
|
|
|
|
|
delete options.password_permissions[pass]
|
|
|
|
|
options.password_permissions = options.password_permissions
|
|
|
|
|
@@ -69,11 +83,14 @@ const del_password = (pass: string) => {
|
|
|
|
|
</p>
|
|
|
|
|
<form onsubmit={add_user} class="row">
|
|
|
|
|
<input type="text" bind:value={new_user_id} placeholder="Username" class="grow" size="1">
|
|
|
|
|
<Button type="submit" icon="add" label="Add"/>
|
|
|
|
|
<div class="perms">
|
|
|
|
|
<PermissionButton bind:permissions={new_user_perms}/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="perms">
|
|
|
|
|
<Button type="submit" icon="add" label="Add"/>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<hr/>
|
|
|
|
|
{#if options.user_permissions !== undefined}
|
|
|
|
|
{#each Object.keys(options.user_permissions) as id (id)}
|
|
|
|
|
<div class="row">
|
|
|
|
|
@@ -81,6 +98,13 @@ const del_password = (pass: string) => {
|
|
|
|
|
<div class="grow id">
|
|
|
|
|
{id}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="id">
|
|
|
|
|
{#if options.user_permissions[id].last_used}
|
|
|
|
|
Used {formatDate(options.user_permissions[id].last_used, true, true, false)}
|
|
|
|
|
{:else}
|
|
|
|
|
Never used
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="perms">
|
|
|
|
|
<PermissionButton bind:permissions={options.user_permissions[id]}/>
|
|
|
|
|
</div>
|
|
|
|
|
@@ -93,23 +117,35 @@ const del_password = (pass: string) => {
|
|
|
|
|
<legend>Password permissions</legend>
|
|
|
|
|
<p>
|
|
|
|
|
Allow users to enter a password to give them access to this directory.
|
|
|
|
|
</p>
|
|
|
|
|
<p>
|
|
|
|
|
<b>This feature is not implemented currently!</b>
|
|
|
|
|
Passwords can be used as S3 secret keys, see S3 access below.
|
|
|
|
|
</p>
|
|
|
|
|
<form onsubmit={add_password} class="row">
|
|
|
|
|
<input type="text" bind:value={new_password} placeholder="Password" class="grow" size="1">
|
|
|
|
|
<Button type="submit" icon="add" label="Add"/>
|
|
|
|
|
<input type="text" bind:value={new_password_label} placeholder="Label" class="grow" maxlength="100" size="1">
|
|
|
|
|
<input type="text" bind:value={new_password} placeholder="Password" class="grow" size="1" minlength="8" maxlength="50">
|
|
|
|
|
<Button type="button" click={generate_password} icon="key" label="Generate"/>
|
|
|
|
|
<div class="perms">
|
|
|
|
|
<PermissionButton bind:permissions={new_password_perms}/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="perms">
|
|
|
|
|
<Button type="submit" icon="add" label="Add"/>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
<hr/>
|
|
|
|
|
{#if options.password_permissions !== undefined}
|
|
|
|
|
{#each Object.keys(options.password_permissions) as password (password)}
|
|
|
|
|
<div class="row">
|
|
|
|
|
<Button click={() => del_password(password)} icon="delete"/>
|
|
|
|
|
<input type="text" bind:value={options.password_permissions[password].label} placeholder="Label" class="grow" maxlength="100" size="1">
|
|
|
|
|
<ToggleButton bind:on={revealed[password]} icon_on="visibility" icon_off="visibility_off"/>
|
|
|
|
|
<div class="grow id">
|
|
|
|
|
{password}
|
|
|
|
|
{revealed[password] ? password : "••••••••••••••••"}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="id">
|
|
|
|
|
{#if options.password_permissions[password].last_used}
|
|
|
|
|
Used {formatDate(options.password_permissions[password].last_used, true, true, false)}
|
|
|
|
|
{:else}
|
|
|
|
|
Never used
|
|
|
|
|
{/if}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="perms">
|
|
|
|
|
<PermissionButton bind:permissions={options.password_permissions[password]}/>
|
|
|
|
|
|