Add access controls window

This commit is contained in:
2024-11-19 15:31:51 +01:00
parent 27882303d9
commit f7a0ff4538
41 changed files with 307 additions and 63 deletions

View File

@@ -0,0 +1,137 @@
<script lang="ts">
import Button from "../../layout/Button.svelte";
import type { FSNode, FSPermissions } from "../FilesystemAPI.mjs";
import PermissionButton from "./PermissionButton.svelte";
export let file: FSNode
let new_user_id = ""
let new_user_perms = <FSPermissions>{read: true}
const add_user = (e: SubmitEvent) => {
e.preventDefault()
if (file.user_permissions === undefined) {
file.user_permissions = <[string: FSPermissions]>{}
}
file.user_permissions[new_user_id] = structuredClone(new_user_perms)
}
const del_user = (id: string) => {
delete file.user_permissions[id]
file.user_permissions = file.user_permissions
}
let new_password = ""
let new_password_perms = <FSPermissions>{read: true}
const add_password = (e: SubmitEvent) => {
e.preventDefault()
if (file.password_permissions === undefined) {
file.password_permissions = <[string: FSPermissions]>{}
}
file.password_permissions[new_password] = structuredClone(new_password_perms)
}
const del_password = (pass: string) => {
delete file.password_permissions[pass]
file.password_permissions = file.password_permissions
}
</script>
<p>
Access controls are only available for users with an account currently. Even
if you set 'Anyone with the link' to write, they will need to be logged in
to write to the directory.
</p>
<p>
Users can always delete files they uploaded themselves, even if they don't
have delete permissions. You can see who the owner of a file is in the
Details window.
</p>
<h2>Link permissions</h2>
<div class="row">
<div class="grow id">
Anyone with the link can...
</div>
<div class="perms">
<PermissionButton bind:permissions={file.link_permissions}/>
</div>
</div>
<h2>User permissions</h2>
<p>
Enter a username here to give them access to this directory. The user will
not receive an e-mail invite. Giving write access to a user without giving
read access as well does not actually allow them to write anything.
</p>
<form on:submit={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>
</form>
{#if file.user_permissions !== undefined}
{#each Object.keys(file.user_permissions) as id (id)}
<div class="row">
<Button click={() => del_user(id)} icon="delete"/>
<div class="grow id">
{id}
</div>
<div class="perms">
<PermissionButton bind:permissions={file.user_permissions[id]}/>
</div>
</div>
{/each}
{/if}
<h2>Password permissions</h2>
<p>
Allow users to enter a password to give them access to this directory.
</p>
<p>
<b>This feature is not implemented currently!</b>
</p>
<form on:submit={add_password} class="row">
<input type="text" bind:value={new_password} placeholder="Password" class="grow" size="1">
<Button type="submit" icon="add" label="Add"/>
<div class="perms">
<PermissionButton bind:permissions={new_password_perms}/>
</div>
</form>
{#if file.password_permissions !== undefined}
{#each Object.keys(file.password_permissions) as password (password)}
<div class="row">
<Button click={() => del_password(password)} icon="delete"/>
<div class="grow id">
{password}
</div>
<div class="perms">
<PermissionButton bind:permissions={file.password_permissions[password]}/>
</div>
</div>
{/each}
{/if}
<style>
.row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
border-bottom: 1px solid var(--separator);
margin-bottom: 2px;
padding-bottom: 2px;
}
.row > .grow {
min-width: 150px;
flex: 1 1 content;
}
.row > * {
flex: 0 0 content;
}
.id {
margin-left: 0.5em;
display: flex;
align-items: center;
}
.perms {
text-align: right;
margin-left: 0.5em;
}
</style>

View File

@@ -68,7 +68,7 @@ const add_styles = (style, properties) => {
style.body_color = properties.brand_body_color
style.body_background = properties.brand_body_color
style.body_text_color = add_contrast(properties.brand_body_color, 75)
style.shaded_background = set_alpha(properties.brand_body_color, 0.8)
style.shaded_background = set_alpha(properties.brand_body_color, 0.75)
style.separator = add_contrast(properties.brand_body_color, 8)
style.shadow_color = darken(properties.brand_body_color, 0.8)
}

View File

@@ -1,7 +1,7 @@
<script>
import { createEventDispatcher } from "svelte";
import FilePicker from "../filemanager/FilePicker.svelte";
import { fs_update, fs_node_type } from "../FilesystemAPI";
import { fs_update, fs_node_type } from "../FilesystemAPI.mjs";
import CustomBanner from "../viewers/CustomBanner.svelte";
import HelpButton from "../../layout/HelpButton.svelte";
let dispatch = createEventDispatcher()

View File

@@ -1,10 +1,11 @@
<script>
import { fs_rename, fs_update } from "../FilesystemAPI";
import { fs_rename, fs_update } from "../FilesystemAPI.mjs";
import Modal from "../../util/Modal.svelte";
import BrandingOptions from "./BrandingOptions.svelte";
import { branding_from_node } from "./Branding";
import FileOptions from "./FileOptions.svelte";
import SharingOptions from "./SharingOptions.svelte";
import AccessControl from "./AccessControl.svelte";
export let nav
let file = {
@@ -40,6 +41,11 @@ export const edit = (f, oae = false, open_tab = "") => {
file.properties = {}
}
if (shared && file.link_permissions === undefined) {
// Default to read-only for public links
file.link_permissions = {read: true, write: false, delete: false}
}
branding_enabled = file.properties.branding_enabled === "true"
if (branding_enabled) {
custom_css = branding_from_node(file)
@@ -76,7 +82,9 @@ const save = async (keep_editing = false) => {
let new_file
try {
nav.set_loading(true)
let opts = {shared: shared}
let opts = {
shared: shared,
}
opts.branding_enabled = branding_enabled ? "true" : ""
@@ -89,6 +97,16 @@ const save = async (keep_editing = false) => {
}
}
if (shared && file.link_permissions !== undefined) {
opts.link_permissions = file.link_permissions
}
if (shared && file.user_permissions !== undefined) {
opts.user_permissions = file.user_permissions
}
if (shared && file.password_permissions !== undefined) {
opts.password_permissions = file.password_permissions
}
new_file = await fs_update(file.path, opts)
if (new_name !== file.name) {
@@ -135,6 +153,12 @@ const save = async (keep_editing = false) => {
<i class="icon">share</i>
Sharing
</button>
{#if shared && $nav.permissions.owner}
<button class:button_highlight={tab === "access"} on:click={() => tab = "access"}>
<i class="icon">key</i>
Access control
</button>
{/if}
<button class:button_highlight={tab === "branding"} on:click={() => tab = "branding"}>
<i class="icon">palette</i>
Branding
@@ -153,11 +177,9 @@ const save = async (keep_editing = false) => {
bind:open_after_edit
/>
{:else if tab === "share"}
<SharingOptions
bind:file
bind:shared
on:save={() => save(true)}
/>
<SharingOptions bind:file bind:shared on:save={() => save(true)} />
{:else if tab === "access"}
<AccessControl bind:file bind:shared />
{:else if tab === "branding"}
<BrandingOptions
bind:enabled={branding_enabled}

View File

@@ -1,6 +1,6 @@
<script>
import Button from "../../layout/Button.svelte";
import { fs_delete_all } from "../FilesystemAPI";
import { fs_delete_all } from "../FilesystemAPI.mjs";
import PathLink from "../util/PathLink.svelte";
export let nav
@@ -47,12 +47,14 @@ const delete_file = async e => {
<label for="file_name">Name</label>
<input form="edit_form" bind:value={new_name} id="file_name" type="text" class="form_input" disabled={is_root_dir}/>
</div>
<h2>Delete</h2>
<p>
Delete this file or directory. If this is a directory then all
subfiles will be deleted as well. This action cannot be undone.
</p>
<Button click={delete_file} red icon="delete" label="Delete" style="align-self: flex-start;"/>
{#if $nav.permissions.delete === true}
<h2>Delete</h2>
<p>
Delete this file or directory. If this is a directory then all
subfiles will be deleted as well. This action cannot be undone.
</p>
<Button click={delete_file} red icon="delete" label="Delete" style="align-self: flex-start;"/>
{/if}
<style>
.form_grid {

View File

@@ -0,0 +1,10 @@
<script lang="ts">
import ToggleButton from "../../layout/ToggleButton.svelte";
import type { FSPermissions } from "../FilesystemAPI.mjs";
export let permissions = <FSPermissions>{}
</script>
<ToggleButton group_first bind:on={permissions.read}>Read</ToggleButton>
<ToggleButton group_middle bind:on={permissions.write}>Write</ToggleButton>
<ToggleButton group_last bind:on={permissions.delete}>Delete</ToggleButton>