Add access controls window
This commit is contained in:
137
svelte/src/filesystem/edit_window/AccessControl.svelte
Normal file
137
svelte/src/filesystem/edit_window/AccessControl.svelte
Normal 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>
|
@@ -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)
|
||||
}
|
||||
|
@@ -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()
|
||||
|
@@ -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}
|
||||
|
@@ -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 {
|
||||
|
10
svelte/src/filesystem/edit_window/PermissionButton.svelte
Normal file
10
svelte/src/filesystem/edit_window/PermissionButton.svelte
Normal 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>
|
Reference in New Issue
Block a user