This commit is contained in:
Timothy Jaeryang Baek committed 2026-07-26 18:06:03 -04:00
1 parent e3cce68ef2
commit 1f0dc90abe
11 files changed
+287 -82

No files matched your search

@@ -494,6 +494,25 @@
</div>
{/if}
</div>
<div class="flex flex-col w-full">
<div class="flex w-full justify-between my-1">
<div class=" self-center text-xs font-normal">
{$i18n.t('Chats Open Sharing')}
</div>
<Switch
bind:state={permissions.sharing.open_chats}
ariaLabel={$i18n.t('Chats Open Sharing')}
/>
</div>
{#if defaultPermissions?.sharing?.open_chats && !permissions.sharing.open_chats}
<div>
<div class="text-xs text-gray-500">
{$i18n.t('This is a default user permission and will remain enabled.')}
</div>
</div>
{/if}
</div>
{/if}
{#if permissions.features.calendar}
@@ -158,6 +158,7 @@
bind:accessGrants
accessRoles={['read']}
sharePublic={$user?.permissions?.sharing?.public_chats || $user?.role === 'admin'}
shareOpen={$user?.permissions?.sharing?.open_chats || $user?.role === 'admin'}
shareUsers={($user?.permissions?.access_grants?.allow_users ?? true) ||
$user?.role === 'admin'}
onChange={saveAccessGrants}
@@ -16,7 +16,7 @@
type AccessGrant = {
id?: string;
principal_type: 'user' | 'group';
principal_type: 'user' | 'group' | 'anyone';
principal_id: string;
permission: 'read' | 'write';
};
@@ -34,6 +34,7 @@
export let share = true;
export let sharePublic = true;
export let shareOpen = false;
export let shareUsers = true;
export let allowGroups = true;
export let defaultPermission: 'read' | 'write' = 'read';
@@ -162,6 +163,14 @@
grant.principal_type === 'user' && grant.principal_id === '*' && grant.permission === 'read'
);
const hasAnyoneReadGrant = (grants: AccessGrant[]): boolean =>
grants.some(
(grant) =>
grant.principal_type === 'anyone' &&
grant.principal_id === '*' &&
grant.permission === 'read'
);
const hasPublicWriteGrant = (grants: AccessGrant[]): boolean =>
grants.some(
(grant) =>
@@ -170,16 +179,17 @@
grant.permission === 'write'
);
const currentGrants = (): AccessGrant[] =>
Array.isArray(accessGrants) ? (accessGrants as AccessGrant[]) : [];
const currentGrants = (grants: AccessGrant[] | any = accessGrants): AccessGrant[] =>
Array.isArray(grants) ? (grants as AccessGrant[]) : [];
const getPrincipalIdsByPermission = (
principalType: 'user' | 'group',
permission: 'read' | 'write'
permission: 'read' | 'write',
grants: AccessGrant[] | any = accessGrants
): string[] =>
Array.from(
new Set(
currentGrants()
currentGrants(grants)
.filter(
(grant) => grant.principal_type === principalType && grant.permission === permission
)
@@ -188,7 +198,7 @@
);
const hasPrincipalGrant = (
principalType: 'user' | 'group',
principalType: 'user' | 'group' | 'anyone',
principalId: string,
permission: 'read' | 'write'
): boolean =>
@@ -204,17 +214,32 @@
onChange(accessGrants);
};
const setPublic = (isPublic: boolean) => {
// Remove all user:* grants
const getVisibility = (grants: AccessGrant[]): 'private' | 'public' | 'open' => {
if (hasAnyoneReadGrant(grants)) return 'open';
if (hasPublicReadGrant(grants)) return 'public';
return 'private';
};
const setVisibility = (visibility: 'private' | 'public' | 'open') => {
const filtered = currentGrants().filter(
(grant) => !(grant.principal_type === 'user' && grant.principal_id === '*')
(grant) =>
!(
(grant.principal_type === 'user' || grant.principal_type === 'anyone') &&
grant.principal_id === '*'
)
);
if (isPublic) {
if (visibility === 'public') {
filtered.push({
principal_type: 'user',
principal_id: '*',
permission: 'read'
});
} else if (visibility === 'open') {
filtered.push({
principal_type: 'anyone',
principal_id: '*',
permission: 'read'
});
}
commitAccessGrants(filtered);
};
@@ -237,7 +262,7 @@
};
const upsertPrincipalGrant = (
principalType: 'user' | 'group',
principalType: 'user' | 'group' | 'anyone',
principalId: string,
permission: 'read' | 'write',
grants: AccessGrant[]
@@ -263,7 +288,7 @@
};
const removePrincipalGrant = (
principalType: 'user' | 'group',
principalType: 'user' | 'group' | 'anyone',
principalId: string,
permission: 'read' | 'write',
grants: AccessGrant[]
@@ -277,14 +302,14 @@
)
);
const removePrincipal = (principalType: 'user' | 'group', principalId: string) => {
const removePrincipal = (principalType: 'user' | 'group' | 'anyone', principalId: string) => {
let next = [...currentGrants()];
next = removePrincipalGrant(principalType, principalId, 'read', next);
next = removePrincipalGrant(principalType, principalId, 'write', next);
commitAccessGrants(next);
};
const togglePrincipalWrite = (principalType: 'user' | 'group', principalId: string) => {
const togglePrincipalWrite = (principalType: 'user' | 'group' | 'anyone', principalId: string) => {
let next = [...currentGrants()];
const hasWrite = hasPrincipalGrant(principalType, principalId, 'write');
if (hasWrite) {
@@ -379,12 +404,14 @@
$: if (readGroupIds.length > 0 || writeGroupIds.length > 0) {
void ensureGroupsByIds([...readGroupIds, ...writeGroupIds]);
}
$: readGroupIds = (accessGrants, getPrincipalIdsByPermission('group', 'read'));
$: writeGroupIds = (accessGrants, getPrincipalIdsByPermission('group', 'write'));
$: readUserIds =
(accessGrants, getPrincipalIdsByPermission('user', 'read').filter((id) => id !== '*'));
$: writeUserIds =
(accessGrants, getPrincipalIdsByPermission('user', 'write').filter((id) => id !== '*'));
$: readGroupIds = getPrincipalIdsByPermission('group', 'read', accessGrants);
$: writeGroupIds = getPrincipalIdsByPermission('group', 'write', accessGrants);
$: readUserIds = getPrincipalIdsByPermission('user', 'read', accessGrants).filter(
(id) => id !== '*'
);
$: writeUserIds = getPrincipalIdsByPermission('user', 'write', accessGrants).filter(
(id) => id !== '*'
);
$: selectedUserIds = Array.from(new Set([...readUserIds, ...writeUserIds]));
@@ -450,7 +477,7 @@
<div class="flex gap-2 items-center">
<div>
<div class="p-2 bg-black/5 dark:bg-white/5 rounded-full">
{#if !hasPublicReadGrant(accessGrants ?? [])}
{#if getVisibility(accessGrants ?? []) === 'private'}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
@@ -486,36 +513,41 @@
<div>
<Tooltip
content={!(share && sharePublic) && !hasPublicReadGrant(accessGrants ?? [])
content={!(share && sharePublic) && getVisibility(accessGrants ?? []) === 'private'
? $i18n.t('You do not have permission to make this public')
: ''}
>
<select
id="models"
class="outline-none bg-transparent text-sm font-normal block w-fit pr-8 max-w-full placeholder-gray-400"
value={!hasPublicReadGrant(accessGrants ?? []) ? 'private' : 'public'}
value={getVisibility(accessGrants ?? [])}
on:change={(e) => {
setPublic((e.target as HTMLSelectElement).value === 'public');
setVisibility((e.target as HTMLSelectElement).value as 'private' | 'public' | 'open');
}}
>
<option class=" text-gray-700" value="private">{$i18n.t('Private')}</option>
{#if (share && sharePublic) || hasPublicReadGrant(accessGrants ?? [])}
<option class=" text-gray-700" value="public">{$i18n.t('Public')}</option>
{/if}
{#if (share && shareOpen) || hasAnyoneReadGrant(accessGrants ?? [])}
<option class=" text-gray-700" value="open">{$i18n.t('Open')}</option>
{/if}
</select>
</Tooltip>
<div class=" text-xs text-gray-400 font-normal">
{#if !hasPublicReadGrant(accessGrants ?? [])}
{#if getVisibility(accessGrants ?? []) === 'private'}
{$i18n.t('Only select users and groups with permission can access')}
{:else}
{:else if getVisibility(accessGrants ?? []) === 'public'}
{$i18n.t('Accessible to all users')}
{:else}
{$i18n.t('Anyone with the link can view')}
{/if}
</div>
</div>
</div>
{#if hasPublicReadGrant(accessGrants ?? []) && accessRoles.includes('write')}
{#if hasPublicReadGrant(accessGrants ?? []) && !hasAnyoneReadGrant(accessGrants ?? []) && accessRoles.includes('write')}
<div class="flex w-full justify-between mt-1.5 ml-0.5">
<div class="self-center text-xs">
{$i18n.t('Allow public write access')}
@@ -660,7 +692,7 @@
{/each}
{/if}
{#if !hasPublicReadGrant(accessGrants ?? []) && accessGroups.length === 0 && selectedUsers.length === 0}
{#if getVisibility(accessGrants ?? []) === 'private' && accessGroups.length === 0 && selectedUsers.length === 0}
<div class="text-xs text-gray-500 text-center py-3">
{$i18n.t('No access grants. Private to you.')}
</div>
@@ -8,7 +8,7 @@
type AccessGrant = {
id?: string;
principal_type: 'user' | 'group';
principal_type: 'user' | 'group' | 'anyone';
principal_id: string;
permission: 'read' | 'write';
};
@@ -20,6 +20,7 @@
export let share = true;
export let sharePublic = true;
export let shareOpen = false;
export let shareUsers = true;
export let onChange = () => {};
@@ -49,6 +50,7 @@
{accessRoles}
{share}
{sharePublic}
{shareOpen}
{shareUsers}
/>
</div>
+1
View File
@@ -29,6 +29,7 @@ export const DEFAULT_PERMISSIONS = {
public_notes: false,
folders: false,
public_chats: false,
open_chats: false,
public_calendars: false
},
access_grants: {
@@ -223,6 +223,7 @@
"and create a new shared link.": "",
"Android": "",
"Anyone": "",
"Anyone with the link can view": "",
"API Auth String": "",
"API Base URL": "",
"API Key": "",
@@ -432,6 +433,7 @@
"Chat unshared successfully.": "",
"chats": "",
"Chats": "",
"Chats Open Sharing": "",
"Chats Public Sharing": "",
"Check Again": "",
"Check for updates": "",
@@ -1908,6 +1910,7 @@
"Open Modal To Manage Floating Quick Actions": "",
"Open Modal To Manage Image Compression": "",
"Open Model Selector": "",
"Open": "",
"Open note": "",
"Open Settings": "",
"Open Sidebar": "",