refac
This commit is contained in:
@@ -300,6 +300,58 @@ async def update_note_by_id(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
############################
|
||||||
|
# UpdateNoteAccessById
|
||||||
|
############################
|
||||||
|
|
||||||
|
|
||||||
|
class NoteAccessGrantsForm(BaseModel):
|
||||||
|
access_grants: list[dict]
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/{id}/access/update", response_model=Optional[NoteModel])
|
||||||
|
async def update_note_access_by_id(
|
||||||
|
request: Request,
|
||||||
|
id: str,
|
||||||
|
form_data: NoteAccessGrantsForm,
|
||||||
|
user=Depends(get_verified_user),
|
||||||
|
db: Session = Depends(get_session),
|
||||||
|
):
|
||||||
|
if user.role != "admin" and not has_permission(
|
||||||
|
user.id, "features.notes", request.app.state.config.USER_PERMISSIONS, db=db
|
||||||
|
):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
|
detail=ERROR_MESSAGES.UNAUTHORIZED,
|
||||||
|
)
|
||||||
|
|
||||||
|
note = Notes.get_note_by_id(id, db=db)
|
||||||
|
if not note:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND
|
||||||
|
)
|
||||||
|
|
||||||
|
if user.role != "admin" and (
|
||||||
|
user.id != note.user_id
|
||||||
|
and not AccessGrants.has_access(
|
||||||
|
user_id=user.id,
|
||||||
|
resource_type="note",
|
||||||
|
resource_id=note.id,
|
||||||
|
permission="write",
|
||||||
|
db=db,
|
||||||
|
)
|
||||||
|
):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()
|
||||||
|
)
|
||||||
|
|
||||||
|
AccessGrants.set_access_grants(
|
||||||
|
"note", id, form_data.access_grants, db=db
|
||||||
|
)
|
||||||
|
|
||||||
|
return Notes.get_note_by_id(id, db=db)
|
||||||
|
|
||||||
|
|
||||||
############################
|
############################
|
||||||
# DeleteNoteById
|
# DeleteNoteById
|
||||||
############################
|
############################
|
||||||
|
|||||||
@@ -253,6 +253,39 @@ export const updateNoteById = async (token: string, id: string, note: NoteItem)
|
|||||||
return res;
|
return res;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateNoteAccessGrants = async (
|
||||||
|
token: string,
|
||||||
|
id: string,
|
||||||
|
accessGrants: any[]
|
||||||
|
) => {
|
||||||
|
let error = null;
|
||||||
|
|
||||||
|
const res = await fetch(`${WEBUI_API_BASE_URL}/notes/${id}/access/update`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
authorization: `Bearer ${token}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ access_grants: accessGrants })
|
||||||
|
})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (!res.ok) throw await res.json();
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
error = err.detail;
|
||||||
|
console.error(err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
export const deleteNoteById = async (token: string, id: string) => {
|
export const deleteNoteById = async (token: string, id: string) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
// Assuming $i18n.languages is an array of language codes
|
// Assuming $i18n.languages is an array of language codes
|
||||||
$: loadLocale($i18n.languages);
|
$: loadLocale($i18n.languages);
|
||||||
|
|
||||||
import { deleteNoteById, getNoteById, updateNoteById } from '$lib/apis/notes';
|
import { deleteNoteById, getNoteById, updateNoteById, updateNoteAccessGrants } from '$lib/apis/notes';
|
||||||
|
|
||||||
import RichTextInput from '../common/RichTextInput.svelte';
|
import RichTextInput from '../common/RichTextInput.svelte';
|
||||||
import Spinner from '../common/Spinner.svelte';
|
import Spinner from '../common/Spinner.svelte';
|
||||||
@@ -71,6 +71,7 @@
|
|||||||
|
|
||||||
import Calendar from '../icons/Calendar.svelte';
|
import Calendar from '../icons/Calendar.svelte';
|
||||||
import Users from '../icons/Users.svelte';
|
import Users from '../icons/Users.svelte';
|
||||||
|
import LockClosed from '../icons/LockClosed.svelte';
|
||||||
|
|
||||||
import Image from '../common/Image.svelte';
|
import Image from '../common/Image.svelte';
|
||||||
import FileItem from '../common/FileItem.svelte';
|
import FileItem from '../common/FileItem.svelte';
|
||||||
@@ -865,8 +866,15 @@ Provide the enhanced notes in markdown format. Use markdown syntax for headings,
|
|||||||
bind:show={showAccessControlModal}
|
bind:show={showAccessControlModal}
|
||||||
bind:accessGrants={note.access_grants}
|
bind:accessGrants={note.access_grants}
|
||||||
accessRoles={['read', 'write']}
|
accessRoles={['read', 'write']}
|
||||||
onChange={() => {
|
onChange={async () => {
|
||||||
changeDebounceHandler();
|
if (id) {
|
||||||
|
try {
|
||||||
|
await updateNoteAccessGrants(localStorage.token, id, note.access_grants ?? []);
|
||||||
|
toast.success($i18n.t('Saved'));
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(`${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -898,7 +906,7 @@ Provide the enhanced notes in markdown format. Use markdown syntax for headings,
|
|||||||
{:else}
|
{:else}
|
||||||
<div class=" w-full flex flex-col {loading ? 'opacity-20' : ''}">
|
<div class=" w-full flex flex-col {loading ? 'opacity-20' : ''}">
|
||||||
<div class="shrink-0 w-full flex justify-between items-center px-3.5 mb-1.5">
|
<div class="shrink-0 w-full flex justify-between items-center px-3.5 mb-1.5">
|
||||||
<div class="w-full flex items-center">
|
<div class="w-full min-w-0 flex items-center">
|
||||||
{#if $mobile}
|
{#if $mobile}
|
||||||
<div
|
<div
|
||||||
class="{$showSidebar
|
class="{$showSidebar
|
||||||
@@ -974,7 +982,7 @@ Provide the enhanced notes in markdown format. Use markdown syntax for headings,
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="flex items-center gap-0.5 translate-x-1">
|
<div class="flex items-center gap-0.5 shrink-0 translate-x-1">
|
||||||
{#if note?.write_access}
|
{#if note?.write_access}
|
||||||
{#if editor}
|
{#if editor}
|
||||||
<div>
|
<div>
|
||||||
@@ -1077,6 +1085,23 @@ Provide the enhanced notes in markdown format. Use markdown syntax for headings,
|
|||||||
<EllipsisHorizontal className="size-5" />
|
<EllipsisHorizontal className="size-5" />
|
||||||
</div>
|
</div>
|
||||||
</NoteMenu>
|
</NoteMenu>
|
||||||
|
|
||||||
|
{#if note?.write_access}
|
||||||
|
<button
|
||||||
|
class="shrink-0 bg-gray-50 hover:bg-gray-100 text-black dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white transition px-2.5 py-1 rounded-full flex gap-1.5 items-center text-sm"
|
||||||
|
on:click={() => {
|
||||||
|
showAccessControlModal = true;
|
||||||
|
}}
|
||||||
|
disabled={note?.user_id !== $user?.id && $user?.role !== 'admin'}
|
||||||
|
>
|
||||||
|
<LockClosed strokeWidth="2.5" className="size-3.5" />
|
||||||
|
{$i18n.t('Access')}
|
||||||
|
</button>
|
||||||
|
{:else}
|
||||||
|
<div class="shrink-0 text-xs text-gray-500 px-2 py-1">
|
||||||
|
{$i18n.t('Read-Only Access')}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1118,26 +1143,6 @@ Provide the enhanced notes in markdown format. Use markdown syntax for headings,
|
|||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if note?.write_access}
|
|
||||||
<button
|
|
||||||
class=" flex items-center gap-1 w-fit py-1 px-1.5 rounded-lg min-w-fit"
|
|
||||||
on:click={() => {
|
|
||||||
showAccessControlModal = true;
|
|
||||||
}}
|
|
||||||
disabled={note?.user_id !== $user?.id && $user?.role !== 'admin'}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
{hasPublicReadGrant(note?.access_grants)
|
|
||||||
? $i18n.t('Everyone')
|
|
||||||
: $i18n.t('Private')}
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
{:else}
|
|
||||||
<div>
|
|
||||||
{$i18n.t('Read-Only Access')}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if editor}
|
{#if editor}
|
||||||
<div class="flex items-center gap-1 px-1 min-w-fit">
|
<div class="flex items-center gap-1 px-1 min-w-fit">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user