mirror of
https://github.com/bewcloud/bewcloud.git
synced 2026-03-11 08:54:49 +00:00
Upgrade Fresh to v2
Also upgrade all dependencies, make some unnecessary, and some other small tweaks. Because this has a big potential of unexpectedly breaking things, I'm doing a "breaking release", v3.
This commit is contained in:
parent
ba2103afa9
commit
986573cfc9
138 changed files with 13638 additions and 844 deletions
|
|
@ -12,3 +12,4 @@ node_modules
|
|||
_fresh
|
||||
data-files
|
||||
bewcloud.config.sample.ts
|
||||
.vite
|
||||
|
|
|
|||
2
.dvmrc
2
.dvmrc
|
|
@ -1 +1 @@
|
|||
2.4.5
|
||||
2.5.1
|
||||
|
|
|
|||
2
.github/workflows/build-docker-image.yml
vendored
2
.github/workflows/build-docker-image.yml
vendored
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v3
|
||||
|
|
|
|||
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- name: Configure SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh/
|
||||
|
|
|
|||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
|
@ -6,7 +6,7 @@ jobs:
|
|||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: denoland/setup-deno@v2
|
||||
with:
|
||||
deno-version-file: .dvmrc
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -18,3 +18,6 @@ bewcloud.config.ts
|
|||
|
||||
# Radicale files
|
||||
data-radicale/
|
||||
|
||||
# Vite files
|
||||
.vite
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM denoland/deno:ubuntu-2.4.5
|
||||
FROM denoland/deno:ubuntu-2.5.1
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
|
|
@ -22,4 +22,7 @@ USER deno
|
|||
# Compile the main app so that it doesn't need to be compiled each startup/entry.
|
||||
RUN deno cache --reload main.ts
|
||||
|
||||
# Allow the crons to start
|
||||
ENV START_BEWCLOUD_CRONS=true
|
||||
|
||||
CMD ["run", "--allow-all", "main.ts"]
|
||||
|
|
|
|||
6
Makefile
6
Makefile
|
|
@ -1,3 +1,5 @@
|
|||
SHELL := /bin/bash
|
||||
|
||||
.PHONY: start
|
||||
start:
|
||||
deno task start
|
||||
|
|
@ -19,10 +21,6 @@ build:
|
|||
migrate-db:
|
||||
deno run --allow-net --allow-read --allow-env migrate-db.ts
|
||||
|
||||
.PHONY: crons/cleanup
|
||||
crons/cleanup:
|
||||
deno run --allow-net --allow-read --allow-env crons/cleanup.ts
|
||||
|
||||
.PHONY: exec-db
|
||||
exec-db:
|
||||
docker exec -it -u postgres $(shell basename $(CURDIR))-postgresql-1 psql
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Config, PartialDeep } from './lib/types.ts';
|
|||
/** Check the Config type for all the possible options and instructions. */
|
||||
const config: PartialDeep<Config> = {
|
||||
auth: {
|
||||
baseUrl: 'http://localhost:8000', // The base URL of the application you use to access the app, i.e. "http://localhost:8000" or "https://cloud.example.com" (SSO redirect, if enabled, will be this + /oidc/callback, so "https://cloud.example.com/oidc/callback")
|
||||
baseUrl: 'http://localhost:8000', // The base URL of the application you use to access the app, i.e. "http://localhost:8000" or "https://cloud.example.com" (note authentication won't work without https:// except for localhost; SSO redirect, if enabled, will be this + /oidc/callback, so "https://cloud.example.com/oidc/callback")
|
||||
allowSignups: false, // If true, anyone can sign up for an account. Note that it's always possible to sign up for the first user, and they will be an admin
|
||||
enableEmailVerification: false, // If true, email verification will be required for signups (using SMTP settings below)
|
||||
enableForeverSignup: true, // If true, all signups become active for 100 years
|
||||
|
|
|
|||
1
client.ts
Normal file
1
client.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
import './static/styles.css';
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Head } from 'fresh/runtime.ts';
|
||||
import { Head } from 'fresh/runtime';
|
||||
|
||||
import { OptionalApp, User } from '/lib/types.ts';
|
||||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,6 @@ export default function ExpenseModal(
|
|||
onChange={(event) => {
|
||||
newExpenseBudget.value = event.currentTarget.value;
|
||||
}}
|
||||
placeholder='Misc'
|
||||
>
|
||||
{sortedBudgetNames.map((budget) => (
|
||||
<option value={budget} selected={newExpenseBudget.value === budget}>{budget}</option>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useSignal } from '@preact/signals';
|
||||
import { useEffect, useRef } from 'preact/hooks';
|
||||
import { Chart } from 'chart.js';
|
||||
import { Chart } from 'chart.js/auto';
|
||||
|
||||
import { formatNumber } from '/lib/utils/misc.ts';
|
||||
import { Budget, SupportedCurrencySymbol } from '/lib/types.ts';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { join } from 'std/path/join.ts';
|
||||
import { join } from '@std/path';
|
||||
|
||||
import { Directory, DirectoryFile } from '/lib/types.ts';
|
||||
import { humanFileSize, TRASH_PATH } from '/lib/utils/files.ts';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { Directory, DirectoryFile } from '/lib/types.ts';
|
||||
import { humanFileSize, TRASH_PATH } from '/lib/utils/files.ts';
|
||||
|
||||
interface ListFilesProps {
|
||||
interface ListPhotosProps {
|
||||
directories: Directory[];
|
||||
files: DirectoryFile[];
|
||||
onClickOpenRenameDirectory?: (parentPath: string, name: string) => void;
|
||||
|
|
@ -13,7 +13,7 @@ interface ListFilesProps {
|
|||
isShowingNotes?: boolean;
|
||||
}
|
||||
|
||||
export default function ListFiles(
|
||||
export default function ListPhotos(
|
||||
{
|
||||
directories,
|
||||
files,
|
||||
|
|
@ -24,7 +24,7 @@ export default function ListFiles(
|
|||
onClickDeleteDirectory,
|
||||
onClickDeleteFile,
|
||||
isShowingNotes,
|
||||
}: ListFilesProps,
|
||||
}: ListPhotosProps,
|
||||
) {
|
||||
const dateFormatOptions: Intl.DateTimeFormatOptions = {
|
||||
year: 'numeric',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Cron } from 'https://deno.land/x/croner@8.1.2/dist/croner.js';
|
||||
import { Cron } from '@hexagon/croner';
|
||||
|
||||
import { AppConfig } from '/lib/config.ts';
|
||||
import { cleanupSessions } from './sessions.ts';
|
||||
|
|
|
|||
69
deno.json
69
deno.json
|
|
@ -1,13 +1,10 @@
|
|||
{
|
||||
"lock": false,
|
||||
"tasks": {
|
||||
"check": "deno fmt --check && deno lint && deno check **/*.ts && deno check **/*.tsx",
|
||||
"cli": "echo \"import '\\$fresh/src/dev/cli.ts'\" | deno run --unstable -A -",
|
||||
"manifest": "deno task cli manifest $(pwd)",
|
||||
"start": "deno run -A --watch=static/,routes/,lib/,components/,islands/ dev.ts",
|
||||
"build": "deno run -A dev.ts build",
|
||||
"preview": "deno run -A main.ts",
|
||||
"update": "deno run -A -r https://fresh.deno.dev/update .",
|
||||
"check": "deno fmt --check && deno lint && deno check",
|
||||
"start": "START_BEWCLOUD_CRONS=true vite --host localhost --port 8000",
|
||||
"build": "vite build",
|
||||
"preview": "START_BEWCLOUD_CRONS=true deno serve -A _fresh/server.js",
|
||||
"update": "deno run -A -r jsr:@fresh/update .",
|
||||
"test": "deno test -A --check"
|
||||
},
|
||||
"fmt": {
|
||||
|
|
@ -16,13 +13,14 @@
|
|||
"indentWidth": 2,
|
||||
"singleQuote": true,
|
||||
"proseWrap": "preserve",
|
||||
"exclude": ["README.md"]
|
||||
"exclude": ["README.md", "lib/models/dav.js"]
|
||||
},
|
||||
"lint": {
|
||||
"rules": {
|
||||
"tags": ["fresh", "recommended"],
|
||||
"exclude": ["no-explicit-any", "no-empty-interface", "no-window", "no-unused-vars"]
|
||||
}
|
||||
},
|
||||
"exclude": ["lib/models/dav.js"]
|
||||
},
|
||||
"exclude": ["./_fresh/*", "./node_modules/*", "**/_fresh/*"],
|
||||
"compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "preact" },
|
||||
|
|
@ -30,28 +28,33 @@
|
|||
"imports": {
|
||||
"/": "./",
|
||||
"./": "./",
|
||||
"xml": "https://deno.land/x/xml@2.1.3/mod.ts",
|
||||
"mrmime": "https://deno.land/x/mrmime@v2.0.0/mod.ts",
|
||||
"fresh/": "https://deno.land/x/fresh@1.7.3/",
|
||||
"$fresh/": "https://deno.land/x/fresh@1.7.3/",
|
||||
"std/": "https://deno.land/std@0.224.0/",
|
||||
"$std/": "https://deno.land/std@0.224.0/",
|
||||
"postgres": "https://deno.land/x/postgres@v0.19.3/mod.ts",
|
||||
"preact": "https://esm.sh/preact@10.23.2",
|
||||
"preact/": "https://esm.sh/preact@10.23.2/",
|
||||
"@preact/signals": "https://esm.sh/*@preact/signals@1.3.0",
|
||||
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.8.0",
|
||||
"chart.js": "https://esm.sh/chart.js@4.4.9/auto",
|
||||
"otpauth": "https://esm.sh/otpauth@9.4.0",
|
||||
"qrcode": "https://esm.sh/qrcode@1.5.4",
|
||||
"openid-client": "https://esm.sh/openid-client@6.6.3",
|
||||
"@simplewebauthn/server": "jsr:@simplewebauthn/server@13.1.2",
|
||||
"@simplewebauthn/server/helpers": "jsr:@simplewebauthn/server@13.1.2/helpers",
|
||||
"@simplewebauthn/browser": "jsr:@simplewebauthn/browser@13.1.2",
|
||||
"tailwindcss": "npm:tailwindcss@3.4.17",
|
||||
"tailwindcss/": "npm:/tailwindcss@3.4.17/",
|
||||
"tailwindcss/plugin": "npm:/tailwindcss@3.4.17/plugin.js",
|
||||
"nodemailer": "npm:nodemailer@7.0.5",
|
||||
"tsdav": "https://raw.githubusercontent.com/sunsama/tsdav/cc1c5a09b64c87bbee7e5f171cfcb6748e99469e/dist/tsdav.js"
|
||||
|
||||
"fresh": "jsr:@fresh/core@2.1.1",
|
||||
"postgres": "jsr:@db/postgres@0.19.5",
|
||||
"@b-fuze/deno-dom": "jsr:@b-fuze/deno-dom@0.1.56",
|
||||
"@fresh/plugin-vite": "jsr:@fresh/plugin-vite@1.0.4",
|
||||
"@hexagon/croner": "jsr:@hexagon/croner@9.1.0",
|
||||
"@mikaelporttila/rss": "jsr:@mikaelporttila/rss@1.1.3",
|
||||
"@libs/qrcode": "jsr:@libs/qrcode@3.0.0",
|
||||
"@libs/xml": "jsr:@libs/xml@7.0.2",
|
||||
"@simplewebauthn/server": "jsr:@simplewebauthn/server@13.2.1",
|
||||
"@simplewebauthn/browser": "jsr:@simplewebauthn/browser@13.2.0",
|
||||
"@std/assert": "jsr:@std/assert@1.0.14",
|
||||
"@std/dotenv": "jsr:@std/dotenv@0.225.5",
|
||||
"@std/encoding": "jsr:@std/encoding@1.0.10",
|
||||
"@std/http": "jsr:@std/http@1.0.20",
|
||||
"@std/path": "jsr:@std/path@1.1.2",
|
||||
|
||||
"chart.js": "npm:chart.js@4.5.0",
|
||||
"mrmime": "npm:mrmime@2.0.1",
|
||||
"nodemailer": "npm:nodemailer@7.0.6",
|
||||
"openid-client": "npm:openid-client@6.8.0",
|
||||
"otpauth": "npm:otpauth@9.4.1",
|
||||
"preact": "npm:preact@10.27.2",
|
||||
"sharp": "npm:sharp@0.34.4",
|
||||
"tailwindcss": "npm:tailwindcss@4.1.13",
|
||||
"vite": "npm:vite@7.1.7",
|
||||
"@preact/signals": "npm:@preact/signals@2.3.1",
|
||||
"@tailwindcss/vite": "npm:@tailwindcss/vite@4.1.13"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8
dev.ts
8
dev.ts
|
|
@ -1,8 +0,0 @@
|
|||
#!/usr/bin/env -S deno run -A --watch=static/,routes/,lib/,components/,islands/
|
||||
|
||||
import dev from 'fresh/dev.ts';
|
||||
import config from './fresh.config.ts';
|
||||
|
||||
import 'std/dotenv/load.ts';
|
||||
|
||||
await dev(import.meta.url, './main.ts', config);
|
||||
|
|
@ -18,7 +18,7 @@ services:
|
|||
|
||||
# NOTE: If you don't want to use the CardDav/CalDav servers, you can comment/remove this service.
|
||||
radicale:
|
||||
image: tomsquest/docker-radicale:3.5.4.0
|
||||
image: tomsquest/docker-radicale:3.5.6.0
|
||||
ports:
|
||||
- 5232:5232
|
||||
init: true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
services:
|
||||
website:
|
||||
image: ghcr.io/bewcloud/bewcloud:v2.5.3
|
||||
image: ghcr.io/bewcloud/bewcloud:v3.0.0
|
||||
restart: always
|
||||
ports:
|
||||
- 127.0.0.1:8000:8000
|
||||
|
|
@ -32,7 +32,7 @@ services:
|
|||
|
||||
# NOTE: If you don't want to use the CardDav/CalDav servers, you can comment/remove this service.
|
||||
radicale:
|
||||
image: tomsquest/docker-radicale:3.5.4.0
|
||||
image: tomsquest/docker-radicale:3.5.6.0
|
||||
# NOTE: uncomment below only if you need to connect to the CardDav/CalDav servers from outside the container
|
||||
# ports:
|
||||
# - 127.0.0.1:5232:5232
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
import { defineConfig } from 'fresh/server.ts';
|
||||
import tailwind from 'fresh/plugins/tailwind.ts';
|
||||
|
||||
import { startCrons } from '/crons/index.ts';
|
||||
|
||||
const isBuildMode = Deno.args.includes('build');
|
||||
|
||||
if (!isBuildMode) {
|
||||
await startCrons();
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [tailwind()],
|
||||
});
|
||||
225
fresh.gen.ts
225
fresh.gen.ts
|
|
@ -1,225 +0,0 @@
|
|||
// DO NOT EDIT. This file is generated by Fresh.
|
||||
// This file SHOULD be checked into source version control.
|
||||
// This file is automatically updated during development when running `dev.ts`.
|
||||
|
||||
import * as $_well_known_caldav from './routes/.well-known/caldav.tsx';
|
||||
import * as $_well_known_carddav from './routes/.well-known/carddav.tsx';
|
||||
import * as $_404 from './routes/_404.tsx';
|
||||
import * as $_app from './routes/_app.tsx';
|
||||
import * as $_middleware from './routes/_middleware.tsx';
|
||||
import * as $api_auth_multi_factor_disable from './routes/api/auth/multi-factor/disable.ts';
|
||||
import * as $api_auth_multi_factor_email_setup from './routes/api/auth/multi-factor/email/setup.ts';
|
||||
import * as $api_auth_multi_factor_enable from './routes/api/auth/multi-factor/enable.ts';
|
||||
import * as $api_auth_multi_factor_passkey_begin from './routes/api/auth/multi-factor/passkey/begin.ts';
|
||||
import * as $api_auth_multi_factor_passkey_setup_begin from './routes/api/auth/multi-factor/passkey/setup-begin.ts';
|
||||
import * as $api_auth_multi_factor_passkey_setup_complete from './routes/api/auth/multi-factor/passkey/setup-complete.ts';
|
||||
import * as $api_auth_multi_factor_passkey_verify from './routes/api/auth/multi-factor/passkey/verify.ts';
|
||||
import * as $api_auth_multi_factor_totp_setup from './routes/api/auth/multi-factor/totp/setup.ts';
|
||||
import * as $api_calendar_add_event from './routes/api/calendar/add-event.tsx';
|
||||
import * as $api_calendar_add from './routes/api/calendar/add.tsx';
|
||||
import * as $api_calendar_delete_event from './routes/api/calendar/delete-event.tsx';
|
||||
import * as $api_calendar_delete from './routes/api/calendar/delete.tsx';
|
||||
import * as $api_calendar_export_events from './routes/api/calendar/export-events.tsx';
|
||||
import * as $api_calendar_import from './routes/api/calendar/import.tsx';
|
||||
import * as $api_calendar_search_events from './routes/api/calendar/search-events.tsx';
|
||||
import * as $api_calendar_update from './routes/api/calendar/update.tsx';
|
||||
import * as $api_contacts_add_addressbook from './routes/api/contacts/add-addressbook.tsx';
|
||||
import * as $api_contacts_add from './routes/api/contacts/add.tsx';
|
||||
import * as $api_contacts_delete_addressbook from './routes/api/contacts/delete-addressbook.tsx';
|
||||
import * as $api_contacts_delete from './routes/api/contacts/delete.tsx';
|
||||
import * as $api_contacts_get_addressbooks from './routes/api/contacts/get-addressbooks.tsx';
|
||||
import * as $api_contacts_get from './routes/api/contacts/get.tsx';
|
||||
import * as $api_contacts_import from './routes/api/contacts/import.tsx';
|
||||
import * as $api_dashboard_save_links from './routes/api/dashboard/save-links.tsx';
|
||||
import * as $api_dashboard_save_notes from './routes/api/dashboard/save-notes.tsx';
|
||||
import * as $api_expenses_add_budget from './routes/api/expenses/add-budget.tsx';
|
||||
import * as $api_expenses_add_expense from './routes/api/expenses/add-expense.tsx';
|
||||
import * as $api_expenses_auto_complete from './routes/api/expenses/auto-complete.tsx';
|
||||
import * as $api_expenses_delete_budget from './routes/api/expenses/delete-budget.tsx';
|
||||
import * as $api_expenses_delete_expense from './routes/api/expenses/delete-expense.tsx';
|
||||
import * as $api_expenses_export_expenses from './routes/api/expenses/export-expenses.tsx';
|
||||
import * as $api_expenses_import_expenses from './routes/api/expenses/import-expenses.tsx';
|
||||
import * as $api_expenses_update_budget from './routes/api/expenses/update-budget.tsx';
|
||||
import * as $api_expenses_update_expense from './routes/api/expenses/update-expense.tsx';
|
||||
import * as $api_files_create_directory from './routes/api/files/create-directory.tsx';
|
||||
import * as $api_files_create_share from './routes/api/files/create-share.tsx';
|
||||
import * as $api_files_delete_directory from './routes/api/files/delete-directory.tsx';
|
||||
import * as $api_files_delete_share from './routes/api/files/delete-share.tsx';
|
||||
import * as $api_files_delete from './routes/api/files/delete.tsx';
|
||||
import * as $api_files_get_directories from './routes/api/files/get-directories.tsx';
|
||||
import * as $api_files_get_share from './routes/api/files/get-share.tsx';
|
||||
import * as $api_files_get from './routes/api/files/get.tsx';
|
||||
import * as $api_files_move_directory from './routes/api/files/move-directory.tsx';
|
||||
import * as $api_files_move from './routes/api/files/move.tsx';
|
||||
import * as $api_files_rename_directory from './routes/api/files/rename-directory.tsx';
|
||||
import * as $api_files_rename from './routes/api/files/rename.tsx';
|
||||
import * as $api_files_search from './routes/api/files/search.tsx';
|
||||
import * as $api_files_update_share from './routes/api/files/update-share.tsx';
|
||||
import * as $api_files_upload from './routes/api/files/upload.tsx';
|
||||
import * as $api_news_add_feed from './routes/api/news/add-feed.tsx';
|
||||
import * as $api_news_delete_feed from './routes/api/news/delete-feed.tsx';
|
||||
import * as $api_news_import_feeds from './routes/api/news/import-feeds.tsx';
|
||||
import * as $api_news_mark_read from './routes/api/news/mark-read.tsx';
|
||||
import * as $api_news_refresh_articles from './routes/api/news/refresh-articles.tsx';
|
||||
import * as $api_notes_save from './routes/api/notes/save.tsx';
|
||||
import * as $caldav from './routes/caldav.tsx';
|
||||
import * as $calendar from './routes/calendar.tsx';
|
||||
import * as $calendar_calendarEventId_ from './routes/calendar/[calendarEventId].tsx';
|
||||
import * as $calendars from './routes/calendars.tsx';
|
||||
import * as $carddav from './routes/carddav.tsx';
|
||||
import * as $contacts from './routes/contacts.tsx';
|
||||
import * as $contacts_contactId_ from './routes/contacts/[contactId].tsx';
|
||||
import * as $dashboard from './routes/dashboard.tsx';
|
||||
import * as $dav from './routes/dav.tsx';
|
||||
import * as $expenses from './routes/expenses.tsx';
|
||||
import * as $file_share_fileShareId_ from './routes/file-share/[fileShareId].tsx';
|
||||
import * as $file_share_fileShareId_open_fileName_ from './routes/file-share/[fileShareId]/open/[fileName].tsx';
|
||||
import * as $file_share_fileShareId_verify from './routes/file-share/[fileShareId]/verify.tsx';
|
||||
import * as $files from './routes/files.tsx';
|
||||
import * as $files_open_fileName_ from './routes/files/open/[fileName].tsx';
|
||||
import * as $index from './routes/index.tsx';
|
||||
import * as $login from './routes/login.tsx';
|
||||
import * as $logout from './routes/logout.tsx';
|
||||
import * as $mfa_verify from './routes/mfa-verify.tsx';
|
||||
import * as $news from './routes/news.tsx';
|
||||
import * as $news_feeds from './routes/news/feeds.tsx';
|
||||
import * as $notes from './routes/notes.tsx';
|
||||
import * as $notes_open_fileName_ from './routes/notes/open/[fileName].tsx';
|
||||
import * as $oidc_callback from './routes/oidc/callback.tsx';
|
||||
import * as $photos from './routes/photos.tsx';
|
||||
import * as $photos_thumbnail_fileName_ from './routes/photos/thumbnail/[fileName].tsx';
|
||||
import * as $settings from './routes/settings.tsx';
|
||||
import * as $signup from './routes/signup.tsx';
|
||||
import * as $Settings from './islands/Settings.tsx';
|
||||
import * as $auth_MultiFactorAuthSettings from './islands/auth/MultiFactorAuthSettings.tsx';
|
||||
import * as $auth_PasswordlessPasskeyLogin from './islands/auth/PasswordlessPasskeyLogin.tsx';
|
||||
import * as $calendar_CalendarWrapper from './islands/calendar/CalendarWrapper.tsx';
|
||||
import * as $calendar_Calendars from './islands/calendar/Calendars.tsx';
|
||||
import * as $calendar_ViewCalendarEvent from './islands/calendar/ViewCalendarEvent.tsx';
|
||||
import * as $contacts_Contacts from './islands/contacts/Contacts.tsx';
|
||||
import * as $contacts_ViewContact from './islands/contacts/ViewContact.tsx';
|
||||
import * as $dashboard_Links from './islands/dashboard/Links.tsx';
|
||||
import * as $dashboard_Notes from './islands/dashboard/Notes.tsx';
|
||||
import * as $expenses_ExpensesWrapper from './islands/expenses/ExpensesWrapper.tsx';
|
||||
import * as $files_FilesWrapper from './islands/files/FilesWrapper.tsx';
|
||||
import * as $news_Articles from './islands/news/Articles.tsx';
|
||||
import * as $news_Feeds from './islands/news/Feeds.tsx';
|
||||
import * as $notes_Note from './islands/notes/Note.tsx';
|
||||
import * as $notes_NotesWrapper from './islands/notes/NotesWrapper.tsx';
|
||||
import * as $photos_PhotosWrapper from './islands/photos/PhotosWrapper.tsx';
|
||||
import type { Manifest } from '$fresh/server.ts';
|
||||
|
||||
const manifest = {
|
||||
routes: {
|
||||
'./routes/.well-known/caldav.tsx': $_well_known_caldav,
|
||||
'./routes/.well-known/carddav.tsx': $_well_known_carddav,
|
||||
'./routes/_404.tsx': $_404,
|
||||
'./routes/_app.tsx': $_app,
|
||||
'./routes/_middleware.tsx': $_middleware,
|
||||
'./routes/api/auth/multi-factor/disable.ts': $api_auth_multi_factor_disable,
|
||||
'./routes/api/auth/multi-factor/email/setup.ts': $api_auth_multi_factor_email_setup,
|
||||
'./routes/api/auth/multi-factor/enable.ts': $api_auth_multi_factor_enable,
|
||||
'./routes/api/auth/multi-factor/passkey/begin.ts': $api_auth_multi_factor_passkey_begin,
|
||||
'./routes/api/auth/multi-factor/passkey/setup-begin.ts': $api_auth_multi_factor_passkey_setup_begin,
|
||||
'./routes/api/auth/multi-factor/passkey/setup-complete.ts': $api_auth_multi_factor_passkey_setup_complete,
|
||||
'./routes/api/auth/multi-factor/passkey/verify.ts': $api_auth_multi_factor_passkey_verify,
|
||||
'./routes/api/auth/multi-factor/totp/setup.ts': $api_auth_multi_factor_totp_setup,
|
||||
'./routes/api/calendar/add-event.tsx': $api_calendar_add_event,
|
||||
'./routes/api/calendar/add.tsx': $api_calendar_add,
|
||||
'./routes/api/calendar/delete-event.tsx': $api_calendar_delete_event,
|
||||
'./routes/api/calendar/delete.tsx': $api_calendar_delete,
|
||||
'./routes/api/calendar/export-events.tsx': $api_calendar_export_events,
|
||||
'./routes/api/calendar/import.tsx': $api_calendar_import,
|
||||
'./routes/api/calendar/search-events.tsx': $api_calendar_search_events,
|
||||
'./routes/api/calendar/update.tsx': $api_calendar_update,
|
||||
'./routes/api/contacts/add-addressbook.tsx': $api_contacts_add_addressbook,
|
||||
'./routes/api/contacts/add.tsx': $api_contacts_add,
|
||||
'./routes/api/contacts/delete-addressbook.tsx': $api_contacts_delete_addressbook,
|
||||
'./routes/api/contacts/delete.tsx': $api_contacts_delete,
|
||||
'./routes/api/contacts/get-addressbooks.tsx': $api_contacts_get_addressbooks,
|
||||
'./routes/api/contacts/get.tsx': $api_contacts_get,
|
||||
'./routes/api/contacts/import.tsx': $api_contacts_import,
|
||||
'./routes/api/dashboard/save-links.tsx': $api_dashboard_save_links,
|
||||
'./routes/api/dashboard/save-notes.tsx': $api_dashboard_save_notes,
|
||||
'./routes/api/expenses/add-budget.tsx': $api_expenses_add_budget,
|
||||
'./routes/api/expenses/add-expense.tsx': $api_expenses_add_expense,
|
||||
'./routes/api/expenses/auto-complete.tsx': $api_expenses_auto_complete,
|
||||
'./routes/api/expenses/delete-budget.tsx': $api_expenses_delete_budget,
|
||||
'./routes/api/expenses/delete-expense.tsx': $api_expenses_delete_expense,
|
||||
'./routes/api/expenses/export-expenses.tsx': $api_expenses_export_expenses,
|
||||
'./routes/api/expenses/import-expenses.tsx': $api_expenses_import_expenses,
|
||||
'./routes/api/expenses/update-budget.tsx': $api_expenses_update_budget,
|
||||
'./routes/api/expenses/update-expense.tsx': $api_expenses_update_expense,
|
||||
'./routes/api/files/create-directory.tsx': $api_files_create_directory,
|
||||
'./routes/api/files/create-share.tsx': $api_files_create_share,
|
||||
'./routes/api/files/delete-directory.tsx': $api_files_delete_directory,
|
||||
'./routes/api/files/delete-share.tsx': $api_files_delete_share,
|
||||
'./routes/api/files/delete.tsx': $api_files_delete,
|
||||
'./routes/api/files/get-directories.tsx': $api_files_get_directories,
|
||||
'./routes/api/files/get-share.tsx': $api_files_get_share,
|
||||
'./routes/api/files/get.tsx': $api_files_get,
|
||||
'./routes/api/files/move-directory.tsx': $api_files_move_directory,
|
||||
'./routes/api/files/move.tsx': $api_files_move,
|
||||
'./routes/api/files/rename-directory.tsx': $api_files_rename_directory,
|
||||
'./routes/api/files/rename.tsx': $api_files_rename,
|
||||
'./routes/api/files/search.tsx': $api_files_search,
|
||||
'./routes/api/files/update-share.tsx': $api_files_update_share,
|
||||
'./routes/api/files/upload.tsx': $api_files_upload,
|
||||
'./routes/api/news/add-feed.tsx': $api_news_add_feed,
|
||||
'./routes/api/news/delete-feed.tsx': $api_news_delete_feed,
|
||||
'./routes/api/news/import-feeds.tsx': $api_news_import_feeds,
|
||||
'./routes/api/news/mark-read.tsx': $api_news_mark_read,
|
||||
'./routes/api/news/refresh-articles.tsx': $api_news_refresh_articles,
|
||||
'./routes/api/notes/save.tsx': $api_notes_save,
|
||||
'./routes/caldav.tsx': $caldav,
|
||||
'./routes/calendar.tsx': $calendar,
|
||||
'./routes/calendar/[calendarEventId].tsx': $calendar_calendarEventId_,
|
||||
'./routes/calendars.tsx': $calendars,
|
||||
'./routes/carddav.tsx': $carddav,
|
||||
'./routes/contacts.tsx': $contacts,
|
||||
'./routes/contacts/[contactId].tsx': $contacts_contactId_,
|
||||
'./routes/dashboard.tsx': $dashboard,
|
||||
'./routes/dav.tsx': $dav,
|
||||
'./routes/expenses.tsx': $expenses,
|
||||
'./routes/file-share/[fileShareId].tsx': $file_share_fileShareId_,
|
||||
'./routes/file-share/[fileShareId]/open/[fileName].tsx': $file_share_fileShareId_open_fileName_,
|
||||
'./routes/file-share/[fileShareId]/verify.tsx': $file_share_fileShareId_verify,
|
||||
'./routes/files.tsx': $files,
|
||||
'./routes/files/open/[fileName].tsx': $files_open_fileName_,
|
||||
'./routes/index.tsx': $index,
|
||||
'./routes/login.tsx': $login,
|
||||
'./routes/logout.tsx': $logout,
|
||||
'./routes/mfa-verify.tsx': $mfa_verify,
|
||||
'./routes/news.tsx': $news,
|
||||
'./routes/news/feeds.tsx': $news_feeds,
|
||||
'./routes/notes.tsx': $notes,
|
||||
'./routes/notes/open/[fileName].tsx': $notes_open_fileName_,
|
||||
'./routes/oidc/callback.tsx': $oidc_callback,
|
||||
'./routes/photos.tsx': $photos,
|
||||
'./routes/photos/thumbnail/[fileName].tsx': $photos_thumbnail_fileName_,
|
||||
'./routes/settings.tsx': $settings,
|
||||
'./routes/signup.tsx': $signup,
|
||||
},
|
||||
islands: {
|
||||
'./islands/Settings.tsx': $Settings,
|
||||
'./islands/auth/MultiFactorAuthSettings.tsx': $auth_MultiFactorAuthSettings,
|
||||
'./islands/auth/PasswordlessPasskeyLogin.tsx': $auth_PasswordlessPasskeyLogin,
|
||||
'./islands/calendar/CalendarWrapper.tsx': $calendar_CalendarWrapper,
|
||||
'./islands/calendar/Calendars.tsx': $calendar_Calendars,
|
||||
'./islands/calendar/ViewCalendarEvent.tsx': $calendar_ViewCalendarEvent,
|
||||
'./islands/contacts/Contacts.tsx': $contacts_Contacts,
|
||||
'./islands/contacts/ViewContact.tsx': $contacts_ViewContact,
|
||||
'./islands/dashboard/Links.tsx': $dashboard_Links,
|
||||
'./islands/dashboard/Notes.tsx': $dashboard_Notes,
|
||||
'./islands/expenses/ExpensesWrapper.tsx': $expenses_ExpensesWrapper,
|
||||
'./islands/files/FilesWrapper.tsx': $files_FilesWrapper,
|
||||
'./islands/news/Articles.tsx': $news_Articles,
|
||||
'./islands/news/Feeds.tsx': $news_Feeds,
|
||||
'./islands/notes/Note.tsx': $notes_Note,
|
||||
'./islands/notes/NotesWrapper.tsx': $notes_NotesWrapper,
|
||||
'./islands/photos/PhotosWrapper.tsx': $photos_PhotosWrapper,
|
||||
},
|
||||
baseUrl: import.meta.url,
|
||||
} satisfies Manifest;
|
||||
|
||||
export default manifest;
|
||||
|
|
@ -391,8 +391,8 @@ export default function MultiFactorAuthSettings({ methods }: MultiFactorAuthSett
|
|||
<p class='mb-4'>
|
||||
1. Scan this QR code with your authenticator app (Aegis Authenticator, Google Authenticator, etc.):
|
||||
</p>
|
||||
<section class='flex justify-center mb-4'>
|
||||
<img src={setupData.value.qrCodeUrl} alt='TOTP QR Code' class='border' />
|
||||
<section class='flex justify-center mb-4 max-w-sm mx-auto'>
|
||||
<img src={setupData.value.qrCodeUrl} alt='TOTP QR Code' class='border-8 border-white' />
|
||||
</section>
|
||||
<p class='text-sm text-gray-400 mb-4'>
|
||||
Or manually enter this secret:{' '}
|
||||
|
|
|
|||
12
lib/auth.ts
12
lib/auth.ts
|
|
@ -1,7 +1,6 @@
|
|||
import { decodeBase64Url, encodeBase64Url } from 'std/encoding/base64url.ts';
|
||||
import { decodeBase64 } from 'std/encoding/base64.ts';
|
||||
import { Cookie, getCookies, setCookie } from 'std/http/cookie.ts';
|
||||
import 'std/dotenv/load.ts';
|
||||
import { decodeBase64, decodeBase64Url, encodeBase64Url } from '@std/encoding';
|
||||
import { Cookie, getCookies, setCookie } from '@std/http';
|
||||
import '@std/dotenv/load';
|
||||
|
||||
import { generateHash, isRunningLocally } from './utils/misc.ts';
|
||||
import { User, UserSession } from './types.ts';
|
||||
|
|
@ -46,7 +45,10 @@ export async function verifyAuthJwt<T = JwtData>(key: CryptoKey, jwt: string): P
|
|||
}
|
||||
|
||||
const data = textToData(jwtParts[0] + '.' + jwtParts[1]);
|
||||
if (await crypto.subtle.verify({ name: 'HMAC' }, key, decodeBase64Url(jwtParts[2]), data) === true) {
|
||||
if (
|
||||
await crypto.subtle.verify({ name: 'HMAC' }, key, decodeBase64Url(jwtParts[2]) as unknown as ArrayBuffer, data) ===
|
||||
true
|
||||
) {
|
||||
return JSON.parse(dataToText(decodeBase64Url(jwtParts[1]))) as T;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ export class AppConfig {
|
|||
};
|
||||
|
||||
try {
|
||||
const configFromFile: Config = (await import(`${Deno.cwd()}/bewcloud.config.ts`)).default;
|
||||
const configFromFile: Config = (await import(/* @vite-ignore */ `${Deno.cwd()}/bewcloud.config.ts`)).default;
|
||||
|
||||
this.config = {
|
||||
...config,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { DOMParser, initParser } from 'https://deno.land/x/deno_dom@v0.1.45/deno-dom-wasm-noinit.ts';
|
||||
import { Feed, parseFeed } from 'https://deno.land/x/rss@1.0.0/mod.ts';
|
||||
import { DOMParser, initParser } from '@b-fuze/deno-dom/wasm-noinit';
|
||||
import { Feed, parseFeed } from '@mikaelporttila/rss';
|
||||
import { fetchUrl, fetchUrlAsGooglebot, fetchUrlWithProxy, fetchUrlWithRetries } from './utils/misc.ts';
|
||||
import { NewsFeed, NewsFeedCrawlType, NewsFeedType } from './types.ts';
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ function generateInputHtml(
|
|||
|
||||
if (type === 'select') {
|
||||
return (
|
||||
<select class='mt-1 input-field' id={`field_${name}`} name={name} type={type} {...additionalAttributes}>
|
||||
<select class='mt-1 input-field' id={`field_${name}`} name={name} {...additionalAttributes}>
|
||||
{options?.map((option) => (
|
||||
<option
|
||||
value={option.value}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Client } from 'postgres';
|
||||
import 'std/dotenv/load.ts';
|
||||
import '@std/dotenv/load';
|
||||
|
||||
const POSTGRESQL_HOST = Deno.env.get('POSTGRESQL_HOST') || '';
|
||||
const POSTGRESQL_USER = Deno.env.get('POSTGRESQL_USER') || '';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { createDAVClient } from 'tsdav';
|
||||
|
||||
import { createDAVClient } from '/lib/models/dav.js';
|
||||
import { AppConfig } from '/lib/config.ts';
|
||||
import { getColorAsHex, parseVCalendar } from '/lib/utils/calendar.ts';
|
||||
import { concurrentPromises } from '/lib/utils/misc.ts';
|
||||
|
|
@ -146,7 +145,7 @@ export class CalendarModel {
|
|||
displayName: string,
|
||||
color?: string,
|
||||
): Promise<void> {
|
||||
// Make "manual" request (https://www.rfc-editor.org/rfc/rfc4791.html#page-20) because tsdav doesn't have PROPPATCH
|
||||
// Make "manual" request (https://www.rfc-editor.org/rfc/rfc4791.html#page-20) because the dav client doesn't have PROPPATCH
|
||||
const xmlBody = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<d:proppatch xmlns:d="DAV:" xmlns:a="http://apple.com/ns/ical/">
|
||||
<d:set>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { createDAVClient } from 'tsdav';
|
||||
|
||||
import { createDAVClient } from '/lib/models/dav.js';
|
||||
import { AppConfig } from '/lib/config.ts';
|
||||
import { parseVCard } from '/lib/utils/contacts.ts';
|
||||
|
||||
|
|
|
|||
10891
lib/models/dav.js
Normal file
10891
lib/models/dav.js
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
import nodemailer from 'nodemailer';
|
||||
import 'std/dotenv/load.ts';
|
||||
import '@std/dotenv/load';
|
||||
|
||||
import { escapeHtml } from '/lib/utils/misc.ts';
|
||||
import { AppConfig } from '/lib/config.ts';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { join } from 'std/path/join.ts';
|
||||
import { resolve } from 'std/path/resolve.ts';
|
||||
import { join, resolve } from '@std/path';
|
||||
import { lookup } from 'mrmime';
|
||||
import { Cookie, getCookies, setCookie } from 'std/http/cookie.ts';
|
||||
import { Cookie, getCookies, setCookie } from '@std/http';
|
||||
|
||||
import { AppConfig } from '/lib/config.ts';
|
||||
import { Directory, DirectoryFile, FileShare } from '/lib/types.ts';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Cookie, getCookies, setCookie } from 'std/http/cookie.ts';
|
||||
import { Cookie, getCookies, setCookie } from '@std/http';
|
||||
|
||||
import { MultiFactorAuthMethod, User } from '/lib/types.ts';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { Secret, TOTP } from 'otpauth';
|
||||
import QRCode from 'qrcode';
|
||||
import { encodeBase32 } from 'std/encoding/base32.ts';
|
||||
import { decodeBase64, encodeBase64 } from 'std/encoding/base64.ts';
|
||||
import { qrcode } from '@libs/qrcode';
|
||||
import { decodeBase64, encodeBase32, encodeBase64 } from '@std/encoding';
|
||||
|
||||
import { MultiFactorAuthMethod } from '/lib/types.ts';
|
||||
import { MFA_KEY, MFA_SALT } from '/lib/auth.ts';
|
||||
|
|
@ -133,7 +132,8 @@ export class TOTPModel {
|
|||
private static async generateQRCodeDataURL(secret: string, issuer: string, accountName: string): Promise<string> {
|
||||
const totp = this.createTOTP(secret, issuer, accountName);
|
||||
const uri = totp.toString();
|
||||
return await QRCode.toDataURL(uri);
|
||||
const svgString = await qrcode(uri, { output: 'svg', border: 0 });
|
||||
return `data:image/svg+xml;base64,${encodeBase64(svgString)}`;
|
||||
}
|
||||
|
||||
private static verifyTOTPToken(secret: string, token: string, window = 1): boolean {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Feed } from 'https://deno.land/x/rss@1.0.0/mod.ts';
|
||||
import { Feed } from '@mikaelporttila/rss';
|
||||
|
||||
import Database, { sql } from '/lib/interfaces/database.ts';
|
||||
import Locker from '/lib/interfaces/locker.ts';
|
||||
|
|
@ -136,7 +136,7 @@ export class FeedModel {
|
|||
feedArticle.id;
|
||||
|
||||
// Fix relative URLs in the feeds
|
||||
if (url.startsWith('/')) {
|
||||
if (url!.startsWith('/')) {
|
||||
const feedUrl = new URL(newsFeed.feed_url);
|
||||
url = `${feedUrl.origin}${url}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { decodeBase64Url } from 'std/encoding/base64url.ts';
|
||||
import { decodeBase64Url } from '@std/encoding';
|
||||
import * as openIdClient from 'openid-client';
|
||||
import 'std/dotenv/load.ts';
|
||||
import '@std/dotenv/load';
|
||||
|
||||
import { createSessionResponse, dataToText } from '/lib/auth.ts';
|
||||
import { UserModel } from '/lib/models/user.ts';
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ export type OptionalApp = 'news' | 'notes' | 'photos' | 'expenses' | 'contacts'
|
|||
|
||||
export interface Config {
|
||||
auth: {
|
||||
/** The base URL of the application you use to access the app, i.e. "http://localhost:8000" or "https://cloud.example.com" */
|
||||
/** The base URL of the application you use to access the app, i.e. "http://localhost:8000" or "https://cloud.example.com" (note authentication won't work without https:// except for localhost; SSO redirect, if enabled, will be this + /oidc/callback, so "https://cloud.example.com/oidc/callback") */
|
||||
baseUrl: string;
|
||||
/** If true, anyone can sign up for an account. Note that it's always possible to sign up for the first user, and they will be an admin */
|
||||
allowSignups: boolean;
|
||||
|
|
@ -238,6 +238,7 @@ export interface MultiFactorAuthMethod {
|
|||
counter?: number;
|
||||
device_type?: string;
|
||||
backed_up?: boolean;
|
||||
// @ts-ignore this fails in vite/tests
|
||||
transports?: AuthenticatorTransport[];
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { assertEquals } from 'std/assert/assert_equals.ts';
|
||||
import { assertMatch } from 'std/assert/assert_match.ts';
|
||||
import { assertEquals, assertMatch } from '@std/assert';
|
||||
|
||||
import { Calendar, CalendarEvent } from '/lib/models/calendar.ts';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { assertEquals } from 'std/assert/assert_equals.ts';
|
||||
import { assertMatch } from 'std/assert/assert_match.ts';
|
||||
import { assertEquals, assertMatch } from '@std/assert';
|
||||
|
||||
import { generateVCard, getIdFromVCard, parseVCard, splitTextIntoVCards, updateVCard } from './contacts.ts';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { assertEquals } from 'std/assert/assert_equals.ts';
|
||||
import { assertEquals } from '@std/assert';
|
||||
|
||||
import { humanFileSize } from './files.ts';
|
||||
|
||||
Deno.test('that humanFileSize works', () => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { assertEquals } from 'std/assert/assert_equals.ts';
|
||||
import { assertEquals } from '@std/assert';
|
||||
|
||||
import { SupportedCurrencySymbol } from '/lib/types.ts';
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { join } from 'std/path/join.ts';
|
||||
import { join } from '@std/path';
|
||||
import { lookup } from 'mrmime';
|
||||
|
||||
export function getProperDestinationPath(url: string) {
|
||||
|
|
|
|||
22
main.ts
22
main.ts
|
|
@ -1,13 +1,15 @@
|
|||
/// <reference no-default-lib="true" />
|
||||
/// <reference lib="dom" />
|
||||
/// <reference lib="dom.iterable" />
|
||||
/// <reference lib="dom.asynciterable" />
|
||||
/// <reference lib="deno.ns" />
|
||||
import { App, staticFiles } from 'fresh';
|
||||
|
||||
import 'std/dotenv/load.ts';
|
||||
import { startCrons } from '/crons/index.ts';
|
||||
|
||||
import { start } from 'fresh/server.ts';
|
||||
import manifest from './fresh.gen.ts';
|
||||
import config from './fresh.config.ts';
|
||||
const shouldStartCrons = Deno.env.get('START_BEWCLOUD_CRONS') === 'true';
|
||||
|
||||
await start(manifest, config);
|
||||
if (shouldStartCrons) {
|
||||
await startCrons();
|
||||
}
|
||||
|
||||
export const app = new App()
|
||||
// Add static file serving middleware
|
||||
.use(staticFiles())
|
||||
// Enable file-system based routing
|
||||
.fsRoutes();
|
||||
|
|
|
|||
75
main_test.ts
75
main_test.ts
|
|
@ -1,47 +1,80 @@
|
|||
import { assert } from 'std/assert/assert.ts';
|
||||
import { assertEquals } from 'std/assert/assert_equals.ts';
|
||||
import { createHandler, ServeHandlerInfo } from 'fresh/server.ts';
|
||||
import { join } from '@std/path';
|
||||
import { assertEquals } from '@std/assert';
|
||||
import { createBuilder, type InlineConfig } from 'vite';
|
||||
|
||||
import manifest from './fresh.gen.ts';
|
||||
import config from './fresh.config.ts';
|
||||
|
||||
// @ts-ignore Deno's newer types seem to have messed this up
|
||||
const CONN_INFO: ServeHandlerInfo = {
|
||||
remoteAddr: { hostname: '127.0.0.1', port: 53496, transport: 'tcp' },
|
||||
};
|
||||
|
||||
Deno.test('Basic routes', async (testContext) => {
|
||||
const handler = await createHandler(manifest, config);
|
||||
Deno.test('Basic routes', { sanitizeResources: false, sanitizeOps: false }, async (testContext) => {
|
||||
const app = await buildFreshApp();
|
||||
const { server, address } = startTestServer(app);
|
||||
|
||||
await testContext.step('#1 GET /', async () => {
|
||||
const response = await handler(new Request('http://127.0.0.1/'), CONN_INFO);
|
||||
const response = await fetch(`${address}/`, { redirect: 'manual' });
|
||||
await response.body?.cancel();
|
||||
assertEquals(response.status, 303);
|
||||
assertEquals(response.headers.get('Location'), '/login');
|
||||
});
|
||||
|
||||
await testContext.step('#2 GET /login', async () => {
|
||||
const response = await handler(new Request('http://127.0.0.1/login'), CONN_INFO);
|
||||
const response = await fetch(`${address}/login`);
|
||||
const text = await response.text();
|
||||
assert(text.includes('bewCloud'));
|
||||
assertEquals(text.includes('bewCloud'), true);
|
||||
assertEquals(response.status, 200);
|
||||
});
|
||||
|
||||
await testContext.step('#3 GET /blah', async () => {
|
||||
const response = await handler(new Request('http://127.0.0.1/blah'), CONN_INFO);
|
||||
const response = await fetch(`${address}/blah`);
|
||||
const text = await response.text();
|
||||
assert(text.includes('404 - Page not found'));
|
||||
assertEquals(text.includes('404 - Page not found'), true);
|
||||
assertEquals(response.status, 404);
|
||||
});
|
||||
|
||||
await testContext.step('#4 POST /login', async () => {
|
||||
const formData = new FormData();
|
||||
formData.append('email', 'user@example.com');
|
||||
const request = new Request('http://127.0.0.1/login', {
|
||||
const response = await fetch(`${address}/login`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
const response = await handler(request, CONN_INFO);
|
||||
const text = await response.text();
|
||||
assert(text.includes('Error: Password is too short'));
|
||||
assertEquals(text.includes('Error: Password is too short'), true);
|
||||
assertEquals(response.status, 200);
|
||||
});
|
||||
|
||||
await testContext.step('#5 shutdown', async () => {
|
||||
await server.shutdown();
|
||||
});
|
||||
});
|
||||
|
||||
// Default Fresh build configuration
|
||||
const FRESH_BUILD_CONFIG: InlineConfig = {
|
||||
logLevel: 'error',
|
||||
root: './',
|
||||
build: { emptyOutDir: true },
|
||||
environments: {
|
||||
ssr: { build: { outDir: join('_fresh', 'server') } },
|
||||
client: { build: { outDir: join('_fresh', 'client') } },
|
||||
},
|
||||
};
|
||||
|
||||
// Helper function to create and build the Fresh app
|
||||
async function buildFreshApp(config: InlineConfig = FRESH_BUILD_CONFIG) {
|
||||
const builder = await createBuilder(config);
|
||||
await builder.buildApp();
|
||||
return await import('./_fresh/server.js');
|
||||
}
|
||||
|
||||
// Helper function to start a test server
|
||||
function startTestServer(app: {
|
||||
default: {
|
||||
fetch: (req: Request) => Promise<Response>;
|
||||
};
|
||||
}) {
|
||||
const server = Deno.serve({
|
||||
port: 8000,
|
||||
handler: app.default.fetch,
|
||||
});
|
||||
|
||||
const { port } = server.addr as Deno.NetAddr;
|
||||
const address = `http://localhost:${port}`;
|
||||
|
||||
return { server, address };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import 'std/dotenv/load.ts';
|
||||
import '@std/dotenv/load';
|
||||
|
||||
import Database, { sql } from '/lib/interfaces/database.ts';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Handler } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
||||
interface Data {}
|
||||
|
||||
export const handler: Handler<Data, FreshContextState> = () => {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = () => {
|
||||
return new Response('Redirecting...', { status: 301, headers: { 'Location': '/caldav' } });
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Handler } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
||||
interface Data {}
|
||||
|
||||
export const handler: Handler<Data, FreshContextState> = () => {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = () => {
|
||||
return new Response('Redirecting...', { status: 301, headers: { 'Location': '/carddav' } });
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
import { Head } from 'fresh/runtime.ts';
|
||||
import { PageProps } from 'fresh/server.ts';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
||||
interface Data {}
|
||||
|
||||
export default function Error404({ state }: PageProps<Data, FreshContextState>) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>404 - Page not found</title>
|
||||
</Head>
|
||||
<main>
|
||||
<section class='max-w-screen-md mx-auto flex flex-col items-center justify-center'>
|
||||
{!state.user
|
||||
? (
|
||||
<>
|
||||
<img
|
||||
class='my-6'
|
||||
src='/images/logo-white.svg'
|
||||
width='250'
|
||||
height='50'
|
||||
alt='the bewCloud logo: a stylized logo'
|
||||
/>
|
||||
<h1>404 - Page not found</h1>
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
<p class='my-4'>
|
||||
The page you were looking for doesn't exist.
|
||||
</p>
|
||||
<a href='/'>Go back home</a>
|
||||
</section>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { PageProps } from 'fresh/server.ts';
|
||||
import { PageProps } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { AppConfig } from '/lib/config.ts';
|
||||
|
|
@ -7,7 +7,7 @@ import Header from '/components/Header.tsx';
|
|||
|
||||
interface Data {}
|
||||
|
||||
export default async function App(_request: Request, { route, Component, state }: PageProps<Data, FreshContextState>) {
|
||||
export default async function App({ route, Component, state }: PageProps<Data, FreshContextState>) {
|
||||
const config = await AppConfig.getConfig();
|
||||
|
||||
const defaultTitle = config.visuals.title || 'bewCloud is a modern and simpler alternative to Nextcloud and ownCloud';
|
||||
|
|
@ -29,7 +29,7 @@ export default async function App(_request: Request, { route, Component, state }
|
|||
<link rel='manifest' href='/manifest.json' />
|
||||
</head>
|
||||
<body class='h-full'>
|
||||
<Header route={route} user={state.user} enabledApps={enabledApps} />
|
||||
<Header route={route || '/'} user={state.user} enabledApps={enabledApps} />
|
||||
<Component />
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
66
routes/_error.tsx
Normal file
66
routes/_error.tsx
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import { HttpError, PageProps } from 'fresh';
|
||||
import { Head } from 'fresh/runtime';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
||||
interface Data {}
|
||||
|
||||
export default function ErrorPage({ state, error }: PageProps<Data, FreshContextState>) {
|
||||
if (error instanceof HttpError) {
|
||||
const status = error.status;
|
||||
|
||||
// Render a 404 not found page
|
||||
if (status === 404) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>404 - Page not found</title>
|
||||
</Head>
|
||||
<main>
|
||||
<section class='max-w-screen-md mx-auto flex flex-col items-center justify-center'>
|
||||
{!state.user
|
||||
? (
|
||||
<>
|
||||
<img
|
||||
class='my-6'
|
||||
src='/images/logo-white.svg'
|
||||
width='250'
|
||||
height='50'
|
||||
alt='the bewCloud logo: a stylized logo'
|
||||
/>
|
||||
<h1>404 - Page not found</h1>
|
||||
</>
|
||||
)
|
||||
: null}
|
||||
<p class='my-4'>
|
||||
The page you were looking for doesn't exist.
|
||||
</p>
|
||||
<a href='/'>Go back home</a>
|
||||
</section>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
console.error(error);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>500 - Internal server error</title>
|
||||
</Head>
|
||||
<main>
|
||||
<section class='max-w-screen-md mx-auto flex flex-col items-center justify-center'>
|
||||
<p class='my-4'>
|
||||
An internal server error occurred.
|
||||
</p>
|
||||
<pre>
|
||||
{error?.toString() || JSON.stringify({ error }, null, 2)}
|
||||
</pre>
|
||||
<a href='/'>Go back home</a>
|
||||
</section>
|
||||
</main>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
import { FreshContext } from 'fresh/server.ts';
|
||||
import { Middleware } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { getDataFromRequest } from '/lib/auth.ts';
|
||||
|
||||
export const handler = [
|
||||
async function handleCors(request: Request, context: FreshContext<FreshContextState>) {
|
||||
export const handler: Middleware<FreshContextState>[] = [
|
||||
async function handleCors(context) {
|
||||
const request = context.req;
|
||||
|
||||
const path = new URL(request.url).pathname;
|
||||
|
||||
if (
|
||||
|
|
@ -51,7 +53,9 @@ export const handler = [
|
|||
return response;
|
||||
},
|
||||
|
||||
async function handleContextState(request: Request, context: FreshContext<FreshContextState>) {
|
||||
async function handleContextState(context) {
|
||||
const request = context.req;
|
||||
|
||||
const { user, session } = (await getDataFromRequest(request)) || {};
|
||||
|
||||
if (user) {
|
||||
|
|
@ -67,7 +71,9 @@ export const handler = [
|
|||
return response;
|
||||
},
|
||||
|
||||
async function handleLogging(request: Request, context: FreshContext<FreshContextState>) {
|
||||
async function handleLogging(context) {
|
||||
const request = context.req;
|
||||
|
||||
const response = await context.next();
|
||||
|
||||
console.info(`${new Date().toISOString()} - [${response.status}] ${request.method} ${request.url}`);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { PASSWORD_SALT } from '/lib/auth.ts';
|
||||
|
|
@ -19,8 +19,10 @@ export interface ResponseBody {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { UserModel } from '/lib/models/user.ts';
|
||||
|
|
@ -16,8 +16,8 @@ export interface ResponseBody {
|
|||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { MultiFactorAuthModel } from '/lib/models/multi-factor-auth.ts';
|
||||
|
|
@ -18,8 +18,10 @@ export interface ResponseBody {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/server';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
|
@ -20,8 +20,10 @@ export interface ResponseBody {
|
|||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
const isMultiFactorAuthEnabled = await AppConfig.isMultiFactorAuthEnabled();
|
||||
|
||||
if (!isMultiFactorAuthEnabled) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
import { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/server';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
|
@ -19,8 +19,8 @@ export interface ResponseBody {
|
|||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
import { isoBase64URL } from '@simplewebauthn/server/helpers';
|
||||
import { RegistrationResponseJSON } from '@simplewebauthn/server';
|
||||
|
||||
|
|
@ -18,8 +18,10 @@ export interface ResponseBody {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
import { AuthenticationResponseJSON } from '@simplewebauthn/server';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
|
|
@ -19,8 +19,10 @@ export interface ResponseBody {
|
|||
error?: string;
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
const isMultiFactorAuthEnabled = await AppConfig.isMultiFactorAuthEnabled();
|
||||
|
||||
if (!isMultiFactorAuthEnabled) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { UserModel } from '/lib/models/user.ts';
|
||||
|
|
@ -19,8 +19,8 @@ export interface ResponseBody {
|
|||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<unknown, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<unknown, FreshContextState> = {
|
||||
async POST(context) {
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { CalendarEvent, CalendarEventModel, CalendarModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -22,8 +22,10 @@ export interface ResponseBody {
|
|||
newCalendarEvents: CalendarEvent[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Calendar, CalendarModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
newCalendars: Calendar[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { CalendarEvent, CalendarEventModel, CalendarModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -19,8 +19,10 @@ export interface ResponseBody {
|
|||
newCalendarEvents: CalendarEvent[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Calendar, CalendarModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
newCalendars: Calendar[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { CalendarEvent, CalendarEventModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
calendarEvents: CalendarEvent[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { CalendarEvent, CalendarEventModel, CalendarModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -20,8 +20,10 @@ export interface ResponseBody {
|
|||
newCalendarEvents: CalendarEvent[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { CalendarEvent, CalendarEventModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
matchingCalendarEvents: CalendarEvent[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Calendar, CalendarModel } from '/lib/models/calendar.ts';
|
||||
|
|
@ -19,8 +19,10 @@ export interface ResponseBody {
|
|||
newCalendars: Calendar[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { AddressBook, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
addressBooks: AddressBook[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Contact, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -17,8 +17,10 @@ export interface ResponseBody {
|
|||
contacts: Contact[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { AddressBook, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
addressBooks: AddressBook[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Contact, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
contacts: Contact[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { AddressBook, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -12,8 +12,10 @@ export interface ResponseBody {
|
|||
addressBooks: AddressBook[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Contact, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
contacts: Contact[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { Contact, ContactModel } from '/lib/models/contacts.ts';
|
||||
|
|
@ -17,8 +17,10 @@ export interface ResponseBody {
|
|||
contacts: Contact[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { DashboardLink, FreshContextState } from '/lib/types.ts';
|
||||
import { DashboardModel } from '/lib/models/dashboard.ts';
|
||||
|
|
@ -13,8 +13,10 @@ export interface ResponseBody {
|
|||
success: boolean;
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { DashboardModel } from '/lib/models/dashboard.ts';
|
||||
|
|
@ -13,8 +13,10 @@ export interface ResponseBody {
|
|||
success: boolean;
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -17,8 +17,10 @@ export interface ResponseBody {
|
|||
newBudgets: Budget[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, Expense, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel, ExpenseModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -20,8 +20,10 @@ export interface ResponseBody {
|
|||
newBudgets: Budget[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FreshContextState } from '/lib/types.ts';
|
||||
import { ExpenseModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
suggestions: string[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
newBudgets: Budget[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, Expense, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel, ExpenseModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -16,8 +16,10 @@ export interface ResponseBody {
|
|||
newBudgets: Budget[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, Expense, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel, ExpenseModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -15,8 +15,8 @@ export interface ResponseBody {
|
|||
};
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, Expense, FreshContextState } from '/lib/types.ts';
|
||||
import { concurrentPromises } from '/lib/utils/misc.ts';
|
||||
|
|
@ -19,8 +19,10 @@ export interface ResponseBody {
|
|||
newExpenses: Expense[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -18,8 +18,10 @@ export interface ResponseBody {
|
|||
newBudgets: Budget[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Budget, Expense, FreshContextState } from '/lib/types.ts';
|
||||
import { BudgetModel, ExpenseModel } from '/lib/models/expenses.ts';
|
||||
|
|
@ -21,8 +21,10 @@ export interface ResponseBody {
|
|||
newBudgets: Budget[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel } from '/lib/models/files.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
newDirectories: Directory[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, DirectoryFile, FileShare, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel, FileModel, FileShareModel, getPathInfo } from '/lib/models/files.ts';
|
||||
|
|
@ -21,8 +21,10 @@ export interface ResponseBody {
|
|||
createdFileShareId: string;
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel } from '/lib/models/files.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
newDirectories: Directory[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel, FileModel, FileShareModel } from '/lib/models/files.ts';
|
||||
|
|
@ -17,8 +17,10 @@ export interface ResponseBody {
|
|||
newDirectories: Directory[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { FileModel } from '/lib/models/files.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
newFiles: DirectoryFile[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel } from '/lib/models/files.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
directories: Directory[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { FileShare, FreshContextState } from '/lib/types.ts';
|
||||
import { FileShareModel } from '/lib/models/files.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
fileShare: FileShare;
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { FileModel } from '/lib/models/files.ts';
|
||||
|
|
@ -14,8 +14,10 @@ export interface ResponseBody {
|
|||
files: DirectoryFile[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel } from '/lib/models/files.ts';
|
||||
|
|
@ -16,8 +16,10 @@ export interface ResponseBody {
|
|||
newDirectories: Directory[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { FileModel } from '/lib/models/files.ts';
|
||||
|
|
@ -16,8 +16,10 @@ export interface ResponseBody {
|
|||
newFiles: DirectoryFile[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, FreshContextState } from '/lib/types.ts';
|
||||
import { DirectoryModel } from '/lib/models/files.ts';
|
||||
|
|
@ -16,8 +16,10 @@ export interface ResponseBody {
|
|||
newDirectories: Directory[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { FileModel } from '/lib/models/files.ts';
|
||||
|
|
@ -16,8 +16,10 @@ export interface ResponseBody {
|
|||
newFiles: DirectoryFile[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Handlers } from 'fresh/server.ts';
|
||||
import { RouteHandler } from 'fresh';
|
||||
|
||||
import { Directory, DirectoryFile, FreshContextState } from '/lib/types.ts';
|
||||
import { searchFilesAndDirectories } from '/lib/models/files.ts';
|
||||
|
|
@ -15,8 +15,10 @@ export interface ResponseBody {
|
|||
files: DirectoryFile[];
|
||||
}
|
||||
|
||||
export const handler: Handlers<Data, FreshContextState> = {
|
||||
async POST(request, context) {
|
||||
export const handler: RouteHandler<Data, FreshContextState> = {
|
||||
async POST(context) {
|
||||
const request = context.req;
|
||||
|
||||
if (!context.state.user) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue