mirror of
https://git.srhtnin.garden/sarah/SaraView.git
synced 2026-10-15 02:43:17 +02:00
Fix video embed streaming, permission inheritance in create dialogs, and default to Guest browsing
This commit is contained in:
1 parent
24a6d83ea0
commit
16787aba14
7 files changed
+94
-20
No files matched your search
@@ -71,6 +71,19 @@ def RemoveLock(RootName: str, RelativePath: str) -> None:
|
||||
SaveLocks(Locks)
|
||||
|
||||
|
||||
def GetInheritedLock(RootName: str, DirectoryRelativePath: str) -> dict[str, Any] | None:
|
||||
CurrentPath = DirectoryRelativePath
|
||||
|
||||
while CurrentPath:
|
||||
Lock = GetLockForPath(RootName, CurrentPath)
|
||||
if Lock is not None:
|
||||
return Lock
|
||||
|
||||
CurrentPath = CurrentPath.rsplit("/", 1)[0] if "/" in CurrentPath else ""
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def IsPathAccessible(
|
||||
RootName: str, RelativePath: str, Username: str, UserGroups: list[str]
|
||||
) -> bool:
|
||||
|
||||
@@ -52,6 +52,7 @@ from Groups import (
|
||||
SetGroupMembers,
|
||||
)
|
||||
from Locks import (
|
||||
GetInheritedLock,
|
||||
GetLockForPath,
|
||||
IsPathAccessible,
|
||||
LoadLocks,
|
||||
@@ -332,6 +333,12 @@ def GetLockEndpoint(Root: str, Path: str, CurrentUser: dict = Depends(GetCurrent
|
||||
return GetLockForPath(Root, Path) or {}
|
||||
|
||||
|
||||
@Application.get("/api/lock/inherited")
|
||||
def GetInheritedLockEndpoint(Root: str, Path: str, CurrentUser: dict = Depends(GetCurrentUser)) -> dict:
|
||||
RequirePathAccessible(Root, Path, CurrentUser)
|
||||
return GetInheritedLock(Root, Path) or {}
|
||||
|
||||
|
||||
class SetLockRequest(BaseModel):
|
||||
Users: list[str] = []
|
||||
Groups: list[str] = []
|
||||
|
||||
+7
-1
@@ -55,7 +55,13 @@ def StreamBinaryFile(FilePath: Path, RangeHeader: str | None) -> StreamingRespon
|
||||
def IterateChunk():
|
||||
with FilePath.open("rb") as SourceFile:
|
||||
SourceFile.seek(Start)
|
||||
yield SourceFile.read(ChunkLength)
|
||||
Remaining = ChunkLength
|
||||
while Remaining > 0:
|
||||
Chunk = SourceFile.read(min(1024 * 1024, Remaining))
|
||||
if not Chunk:
|
||||
break
|
||||
Remaining -= len(Chunk)
|
||||
yield Chunk
|
||||
|
||||
Headers = {
|
||||
"Content-Range": f"bytes {Start}-{End}/{FileSize}",
|
||||
|
||||
@@ -117,6 +117,11 @@ export function FetchLock(RootName, RelativePath) {
|
||||
return FetchJson(`/lock?${Params}`);
|
||||
}
|
||||
|
||||
export function FetchInheritedLock(RootName, RelativePath) {
|
||||
const Params = new URLSearchParams({ Root: RootName, Path: RelativePath });
|
||||
return FetchJson(`/lock/inherited?${Params}`);
|
||||
}
|
||||
|
||||
export function SetLock(RootName, RelativePath, Users, Groups) {
|
||||
const Params = new URLSearchParams({ Root: RootName, Path: RelativePath });
|
||||
return FetchJson(`/lock?${Params}`, { method: "PUT", ...JsonBody({ Users, Groups }) });
|
||||
|
||||
@@ -84,7 +84,10 @@ export default function App() {
|
||||
SetCurrentUser(User);
|
||||
SetAuthState("LoggedIn");
|
||||
})
|
||||
.catch(() => SetAuthState("LoggedOut"));
|
||||
.catch(() => {
|
||||
SetCurrentUser(GuestUser);
|
||||
SetAuthState("Guest");
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
CreateEntry,
|
||||
DeleteEntry,
|
||||
FetchInheritedLock,
|
||||
FetchLock,
|
||||
FetchTree,
|
||||
GetDownloadUrl,
|
||||
@@ -59,12 +60,28 @@ export default function DirectoryPane({
|
||||
return DirectoryPath ? `${DirectoryPath}/${Name}` : Name;
|
||||
}
|
||||
|
||||
function OpenCreateFileModal() {
|
||||
SetModalConfig({ Mode: "createFile" });
|
||||
async function OpenCreateFileModal() {
|
||||
const Inherited = await FetchInheritedLock(RootName, DirectoryPath).catch(() => ({}));
|
||||
SetModalConfig({
|
||||
Mode: "createFile",
|
||||
InheritedUsers: Inherited.Users || [],
|
||||
InheritedGroups: Inherited.Groups || [],
|
||||
});
|
||||
}
|
||||
|
||||
function OpenCreateDirectoryModal() {
|
||||
SetModalConfig({ Mode: "createDirectory" });
|
||||
async function OpenCreateDirectoryModal() {
|
||||
const Inherited = await FetchInheritedLock(RootName, DirectoryPath).catch(() => ({}));
|
||||
SetModalConfig({
|
||||
Mode: "createDirectory",
|
||||
InheritedUsers: Inherited.Users || [],
|
||||
InheritedGroups: Inherited.Groups || [],
|
||||
});
|
||||
}
|
||||
|
||||
function SetsEqual(FirstList, SecondList) {
|
||||
if (FirstList.length !== SecondList.length) return false;
|
||||
const FirstSet = new Set(FirstList);
|
||||
return SecondList.every((Item) => FirstSet.has(Item));
|
||||
}
|
||||
|
||||
async function HandleRequestLockEdit(Event, Entry) {
|
||||
@@ -143,7 +160,10 @@ export default function DirectoryPane({
|
||||
const FullPath = JoinPath(Name.trim());
|
||||
await CreateEntry(RootName, FullPath, IsDirectory);
|
||||
|
||||
if (Users.length > 0 || Groups.length > 0) {
|
||||
const MatchesInherited =
|
||||
SetsEqual(Users, ModalConfig.InheritedUsers) && SetsEqual(Groups, ModalConfig.InheritedGroups);
|
||||
|
||||
if (!MatchesInherited && (Users.length > 0 || Groups.length > 0)) {
|
||||
await SetLockApi(RootName, FullPath, Users, Groups);
|
||||
}
|
||||
|
||||
@@ -306,8 +326,8 @@ export default function DirectoryPane({
|
||||
Title={`New file in ${DirectoryPath || "root"}`}
|
||||
ShowNameField
|
||||
NamePlaceholder="Notes.md"
|
||||
InitialUsers={[]}
|
||||
InitialGroups={[]}
|
||||
InitialUsers={ModalConfig.InheritedUsers}
|
||||
InitialGroups={ModalConfig.InheritedGroups}
|
||||
ConfirmLabel="Create"
|
||||
OnConfirm={HandleModalConfirm}
|
||||
OnCancel={() => SetModalConfig(null)}
|
||||
@@ -318,8 +338,8 @@ export default function DirectoryPane({
|
||||
Title={`New directory in ${DirectoryPath || "root"}`}
|
||||
ShowNameField
|
||||
NamePlaceholder="MyFolder"
|
||||
InitialUsers={[]}
|
||||
InitialGroups={[]}
|
||||
InitialUsers={ModalConfig.InheritedUsers}
|
||||
InitialGroups={ModalConfig.InheritedGroups}
|
||||
ConfirmLabel="Create"
|
||||
OnConfirm={HandleModalConfirm}
|
||||
OnCancel={() => SetModalConfig(null)}
|
||||
|
||||
@@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
CreateEntry,
|
||||
DeleteEntry,
|
||||
FetchInheritedLock,
|
||||
FetchLock,
|
||||
FetchTree,
|
||||
GetAvatarUrl,
|
||||
@@ -314,12 +315,28 @@ export default function Sidebar({
|
||||
return CurrentDirectoryPath ? `${CurrentDirectoryPath}/${Name}` : Name;
|
||||
}
|
||||
|
||||
function OpenCreateFileModal() {
|
||||
SetModalConfig({ Mode: "createFile" });
|
||||
async function OpenCreateFileModal() {
|
||||
const Inherited = await FetchInheritedLock(RootName, CurrentDirectoryPath).catch(() => ({}));
|
||||
SetModalConfig({
|
||||
Mode: "createFile",
|
||||
InheritedUsers: Inherited.Users || [],
|
||||
InheritedGroups: Inherited.Groups || [],
|
||||
});
|
||||
}
|
||||
|
||||
function OpenCreateDirectoryModal() {
|
||||
SetModalConfig({ Mode: "createDirectory" });
|
||||
async function OpenCreateDirectoryModal() {
|
||||
const Inherited = await FetchInheritedLock(RootName, CurrentDirectoryPath).catch(() => ({}));
|
||||
SetModalConfig({
|
||||
Mode: "createDirectory",
|
||||
InheritedUsers: Inherited.Users || [],
|
||||
InheritedGroups: Inherited.Groups || [],
|
||||
});
|
||||
}
|
||||
|
||||
function SetsEqual(FirstList, SecondList) {
|
||||
if (FirstList.length !== SecondList.length) return false;
|
||||
const FirstSet = new Set(FirstList);
|
||||
return SecondList.every((Item) => FirstSet.has(Item));
|
||||
}
|
||||
|
||||
async function HandleRequestLockEdit(FullPath, EntryName) {
|
||||
@@ -346,7 +363,10 @@ export default function Sidebar({
|
||||
const FullPath = JoinPath(Name.trim());
|
||||
await CreateEntry(RootName, FullPath, IsDirectory);
|
||||
|
||||
if (Users.length > 0 || Groups.length > 0) {
|
||||
const MatchesInherited =
|
||||
SetsEqual(Users, ModalConfig.InheritedUsers) && SetsEqual(Groups, ModalConfig.InheritedGroups);
|
||||
|
||||
if (!MatchesInherited && (Users.length > 0 || Groups.length > 0)) {
|
||||
await SetLockApi(RootName, FullPath, Users, Groups);
|
||||
}
|
||||
|
||||
@@ -496,8 +516,8 @@ export default function Sidebar({
|
||||
Title={`New file in ${CurrentDirectoryPath || "root"}`}
|
||||
ShowNameField
|
||||
NamePlaceholder="Notes.md"
|
||||
InitialUsers={[]}
|
||||
InitialGroups={[]}
|
||||
InitialUsers={ModalConfig.InheritedUsers}
|
||||
InitialGroups={ModalConfig.InheritedGroups}
|
||||
ConfirmLabel="Create"
|
||||
OnConfirm={HandleModalConfirm}
|
||||
OnCancel={() => SetModalConfig(null)}
|
||||
@@ -508,8 +528,8 @@ export default function Sidebar({
|
||||
Title={`New directory in ${CurrentDirectoryPath || "root"}`}
|
||||
ShowNameField
|
||||
NamePlaceholder="MyFolder"
|
||||
InitialUsers={[]}
|
||||
InitialGroups={[]}
|
||||
InitialUsers={ModalConfig.InheritedUsers}
|
||||
InitialGroups={ModalConfig.InheritedGroups}
|
||||
ConfirmLabel="Create"
|
||||
OnConfirm={HandleModalConfirm}
|
||||
OnCancel={() => SetModalConfig(null)}
|
||||
|
||||
Reference in new issue
Block a user