Compare commits

..

No commits in common. "main" and "v4.0.2" have entirely different histories.
main ... v4.0.2

33 changed files with 178 additions and 80 deletions

View file

@ -10,7 +10,7 @@ If you're looking for the mobile app, it's at [`bewcloud-mobile`](https://github
## Self-host it!
[![Buy managed cloud (1 year)](https://img.shields.io/badge/Buy%20managed%20cloud%20(1%20year)-51a4fb?style=for-the-badge)](https://payment-links.mollie.com/payment/AiEHa5EpD6wkZN5r6Vs3c)
[![Buy managed cloud (1 year)](https://img.shields.io/badge/Buy%20managed%20cloud%20(1%20year)-51a4fb?style=for-the-badge)](https://payment-links.mollie.com/payment/zeLCmenLMLQwTcvqPJMyb)
Or, to run on your own machine, start with these commands:
@ -111,6 +111,3 @@ 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.
- 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.

View file

@ -11,7 +11,6 @@ const config: PartialDeep<Config> = {
// 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
// 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
// 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
@ -20,11 +19,9 @@ const config: PartialDeep<Config> = {
// 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)
// 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: {
// 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: {
// title: 'My own cloud',

View file

@ -448,7 +448,7 @@ export default function MainCalendar(
</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/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 ring-opacity-15 focus:outline-none ${
!isViewOptionsDropdownOpen.value ? 'hidden' : ''
}`}
role='menu'
@ -509,7 +509,7 @@ export default function MainCalendar(
</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/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 ring-opacity-15 focus:outline-none ${
!isImportExportOptionsDropdownOpen.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -111,7 +111,7 @@ export default function SearchEvents({ calendars, onClickOpenEvent }: SearchEven
? (
<section class='relative inline-block text-left ml-2 text-xs'>
<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/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 ring-opacity-15 focus:outline-none`}
role='menu'
aria-orientation='vertical'
aria-labelledby='view-button'

View file

@ -359,7 +359,7 @@ export default function Contacts(
</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/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 ring-opacity-15 focus:outline-none ${
!isAddressBooksDropdownOpen.value ? 'hidden' : ''
}`}
role='menu'
@ -424,7 +424,7 @@ export default function Contacts(
</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/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 ring-opacity-15 focus:outline-none ${
!isOptionsDropdownOpen.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -727,7 +727,7 @@ export default function MainExpenses({ initialBudgets, initialExpenses, initialM
</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/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 ring-opacity-15 focus:outline-none ${
!areNewOptionsOption.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -751,7 +751,7 @@ export default function MainFiles(
</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/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 ring-opacity-15 focus:outline-none ${
!areBulkOptionsOpen.value ? 'hidden' : ''
}`}
role='menu'
@ -802,7 +802,7 @@ export default function MainFiles(
</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/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 ring-opacity-15 focus:outline-none ${
!areNewOptionsOpen.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -111,7 +111,7 @@ export default function SearchFiles() {
? (
<section class='relative inline-block text-left ml-2 text-sm'>
<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/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 ring-opacity-15 focus:outline-none overflow-y-scroll max-h-[80%] min-h-56`}
role='menu'
aria-orientation='vertical'
aria-labelledby='view-button'

View file

@ -181,7 +181,7 @@ export default function Articles({ initialArticles }: ArticlesProps) {
</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/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 ring-opacity-15 focus:outline-none ${
!isFilterDropdownOpen.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -254,7 +254,7 @@ export default function Feeds({ initialFeeds }: FeedsProps) {
</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/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 ring-opacity-15 focus:outline-none ${
!isOptionsDropdownOpen.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -250,7 +250,7 @@ export default function MainNotes({ initialDirectories, initialFiles, initialPat
</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/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 ring-opacity-15 focus:outline-none ${
!areNewOptionsOption.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -166,7 +166,7 @@ export default function MainPhotos({ initialDirectories, initialFiles, initialPa
</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/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 ring-opacity-15 focus:outline-none ${
!areNewOptionsOption.value ? 'hidden' : ''
}`}
role='menu'

View file

@ -1,6 +1,6 @@
services:
website:
image: ghcr.io/bewcloud/bewcloud:v4.1.2
image: ghcr.io/bewcloud/bewcloud:v4.0.2
# NOTE: uncomment below (and comment above) only if you pulled the repo and want to build the image locally
# build:
# context: .

View file

@ -16,7 +16,6 @@ export class AppConfig {
allowedCookieDomains: [],
skipCookieDomainSecurity: false,
enableSingleSignOn: false,
allowSignupsViaSingleSignOn: false,
singleSignOnUrl: '',
singleSignOnEmailAttribute: 'email',
singleSignOnScopes: ['openid', 'email'],
@ -25,11 +24,9 @@ export class AppConfig {
rootPath: 'data-files',
allowPublicSharing: false,
allowDirectoryDownloads: false,
maxUploadSizeInMegabytes: 100,
},
core: {
enabledApps: ['dashboard', 'files', 'news', 'notes', 'photos', 'expenses', 'contacts', 'calendar'],
maxRequestSizeInMegabytes: 12,
},
visuals: {
title: '',
@ -120,12 +117,11 @@ export class AppConfig {
return this.config;
}
static async isSignupAllowed({ viaSingleSignOn = false }: { viaSingleSignOn?: boolean } = {}): Promise<boolean> {
static async isSignupAllowed(): Promise<boolean> {
await this.loadConfig();
const areSignupsAllowed = viaSingleSignOn && !this.config.auth.allowSignups
? this.config.auth.allowSignupsViaSingleSignOn
: this.config.auth.allowSignups;
const areSignupsAllowed = this.config.auth.allowSignups;
const areThereAdmins = await UserModel.isThereAnAdmin();
if (areSignupsAllowed || !areThereAdmins) {

View file

@ -169,7 +169,7 @@ export class OidcModel {
throw new Error(`Missing user/${emailAttribute}`);
}
const isSignupAllowed = await AppConfig.isSignupAllowed({ viaSingleSignOn: true });
const isSignupAllowed = await AppConfig.isSignupAllowed();
const isThereAnAdmin = await UserModel.isThereAnAdmin();
// Confirm the user exists (or signup if allowed)
@ -181,10 +181,6 @@ export class OidcModel {
}
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!');
}

View file

@ -17,7 +17,15 @@ export interface Page {
patch?: RequestHandler;
delete?: RequestHandler;
options?: RequestHandler;
catchAll?: RequestHandler;
copy?: RequestHandler;
move?: RequestHandler;
mkcol?: RequestHandler;
mkcalendar?: RequestHandler;
lock?: RequestHandler;
unlock?: RequestHandler;
propfind?: RequestHandler;
proppatch?: RequestHandler;
report?: RequestHandler;
}
type AccessMode = 'public' | 'user';
@ -53,7 +61,15 @@ export default function page(
patch,
delete: deleteAction,
options,
catchAll,
copy,
move,
mkcol,
mkcalendar,
lock,
unlock,
propfind,
proppatch,
report,
accessMode,
}: Params,
): Page {
@ -64,6 +80,14 @@ export default function page(
patch: patch ? permissioned(patch, accessMode) : undefined,
delete: deleteAction ? permissioned(deleteAction, accessMode) : undefined,
options: options ? permissioned(options, accessMode) : undefined,
catchAll: catchAll ? permissioned(catchAll, accessMode) : undefined,
copy: copy ? permissioned(copy, 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,
};
}

View file

@ -159,8 +159,6 @@ export interface Config {
skipCookieDomainSecurity: boolean;
/** If true, single sign-on will be enabled */
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 */
singleSignOnUrl: string;
/** The attribute to prefer as email of the identity/single sign-on provider */
@ -175,14 +173,10 @@ export interface Config {
allowPublicSharing: boolean;
/** If true, directories can be downloaded as zip files */
allowDirectoryDownloads: boolean;
/** The maximum upload size in megabytes. Overrides the core.maxRequestSizeInMegabytes setting on /dav and /api/files/upload endpoints. */
maxUploadSizeInMegabytes: number;
};
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. */
enabledApps: OptionalApp[];
/** The maximum request size in megabytes. */
maxRequestSizeInMegabytes: number;
};
visuals: {
/** An override title of the application. Empty shows the default title. */

13
main.ts
View file

@ -1,13 +1,9 @@
import routes, { Route } from './routes.ts';
import { startCrons } from './crons/index.ts';
import { Page } from './lib/page.ts';
import { AppConfig } from './lib/config.ts';
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_MEGABYTES = 12;
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) {
const headers = response.headers;
@ -57,15 +53,12 @@ function handleLogging(request: Request, response: Response) {
async function handler(request: Request) {
const contentLength = request.headers.get('content-length');
const path = new URL(request.url).pathname;
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) {
if (contentLength && parseInt(contentLength, 10) > MAX_REQUEST_SIZE_IN_BYTES) {
return new Response('Payload too large', { status: 413 });
}
const path = new URL(request.url).pathname;
const origin = request.headers.get('Origin') || '*';
// CORS headers for non-DAV routes

View file

@ -75,6 +75,14 @@ export default page({
put: get,
delete: get,
options: get,
catchAll: get,
copy: get,
move: get,
mkcol: get,
mkcalendar: get,
lock: get,
unlock: get,
propfind: get,
proppatch: get,
report: get,
accessMode: 'public',
});

View file

@ -75,6 +75,13 @@ export default page({
put: get,
delete: get,
options: get,
catchAll: get,
copy: get,
move: get,
mkcol: get,
lock: get,
unlock: get,
propfind: get,
proppatch: get,
report: get,
accessMode: 'public',
});

View file

@ -142,8 +142,6 @@ async function handler({ request, user, match }: RequestHandlerParams): Promise<
console.error(error);
}
}
return new Response('Not Found', { status: 404 });
}
if (request.method === 'MKCOL') {
@ -259,6 +257,12 @@ export default page({
delete: handler,
put: handler,
options: handler,
catchAll: handler,
copy: handler,
move: handler,
mkcol: handler,
lock: handler,
unlock: handler,
propfind: handler,
report: handler,
accessMode: 'public',
});

View file

@ -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",
"clip-rule": "evenodd"
})))), 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/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 ring-opacity-15 focus:outline-none ${!isViewOptionsDropdownOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"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",
"clip-rule": "evenodd"
})))), 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/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 ring-opacity-15 focus:outline-none ${!isImportExportOptionsDropdownOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "import-export-button",

View file

@ -91,7 +91,7 @@ export default function SearchEvents({
}) : null, areResultsVisible.value ? h("section", {
class: "relative inline-block text-left ml-2 text-xs"
}, 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/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 ring-opacity-15 focus:outline-none`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "view-button",

View file

@ -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",
"clip-rule": "evenodd"
})))), 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/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 ring-opacity-15 focus:outline-none ${!isAddressBooksDropdownOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"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",
"clip-rule": "evenodd"
})))), 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/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 ring-opacity-15 focus:outline-none ${!isOptionsDropdownOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "import-export-button",

View file

@ -538,7 +538,7 @@ export default function MainExpenses({
width: 20,
height: 20
}))), 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/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 ring-opacity-15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "new-button",

View file

@ -543,7 +543,7 @@ export default function MainFiles({
width: 20,
height: 20
}))), 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/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 ring-opacity-15 focus:outline-none ${!areBulkOptionsOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "bulk-button",
@ -576,7 +576,7 @@ export default function MainFiles({
width: 20,
height: 20
}))), 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/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 ring-opacity-15 focus:outline-none ${!areNewOptionsOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "new-button",

View file

@ -90,7 +90,7 @@ export default function SearchFiles() {
}) : null, areResultsVisible.value ? h("section", {
class: "relative inline-block text-left ml-2 text-sm"
}, 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/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 ring-opacity-15 focus:outline-none overflow-y-scroll max-h-[80%] min-h-56`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "view-button",

View file

@ -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",
"clip-rule": "evenodd"
})))), 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/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 ring-opacity-15 focus:outline-none ${!isFilterDropdownOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "filter-button",

View file

@ -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",
"clip-rule": "evenodd"
})))), 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/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 ring-opacity-15 focus:outline-none ${!isOptionsDropdownOpen.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "filter-button",

View file

@ -186,7 +186,7 @@ export default function MainNotes({
width: 20,
height: 20
}))), 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/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 ring-opacity-15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "new-button",

View file

@ -124,7 +124,7 @@ export default function MainPhotos({
width: 20,
height: 20
}))), 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/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 ring-opacity-15 focus:outline-none ${!areNewOptionsOption.value ? 'hidden' : ''}`,
role: "menu",
"aria-orientation": "vertical",
"aria-labelledby": "new-button",

View file

@ -1220,11 +1220,8 @@
--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);
}
.ring-black\/15 {
--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-black {
--tw-ring-color: var(--color-black);
}
.ring-slate-800 {
--tw-ring-color: var(--color-slate-800);

View file

@ -33,7 +33,14 @@ function createPageRouteHandler(id: string, pathname: string) {
patch,
delete: deleteAction,
options,
catchAll,
copy,
move,
mkcol,
lock,
unlock,
propfind,
proppatch,
report,
} = page;
const { user, session, tokenData } = (await getDataFromRequest(request)) || {};
@ -141,9 +148,9 @@ function createPageRouteHandler(id: string, pathname: string) {
});
}
break;
default:
if (catchAll) {
return await catchAll({
case 'COPY':
if (copy) {
return await copy({
request,
match,
user,
@ -151,7 +158,85 @@ function createPageRouteHandler(id: string, pathname: string) {
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:
return new Response('Not Implemented', { status: 501 });
}