mirror of
https://github.com/bewcloud/bewcloud.git
synced 2026-03-11 08:54:49 +00:00
Compare commits
10 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f871b72ad | ||
|
|
f50423028b | ||
|
|
69a916d709 | ||
|
|
0d20b4a337 | ||
|
|
917649b97a | ||
|
|
5d394045dd | ||
|
|
264d4da6e5 | ||
|
|
ec334fb8fa | ||
|
|
bd141bf9dc | ||
|
|
1aca444b22 |
34 changed files with 95 additions and 186 deletions
|
|
@ -10,7 +10,7 @@ If you're looking for the mobile app, it's at [`bewcloud-mobile`](https://github
|
||||||
|
|
||||||
## Self-host it!
|
## Self-host it!
|
||||||
|
|
||||||
[-51a4fb?style=for-the-badge)](https://payment-links.mollie.com/payment/zeLCmenLMLQwTcvqPJMyb)
|
[-51a4fb?style=for-the-badge)](https://payment-links.mollie.com/payment/AiEHa5EpD6wkZN5r6Vs3c)
|
||||||
|
|
||||||
Or, to run on your own machine, start with these commands:
|
Or, to run on your own machine, start with these commands:
|
||||||
|
|
||||||
|
|
@ -111,3 +111,6 @@ These are not officially endorsed, but are alternative ways of running bewCloud.
|
||||||
|
|
||||||
- [`bewcloud-nixos`](https://codeberg.org/ntninja/bewcloud-nixos/) by [@ntninja](https://codeberg.org/ntninja/) exposes bewCloud as an easy-to-use NixOS integration as an alternative to using Docker or running the app locally.
|
- [`bewcloud-nixos`](https://codeberg.org/ntninja/bewcloud-nixos/) by [@ntninja](https://codeberg.org/ntninja/) exposes bewCloud as an easy-to-use NixOS integration as an alternative to using Docker or running the app locally.
|
||||||
- For installation, please see the [README](https://codeberg.org/ntninja/bewcloud-nixos/src/branch/main/README.md).
|
- For installation, please see the [README](https://codeberg.org/ntninja/bewcloud-nixos/src/branch/main/README.md).
|
||||||
|
- [`bewcloud-helm`](https://github.com/loboda4450/charts/tree/main/charts/bewcloud) by [@loboda4450](https://github.com/loboda4450/) exposes bewCloud as a Helm chart.
|
||||||
|
- For installation, please see the [README](https://github.com/loboda4450/charts/blob/main/charts/bewcloud/README.md)
|
||||||
|
- Supports automatic migrations, Radicale installation (as a dependency chart) and streamlined, fully yaml-based configuration.
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ const config: PartialDeep<Config> = {
|
||||||
// allowedCookieDomains: ['example.com', 'example.net'], // Can be set to allow more than the baseUrl's domain for session cookies
|
// allowedCookieDomains: ['example.com', 'example.net'], // Can be set to allow more than the baseUrl's domain for session cookies
|
||||||
// skipCookieDomainSecurity: true, // If true, the cookie domain will not be strictly set and checked against. This skipping slightly reduces security, but is usually necessary for reverse proxies like Cloudflare Tunnel
|
// skipCookieDomainSecurity: true, // If true, the cookie domain will not be strictly set and checked against. This skipping slightly reduces security, but is usually necessary for reverse proxies like Cloudflare Tunnel
|
||||||
// enableSingleSignOn: false, // If true, single sign-on will be enabled
|
// enableSingleSignOn: false, // If true, single sign-on will be enabled
|
||||||
|
// allowSignupsViaSingleSignOn: false, // If true, signups via single sign-on will be allowed, overriding allowSignups
|
||||||
// singleSignOnUrl: '', // The Discovery URL (AKA Issuer) of the identity/single sign-on provider
|
// singleSignOnUrl: '', // The Discovery URL (AKA Issuer) of the identity/single sign-on provider
|
||||||
// singleSignOnEmailAttribute: 'email', // The attribute to prefer as email of the identity/single sign-on provider
|
// singleSignOnEmailAttribute: 'email', // The attribute to prefer as email of the identity/single sign-on provider
|
||||||
// singleSignOnScopes: ['openid', 'email'], // The scopes to request from the identity/single sign-on provider
|
// singleSignOnScopes: ['openid', 'email'], // The scopes to request from the identity/single sign-on provider
|
||||||
|
|
@ -19,9 +20,11 @@ const config: PartialDeep<Config> = {
|
||||||
// rootPath: 'data-files',
|
// rootPath: 'data-files',
|
||||||
// allowPublicSharing: false, // If true, public file sharing will be allowed (still requires a user to enable sharing for a given file or directory)
|
// allowPublicSharing: false, // If true, public file sharing will be allowed (still requires a user to enable sharing for a given file or directory)
|
||||||
// allowDirectoryDownloads: false, // If true, directories can be downloaded as zip files
|
// allowDirectoryDownloads: false, // If true, directories can be downloaded as zip files
|
||||||
|
// maxUploadSizeInMegabytes: 100, // The maximum upload size in megabytes. Overrides the core.maxRequestSizeInMegabytes setting on /dav and /api/files/upload endpoints.
|
||||||
// },
|
// },
|
||||||
// core: {
|
// core: {
|
||||||
// enabledApps: ['dashboard', 'files', 'news', 'notes', 'photos', 'expenses', 'contacts', 'calendar'], // The apps to show, in order of appearance in the header. The first app will be the default one shown after logging in. At least one is required.
|
// enabledApps: ['dashboard', 'files', 'news', 'notes', 'photos', 'expenses', 'contacts', 'calendar'], // The apps to show, in order of appearance in the header. The first app will be the default one shown after logging in. At least one is required.
|
||||||
|
// maxRequestSizeInMegabytes: 12, // The maximum request size in megabytes.
|
||||||
// },
|
// },
|
||||||
// visuals: {
|
// visuals: {
|
||||||
// title: 'My own cloud',
|
// title: 'My own cloud',
|
||||||
|
|
|
||||||
|
|
@ -448,7 +448,7 @@ export default function MainCalendar(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!isViewOptionsDropdownOpen.value ? 'hidden' : ''
|
!isViewOptionsDropdownOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
@ -509,7 +509,7 @@ export default function MainCalendar(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!isImportExportOptionsDropdownOpen.value ? 'hidden' : ''
|
!isImportExportOptionsDropdownOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ export default function SearchEvents({ calendars, onClickOpenEvent }: SearchEven
|
||||||
? (
|
? (
|
||||||
<section class='relative inline-block text-left ml-2 text-xs'>
|
<section class='relative inline-block text-left ml-2 text-xs'>
|
||||||
<section
|
<section
|
||||||
class={`absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none`}
|
class={`absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none`}
|
||||||
role='menu'
|
role='menu'
|
||||||
aria-orientation='vertical'
|
aria-orientation='vertical'
|
||||||
aria-labelledby='view-button'
|
aria-labelledby='view-button'
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,7 @@ export default function Contacts(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right divide-y divide-slate-600 rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right divide-y divide-slate-600 rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!isAddressBooksDropdownOpen.value ? 'hidden' : ''
|
!isAddressBooksDropdownOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
@ -424,7 +424,7 @@ export default function Contacts(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!isOptionsDropdownOpen.value ? 'hidden' : ''
|
!isOptionsDropdownOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -727,7 +727,7 @@ export default function MainExpenses({ initialBudgets, initialExpenses, initialM
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!areNewOptionsOption.value ? 'hidden' : ''
|
!areNewOptionsOption.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -751,7 +751,7 @@ export default function MainFiles(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute left-0 z-10 mt-2 w-44 origin-top-left rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute left-0 z-10 mt-2 w-44 origin-top-left rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!areBulkOptionsOpen.value ? 'hidden' : ''
|
!areBulkOptionsOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
@ -802,7 +802,7 @@ export default function MainFiles(
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!areNewOptionsOpen.value ? 'hidden' : ''
|
!areNewOptionsOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ export default function SearchFiles() {
|
||||||
? (
|
? (
|
||||||
<section class='relative inline-block text-left ml-2 text-sm'>
|
<section class='relative inline-block text-left ml-2 text-sm'>
|
||||||
<section
|
<section
|
||||||
class={`absolute right-0 z-10 mt-2 w-80 origin-top-right rounded-md bg-slate-600 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none overflow-y-scroll max-h-[80%] min-h-56`}
|
class={`absolute right-0 z-10 mt-2 w-80 origin-top-right rounded-md bg-slate-600 shadow-lg ring-1 ring-black/15 focus:outline-none overflow-y-scroll max-h-[80%] min-h-56`}
|
||||||
role='menu'
|
role='menu'
|
||||||
aria-orientation='vertical'
|
aria-orientation='vertical'
|
||||||
aria-labelledby='view-button'
|
aria-labelledby='view-button'
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ export default function Articles({ initialArticles }: ArticlesProps) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!isFilterDropdownOpen.value ? 'hidden' : ''
|
!isFilterDropdownOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -254,7 +254,7 @@ export default function Feeds({ initialFeeds }: FeedsProps) {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!isOptionsDropdownOpen.value ? 'hidden' : ''
|
!isOptionsDropdownOpen.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ export default function MainNotes({ initialDirectories, initialFiles, initialPat
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!areNewOptionsOption.value ? 'hidden' : ''
|
!areNewOptionsOption.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ export default function MainPhotos({ initialDirectories, initialFiles, initialPa
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${
|
class={`absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${
|
||||||
!areNewOptionsOption.value ? 'hidden' : ''
|
!areNewOptionsOption.value ? 'hidden' : ''
|
||||||
}`}
|
}`}
|
||||||
role='menu'
|
role='menu'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
services:
|
services:
|
||||||
website:
|
website:
|
||||||
image: ghcr.io/bewcloud/bewcloud:v4.0.1
|
image: ghcr.io/bewcloud/bewcloud:v4.1.2
|
||||||
# NOTE: uncomment below (and comment above) only if you pulled the repo and want to build the image locally
|
# NOTE: uncomment below (and comment above) only if you pulled the repo and want to build the image locally
|
||||||
# build:
|
# build:
|
||||||
# context: .
|
# context: .
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ export class AppConfig {
|
||||||
allowedCookieDomains: [],
|
allowedCookieDomains: [],
|
||||||
skipCookieDomainSecurity: false,
|
skipCookieDomainSecurity: false,
|
||||||
enableSingleSignOn: false,
|
enableSingleSignOn: false,
|
||||||
|
allowSignupsViaSingleSignOn: false,
|
||||||
singleSignOnUrl: '',
|
singleSignOnUrl: '',
|
||||||
singleSignOnEmailAttribute: 'email',
|
singleSignOnEmailAttribute: 'email',
|
||||||
singleSignOnScopes: ['openid', 'email'],
|
singleSignOnScopes: ['openid', 'email'],
|
||||||
|
|
@ -24,9 +25,11 @@ export class AppConfig {
|
||||||
rootPath: 'data-files',
|
rootPath: 'data-files',
|
||||||
allowPublicSharing: false,
|
allowPublicSharing: false,
|
||||||
allowDirectoryDownloads: false,
|
allowDirectoryDownloads: false,
|
||||||
|
maxUploadSizeInMegabytes: 100,
|
||||||
},
|
},
|
||||||
core: {
|
core: {
|
||||||
enabledApps: ['dashboard', 'files', 'news', 'notes', 'photos', 'expenses', 'contacts', 'calendar'],
|
enabledApps: ['dashboard', 'files', 'news', 'notes', 'photos', 'expenses', 'contacts', 'calendar'],
|
||||||
|
maxRequestSizeInMegabytes: 12,
|
||||||
},
|
},
|
||||||
visuals: {
|
visuals: {
|
||||||
title: '',
|
title: '',
|
||||||
|
|
@ -117,11 +120,12 @@ export class AppConfig {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async isSignupAllowed(): Promise<boolean> {
|
static async isSignupAllowed({ viaSingleSignOn = false }: { viaSingleSignOn?: boolean } = {}): Promise<boolean> {
|
||||||
await this.loadConfig();
|
await this.loadConfig();
|
||||||
|
|
||||||
const areSignupsAllowed = this.config.auth.allowSignups;
|
const areSignupsAllowed = viaSingleSignOn && !this.config.auth.allowSignups
|
||||||
|
? this.config.auth.allowSignupsViaSingleSignOn
|
||||||
|
: this.config.auth.allowSignups;
|
||||||
const areThereAdmins = await UserModel.isThereAnAdmin();
|
const areThereAdmins = await UserModel.isThereAnAdmin();
|
||||||
|
|
||||||
if (areSignupsAllowed || !areThereAdmins) {
|
if (areSignupsAllowed || !areThereAdmins) {
|
||||||
|
|
|
||||||
11
lib/feed.ts
11
lib/feed.ts
|
|
@ -222,13 +222,20 @@ export async function getUrlInfo(url: string): Promise<{ title: string; htmlBody
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseTextFromHtml(html: string): Promise<string> {
|
export async function parseTextFromHtml(html: string): Promise<string> {
|
||||||
let text = '';
|
if (!html || !html.trim()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
await initParser();
|
await initParser();
|
||||||
|
|
||||||
const document = new DOMParser().parseFromString(html, 'text/html');
|
const document = new DOMParser().parseFromString(html, 'text/html');
|
||||||
|
|
||||||
text = document!.textContent;
|
// Extract text from body to avoid any artifacts from the document wrapper
|
||||||
|
const text = (document?.querySelector('body')?.textContent || document?.textContent || '')
|
||||||
|
// Collapse runs of 2+ whitespace/newline characters, preserving single line breaks
|
||||||
|
.replace(/[^\S\n]{2,}/g, ' ')
|
||||||
|
.replace(/\n{3,}/g, '\n\n')
|
||||||
|
.trim();
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ export class OidcModel {
|
||||||
throw new Error(`Missing user/${emailAttribute}`);
|
throw new Error(`Missing user/${emailAttribute}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSignupAllowed = await AppConfig.isSignupAllowed();
|
const isSignupAllowed = await AppConfig.isSignupAllowed({ viaSingleSignOn: true });
|
||||||
const isThereAnAdmin = await UserModel.isThereAnAdmin();
|
const isThereAnAdmin = await UserModel.isThereAnAdmin();
|
||||||
|
|
||||||
// Confirm the user exists (or signup if allowed)
|
// Confirm the user exists (or signup if allowed)
|
||||||
|
|
@ -181,6 +181,10 @@ export class OidcModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
|
if (!config.auth.allowSignupsViaSingleSignOn) {
|
||||||
|
throw new Error('Sign up via SSO is not allowed!');
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error('There was a problem signing up or logging in!');
|
throw new Error('There was a problem signing up or logging in!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
30
lib/page.ts
30
lib/page.ts
|
|
@ -17,15 +17,7 @@ export interface Page {
|
||||||
patch?: RequestHandler;
|
patch?: RequestHandler;
|
||||||
delete?: RequestHandler;
|
delete?: RequestHandler;
|
||||||
options?: RequestHandler;
|
options?: RequestHandler;
|
||||||
copy?: RequestHandler;
|
catchAll?: RequestHandler;
|
||||||
move?: RequestHandler;
|
|
||||||
mkcol?: RequestHandler;
|
|
||||||
mkcalendar?: RequestHandler;
|
|
||||||
lock?: RequestHandler;
|
|
||||||
unlock?: RequestHandler;
|
|
||||||
propfind?: RequestHandler;
|
|
||||||
proppatch?: RequestHandler;
|
|
||||||
report?: RequestHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccessMode = 'public' | 'user';
|
type AccessMode = 'public' | 'user';
|
||||||
|
|
@ -61,15 +53,7 @@ export default function page(
|
||||||
patch,
|
patch,
|
||||||
delete: deleteAction,
|
delete: deleteAction,
|
||||||
options,
|
options,
|
||||||
copy,
|
catchAll,
|
||||||
move,
|
|
||||||
mkcol,
|
|
||||||
mkcalendar,
|
|
||||||
lock,
|
|
||||||
unlock,
|
|
||||||
propfind,
|
|
||||||
proppatch,
|
|
||||||
report,
|
|
||||||
accessMode,
|
accessMode,
|
||||||
}: Params,
|
}: Params,
|
||||||
): Page {
|
): Page {
|
||||||
|
|
@ -80,14 +64,6 @@ export default function page(
|
||||||
patch: patch ? permissioned(patch, accessMode) : undefined,
|
patch: patch ? permissioned(patch, accessMode) : undefined,
|
||||||
delete: deleteAction ? permissioned(deleteAction, accessMode) : undefined,
|
delete: deleteAction ? permissioned(deleteAction, accessMode) : undefined,
|
||||||
options: options ? permissioned(options, accessMode) : undefined,
|
options: options ? permissioned(options, accessMode) : undefined,
|
||||||
copy: copy ? permissioned(copy, accessMode) : undefined,
|
catchAll: catchAll ? permissioned(catchAll, accessMode) : undefined,
|
||||||
move: move ? permissioned(move, accessMode) : undefined,
|
|
||||||
mkcol: mkcol ? permissioned(mkcol, accessMode) : undefined,
|
|
||||||
mkcalendar: mkcalendar ? permissioned(mkcalendar, accessMode) : undefined,
|
|
||||||
lock: lock ? permissioned(lock, accessMode) : undefined,
|
|
||||||
unlock: unlock ? permissioned(unlock, accessMode) : undefined,
|
|
||||||
propfind: propfind ? permissioned(propfind, accessMode) : undefined,
|
|
||||||
proppatch: proppatch ? permissioned(proppatch, accessMode) : undefined,
|
|
||||||
report: report ? permissioned(report, accessMode) : undefined,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,8 @@ export interface Config {
|
||||||
skipCookieDomainSecurity: boolean;
|
skipCookieDomainSecurity: boolean;
|
||||||
/** If true, single sign-on will be enabled */
|
/** If true, single sign-on will be enabled */
|
||||||
enableSingleSignOn: boolean;
|
enableSingleSignOn: boolean;
|
||||||
|
/** If true, signups via single sign-on will be allowed, overriding allowSignups */
|
||||||
|
allowSignupsViaSingleSignOn: boolean;
|
||||||
/** The Discovery URL (AKA Issuer) of the identity/single sign-on provider */
|
/** The Discovery URL (AKA Issuer) of the identity/single sign-on provider */
|
||||||
singleSignOnUrl: string;
|
singleSignOnUrl: string;
|
||||||
/** The attribute to prefer as email of the identity/single sign-on provider */
|
/** The attribute to prefer as email of the identity/single sign-on provider */
|
||||||
|
|
@ -173,10 +175,14 @@ export interface Config {
|
||||||
allowPublicSharing: boolean;
|
allowPublicSharing: boolean;
|
||||||
/** If true, directories can be downloaded as zip files */
|
/** If true, directories can be downloaded as zip files */
|
||||||
allowDirectoryDownloads: boolean;
|
allowDirectoryDownloads: boolean;
|
||||||
|
/** The maximum upload size in megabytes. Overrides the core.maxRequestSizeInMegabytes setting on /dav and /api/files/upload endpoints. */
|
||||||
|
maxUploadSizeInMegabytes: number;
|
||||||
};
|
};
|
||||||
core: {
|
core: {
|
||||||
/** The apps to show, in order of appearance in the header. The first app will be the default one shown after logging in. At least one is required. */
|
/** The apps to show, in order of appearance in the header. The first app will be the default one shown after logging in. At least one is required. */
|
||||||
enabledApps: OptionalApp[];
|
enabledApps: OptionalApp[];
|
||||||
|
/** The maximum request size in megabytes. */
|
||||||
|
maxRequestSizeInMegabytes: number;
|
||||||
};
|
};
|
||||||
visuals: {
|
visuals: {
|
||||||
/** An override title of the application. Empty shows the default title. */
|
/** An override title of the application. Empty shows the default title. */
|
||||||
|
|
|
||||||
13
main.ts
13
main.ts
|
|
@ -1,9 +1,13 @@
|
||||||
import routes, { Route } from './routes.ts';
|
import routes, { Route } from './routes.ts';
|
||||||
import { startCrons } from './crons/index.ts';
|
import { startCrons } from './crons/index.ts';
|
||||||
import { Page } from './lib/page.ts';
|
import { Page } from './lib/page.ts';
|
||||||
|
import { AppConfig } from './lib/config.ts';
|
||||||
|
|
||||||
const MAX_REQUEST_SIZE_IN_MEGABYTES = 12;
|
const config = await AppConfig.getConfig();
|
||||||
|
const MAX_REQUEST_SIZE_IN_MEGABYTES = config.core.maxRequestSizeInMegabytes;
|
||||||
|
const MAX_UPLOAD_SIZE_IN_MEGABYTES = config.files.maxUploadSizeInMegabytes;
|
||||||
const MAX_REQUEST_SIZE_IN_BYTES = MAX_REQUEST_SIZE_IN_MEGABYTES * 1024 * 1024;
|
const MAX_REQUEST_SIZE_IN_BYTES = MAX_REQUEST_SIZE_IN_MEGABYTES * 1024 * 1024;
|
||||||
|
const MAX_UPLOAD_SIZE_IN_BYTES = MAX_UPLOAD_SIZE_IN_MEGABYTES * 1024 * 1024;
|
||||||
|
|
||||||
function applyCorsHeadersToResponse(origin: string, response: Response) {
|
function applyCorsHeadersToResponse(origin: string, response: Response) {
|
||||||
const headers = response.headers;
|
const headers = response.headers;
|
||||||
|
|
@ -53,12 +57,15 @@ function handleLogging(request: Request, response: Response) {
|
||||||
|
|
||||||
async function handler(request: Request) {
|
async function handler(request: Request) {
|
||||||
const contentLength = request.headers.get('content-length');
|
const contentLength = request.headers.get('content-length');
|
||||||
|
const path = new URL(request.url).pathname;
|
||||||
|
|
||||||
if (contentLength && parseInt(contentLength, 10) > MAX_REQUEST_SIZE_IN_BYTES) {
|
const isUploadRequest = path.startsWith('/api/files/upload') || path.startsWith('/dav');
|
||||||
|
const maxSizeInBytes = isUploadRequest ? MAX_UPLOAD_SIZE_IN_BYTES : MAX_REQUEST_SIZE_IN_BYTES;
|
||||||
|
|
||||||
|
if (contentLength && parseInt(contentLength, 10) > maxSizeInBytes) {
|
||||||
return new Response('Payload too large', { status: 413 });
|
return new Response('Payload too large', { status: 413 });
|
||||||
}
|
}
|
||||||
|
|
||||||
const path = new URL(request.url).pathname;
|
|
||||||
const origin = request.headers.get('Origin') || '*';
|
const origin = request.headers.get('Origin') || '*';
|
||||||
|
|
||||||
// CORS headers for non-DAV routes
|
// CORS headers for non-DAV routes
|
||||||
|
|
|
||||||
|
|
@ -75,14 +75,6 @@ export default page({
|
||||||
put: get,
|
put: get,
|
||||||
delete: get,
|
delete: get,
|
||||||
options: get,
|
options: get,
|
||||||
copy: get,
|
catchAll: get,
|
||||||
move: get,
|
|
||||||
mkcol: get,
|
|
||||||
mkcalendar: get,
|
|
||||||
lock: get,
|
|
||||||
unlock: get,
|
|
||||||
propfind: get,
|
|
||||||
proppatch: get,
|
|
||||||
report: get,
|
|
||||||
accessMode: 'public',
|
accessMode: 'public',
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -75,13 +75,6 @@ export default page({
|
||||||
put: get,
|
put: get,
|
||||||
delete: get,
|
delete: get,
|
||||||
options: get,
|
options: get,
|
||||||
copy: get,
|
catchAll: get,
|
||||||
move: get,
|
|
||||||
mkcol: get,
|
|
||||||
lock: get,
|
|
||||||
unlock: get,
|
|
||||||
propfind: get,
|
|
||||||
proppatch: get,
|
|
||||||
report: get,
|
|
||||||
accessMode: 'public',
|
accessMode: 'public',
|
||||||
});
|
});
|
||||||
|
|
|
||||||
10
pages/dav.ts
10
pages/dav.ts
|
|
@ -142,6 +142,8 @@ async function handler({ request, user, match }: RequestHandlerParams): Promise<
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new Response('Not Found', { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.method === 'MKCOL') {
|
if (request.method === 'MKCOL') {
|
||||||
|
|
@ -257,12 +259,6 @@ export default page({
|
||||||
delete: handler,
|
delete: handler,
|
||||||
put: handler,
|
put: handler,
|
||||||
options: handler,
|
options: handler,
|
||||||
copy: handler,
|
catchAll: handler,
|
||||||
move: handler,
|
|
||||||
mkcol: handler,
|
|
||||||
lock: handler,
|
|
||||||
unlock: handler,
|
|
||||||
propfind: handler,
|
|
||||||
report: handler,
|
|
||||||
accessMode: 'public',
|
accessMode: 'public',
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -361,7 +361,7 @@ export default function MainCalendar({
|
||||||
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
||||||
"clip-rule": "evenodd"
|
"clip-rule": "evenodd"
|
||||||
})))), h("div", {
|
})))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!isViewOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!isViewOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "view-button",
|
"aria-labelledby": "view-button",
|
||||||
|
|
@ -399,7 +399,7 @@ export default function MainCalendar({
|
||||||
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
||||||
"clip-rule": "evenodd"
|
"clip-rule": "evenodd"
|
||||||
})))), h("div", {
|
})))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!isImportExportOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!isImportExportOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "import-export-button",
|
"aria-labelledby": "import-export-button",
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ export default function SearchEvents({
|
||||||
}) : null, areResultsVisible.value ? h("section", {
|
}) : null, areResultsVisible.value ? h("section", {
|
||||||
class: "relative inline-block text-left ml-2 text-xs"
|
class: "relative inline-block text-left ml-2 text-xs"
|
||||||
}, h("section", {
|
}, h("section", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none`,
|
class: `absolute right-0 z-10 mt-2 w-56 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "view-button",
|
"aria-labelledby": "view-button",
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,7 @@ export default function Contacts({
|
||||||
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
||||||
"clip-rule": "evenodd"
|
"clip-rule": "evenodd"
|
||||||
})))), h("div", {
|
})))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right divide-y divide-slate-600 rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!isAddressBooksDropdownOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right divide-y divide-slate-600 rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!isAddressBooksDropdownOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "select-address-book-button",
|
"aria-labelledby": "select-address-book-button",
|
||||||
|
|
@ -318,7 +318,7 @@ export default function Contacts({
|
||||||
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
||||||
"clip-rule": "evenodd"
|
"clip-rule": "evenodd"
|
||||||
})))), h("div", {
|
})))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!isOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!isOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "import-export-button",
|
"aria-labelledby": "import-export-button",
|
||||||
|
|
|
||||||
|
|
@ -538,7 +538,7 @@ export default function MainExpenses({
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20
|
||||||
}))), h("div", {
|
}))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "new-button",
|
"aria-labelledby": "new-button",
|
||||||
|
|
|
||||||
|
|
@ -543,7 +543,7 @@ export default function MainFiles({
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20
|
||||||
}))), h("div", {
|
}))), h("div", {
|
||||||
class: `absolute left-0 z-10 mt-2 w-44 origin-top-left rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!areBulkOptionsOpen.value ? 'hidden' : ''}`,
|
class: `absolute left-0 z-10 mt-2 w-44 origin-top-left rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!areBulkOptionsOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "bulk-button",
|
"aria-labelledby": "bulk-button",
|
||||||
|
|
@ -576,7 +576,7 @@ export default function MainFiles({
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20
|
||||||
}))), h("div", {
|
}))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!areNewOptionsOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!areNewOptionsOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "new-button",
|
"aria-labelledby": "new-button",
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ export default function SearchFiles() {
|
||||||
}) : null, areResultsVisible.value ? h("section", {
|
}) : null, areResultsVisible.value ? h("section", {
|
||||||
class: "relative inline-block text-left ml-2 text-sm"
|
class: "relative inline-block text-left ml-2 text-sm"
|
||||||
}, h("section", {
|
}, h("section", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-80 origin-top-right rounded-md bg-slate-600 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none overflow-y-scroll max-h-[80%] min-h-56`,
|
class: `absolute right-0 z-10 mt-2 w-80 origin-top-right rounded-md bg-slate-600 shadow-lg ring-1 ring-black/15 focus:outline-none overflow-y-scroll max-h-[80%] min-h-56`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "view-button",
|
"aria-labelledby": "view-button",
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ export default function Articles({
|
||||||
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
||||||
"clip-rule": "evenodd"
|
"clip-rule": "evenodd"
|
||||||
})))), h("div", {
|
})))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!isFilterDropdownOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!isFilterDropdownOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "filter-button",
|
"aria-labelledby": "filter-button",
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ export default function Feeds({
|
||||||
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
||||||
"clip-rule": "evenodd"
|
"clip-rule": "evenodd"
|
||||||
})))), h("div", {
|
})))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!isOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!isOptionsDropdownOpen.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "filter-button",
|
"aria-labelledby": "filter-button",
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ export default function MainNotes({
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20
|
||||||
}))), h("div", {
|
}))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "new-button",
|
"aria-labelledby": "new-button",
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ export default function MainPhotos({
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20
|
height: 20
|
||||||
}))), h("div", {
|
}))), h("div", {
|
||||||
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black ring-opacity-15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
|
class: `absolute right-0 z-10 mt-2 w-44 origin-top-right rounded-md bg-slate-700 shadow-lg ring-1 ring-black/15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
|
||||||
role: "menu",
|
role: "menu",
|
||||||
"aria-orientation": "vertical",
|
"aria-orientation": "vertical",
|
||||||
"aria-labelledby": "new-button",
|
"aria-labelledby": "new-button",
|
||||||
|
|
|
||||||
|
|
@ -1220,8 +1220,11 @@
|
||||||
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
||||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
}
|
}
|
||||||
.ring-black {
|
.ring-black\/15 {
|
||||||
--tw-ring-color: var(--color-black);
|
--tw-ring-color: color-mix(in srgb, #000 15%, transparent);
|
||||||
|
@supports (color: color-mix(in lab, red, red)) {
|
||||||
|
--tw-ring-color: color-mix(in oklab, var(--color-black) 15%, transparent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.ring-slate-800 {
|
.ring-slate-800 {
|
||||||
--tw-ring-color: var(--color-slate-800);
|
--tw-ring-color: var(--color-slate-800);
|
||||||
|
|
|
||||||
107
routes.ts
107
routes.ts
|
|
@ -33,14 +33,7 @@ function createPageRouteHandler(id: string, pathname: string) {
|
||||||
patch,
|
patch,
|
||||||
delete: deleteAction,
|
delete: deleteAction,
|
||||||
options,
|
options,
|
||||||
copy,
|
catchAll,
|
||||||
move,
|
|
||||||
mkcol,
|
|
||||||
lock,
|
|
||||||
unlock,
|
|
||||||
propfind,
|
|
||||||
proppatch,
|
|
||||||
report,
|
|
||||||
} = page;
|
} = page;
|
||||||
|
|
||||||
const { user, session, tokenData } = (await getDataFromRequest(request)) || {};
|
const { user, session, tokenData } = (await getDataFromRequest(request)) || {};
|
||||||
|
|
@ -148,95 +141,17 @@ function createPageRouteHandler(id: string, pathname: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'COPY':
|
|
||||||
if (copy) {
|
|
||||||
return await copy({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'MOVE':
|
|
||||||
if (move) {
|
|
||||||
return await move({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'MKCOL':
|
|
||||||
if (mkcol) {
|
|
||||||
return await mkcol({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'LOCK':
|
|
||||||
if (lock) {
|
|
||||||
return await lock({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'UNLOCK':
|
|
||||||
if (unlock) {
|
|
||||||
return await unlock({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'PROPFIND':
|
|
||||||
if (propfind) {
|
|
||||||
return await propfind({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'PROPPATCH':
|
|
||||||
if (proppatch) {
|
|
||||||
return await proppatch({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'REPORT':
|
|
||||||
if (report) {
|
|
||||||
return await report({
|
|
||||||
request,
|
|
||||||
match,
|
|
||||||
user,
|
|
||||||
session: { userSession: session, tokenData },
|
|
||||||
isRunningLocally,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
|
if (catchAll) {
|
||||||
|
return await catchAll({
|
||||||
|
request,
|
||||||
|
match,
|
||||||
|
user,
|
||||||
|
session: { userSession: session, tokenData },
|
||||||
|
isRunningLocally,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return new Response('Not Implemented', { status: 501 });
|
return new Response('Not Implemented', { status: 501 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue