race condition security patch
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import type { User } from '$lib/models/user';
|
import type { User } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
import { getPb } from '$lib/pocketbase';
|
||||||
import { currentUser } from '$lib/stores/user_store';
|
import { currentUser } from '$lib/stores/user_store';
|
||||||
|
|
||||||
|
const pb = getPb();
|
||||||
pb.authStore.loadFromCookie(document.cookie)
|
pb.authStore.loadFromCookie(document.cookie)
|
||||||
pb.authStore.onChange(() => {
|
pb.authStore.onChange(() => {
|
||||||
currentUser.set(pb.authStore.record as User)
|
currentUser.set(pb.authStore.record as User)
|
||||||
const secure = location.protocol === "https:"
|
const secure = location.protocol === "https:"
|
||||||
document.cookie = pb.authStore.exportToCookie({ httpOnly: false, secure: secure, sameSite: "Lax" })
|
document.cookie = pb.authStore.exportToCookie({ httpOnly: false, secure: secure, sameSite: "Lax" })
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { env } from '$env/dynamic/private'
|
|||||||
import { env as envPub } from '$env/dynamic/public'
|
import { env as envPub } from '$env/dynamic/public'
|
||||||
import type { Settings } from '$lib/models/settings'
|
import type { Settings } from '$lib/models/settings'
|
||||||
|
|
||||||
import { pb } from '$lib/pocketbase'
|
import PocketBase from 'pocketbase'
|
||||||
import { isRouteProtected } from '$lib/util/authorization_util'
|
import { isRouteProtected } from '$lib/util/authorization_util'
|
||||||
import { json, redirect, text, type Handle } from '@sveltejs/kit'
|
import { json, redirect, text, type Handle } from '@sveltejs/kit'
|
||||||
import { sequence } from '@sveltejs/kit/hooks'
|
import { sequence } from '@sveltejs/kit/hooks'
|
||||||
@@ -49,6 +49,7 @@ function isFormContentType(request: Request) {
|
|||||||
|
|
||||||
|
|
||||||
const auth: Handle = async ({ event, resolve }) => {
|
const auth: Handle = async ({ event, resolve }) => {
|
||||||
|
const pb = new PocketBase(envPub.PUBLIC_POCKETBASE_URL)
|
||||||
// load the store data from the request cookie string
|
// load the store data from the request cookie string
|
||||||
pb.authStore.loadFromCookie(event.request.headers.get('cookie') || '')
|
pb.authStore.loadFromCookie(event.request.headers.get('cookie') || '')
|
||||||
|
|
||||||
@@ -80,8 +81,7 @@ const auth: Handle = async ({ event, resolve }) => {
|
|||||||
meiliApiKey = pb.authStore.record.token
|
meiliApiKey = pb.authStore.record.token
|
||||||
settings = await pb.collection('settings').getFirstListItem<Settings>(`user="${pb.authStore.record.id}"`, { requestKey: null })
|
settings = await pb.collection('settings').getFirstListItem<Settings>(`user="${pb.authStore.record.id}"`, { requestKey: null })
|
||||||
} else {
|
} else {
|
||||||
const r = await event.fetch(pb.buildURL("/public/search/token"));
|
const response = await pb.send("/public/search/token", { method: "GET", fetch: event.fetch });
|
||||||
const response = await r.json();
|
|
||||||
meiliApiKey = response.token;
|
meiliApiKey = response.token;
|
||||||
}
|
}
|
||||||
const ms = new MeiliSearch({ host: env.MEILI_URL, apiKey: meiliApiKey });
|
const ms = new MeiliSearch({ host: env.MEILI_URL, apiKey: meiliApiKey });
|
||||||
@@ -103,7 +103,7 @@ const auth: Handle = async ({ event, resolve }) => {
|
|||||||
const response = await resolve(event)
|
const response = await resolve(event)
|
||||||
|
|
||||||
// send back the default 'pb_auth' cookie to the client with the latest store state
|
// send back the default 'pb_auth' cookie to the client with the latest store state
|
||||||
const secure = event.url.protocol === "https:"
|
const secure = event.url.protocol === "https:"
|
||||||
|
|
||||||
response.headers.set(
|
response.headers.set(
|
||||||
'set-cookie',
|
'set-cookie',
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { afterNavigate, goto } from "$app/navigation";
|
import { afterNavigate, goto } from "$app/navigation";
|
||||||
|
import { page } from "$app/state";
|
||||||
import LogoText from "$lib/components/logo/logo_text.svelte";
|
import LogoText from "$lib/components/logo/logo_text.svelte";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { theme, toggleTheme } from "$lib/stores/theme_store";
|
import { theme, toggleTheme } from "$lib/stores/theme_store";
|
||||||
import { currentUser, logout } from "$lib/stores/user_store";
|
import { currentUser, logout } from "$lib/stores/user_store";
|
||||||
import { getFileURL } from "$lib/util/file_util";
|
import { getFileURL } from "$lib/util/file_util";
|
||||||
|
import type { AuthRecord } from "pocketbase";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { backInOut, cubicOut } from "svelte/easing";
|
import { backInOut, cubicOut } from "svelte/easing";
|
||||||
|
import { Tween } from "svelte/motion";
|
||||||
import Drawer from "./base/drawer.svelte";
|
import Drawer from "./base/drawer.svelte";
|
||||||
import Dropdown from "./base/dropdown.svelte";
|
import Dropdown from "./base/dropdown.svelte";
|
||||||
import LogoTextLight from "./logo/logo_text_light.svelte";
|
import LogoTextLight from "./logo/logo_text_light.svelte";
|
||||||
import NotificationDropdown from "./notification/notification_dropdown.svelte";
|
import NotificationDropdown from "./notification/notification_dropdown.svelte";
|
||||||
import { browser } from "$app/environment";
|
|
||||||
import { page } from "$app/state";
|
|
||||||
import { Tween } from "svelte/motion";
|
|
||||||
import UrlImportModal from "./settings/url_import_modal.svelte";
|
import UrlImportModal from "./settings/url_import_modal.svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
user: AuthRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { user }: Props = $props();
|
||||||
|
|
||||||
let navBarItems = [
|
let navBarItems = [
|
||||||
{ text: "Home", value: "/" },
|
{ text: "Home", value: "/" },
|
||||||
{ text: $_("trail", { values: { n: 2 } }), value: "/trails" },
|
{ text: $_("trail", { values: { n: 2 } }), value: "/trails" },
|
||||||
@@ -107,8 +112,6 @@
|
|||||||
urlImportModal.openModal();
|
urlImportModal.openModal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = $derived(browser ? $currentUser : pb.authStore.record);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Drawer bind:open={drawerOpen}>
|
<Drawer bind:open={drawerOpen}>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { List } from "$lib/models/list";
|
import type { List } from "$lib/models/list";
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import type { User, UserAnonymous } from "$lib/models/user";
|
import type { UserAnonymous } from "$lib/models/user";
|
||||||
import { pb } from "$lib/pocketbase";
|
import { currentUser, users_show } from "$lib/stores/user_store";
|
||||||
import { users_show } from "$lib/stores/user_store";
|
|
||||||
import { getFileURL } from "$lib/util/file_util";
|
import { getFileURL } from "$lib/util/file_util";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { fly, slide } from "svelte/transition";
|
import { fly } from "svelte/transition";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
subject: Trail | List;
|
subject: Trail | List;
|
||||||
@@ -16,12 +15,15 @@
|
|||||||
|
|
||||||
let { subject, large = false, type }: Props = $props();
|
let { subject, large = false, type }: Props = $props();
|
||||||
|
|
||||||
const shareData = type == "trail" ? (subject as Trail).expand?.trail_share_via_trail : (subject as List).expand?.list_share_via_list
|
const shareData =
|
||||||
|
type == "trail"
|
||||||
|
? (subject as Trail).expand?.trail_share_via_trail
|
||||||
|
: (subject as List).expand?.list_share_via_list;
|
||||||
|
|
||||||
let showInfo: boolean = $state(false);
|
let showInfo: boolean = $state(false);
|
||||||
let loading: boolean = $state(false);
|
let loading: boolean = $state(false);
|
||||||
let infoLoaded: boolean = $state(false);
|
let infoLoaded: boolean = $state(false);
|
||||||
let subjectIsOwned: boolean = subject.author == pb.authStore.record?.id;
|
let subjectIsOwned: boolean = subject.author == $currentUser?.id;
|
||||||
let author: UserAnonymous | undefined = $state();
|
let author: UserAnonymous | undefined = $state();
|
||||||
|
|
||||||
async function fetchInfo() {
|
async function fetchInfo() {
|
||||||
@@ -57,8 +59,9 @@
|
|||||||
{#if showInfo}
|
{#if showInfo}
|
||||||
<ul
|
<ul
|
||||||
class="menu absolute z-10 top-8 bg-menu-background border border-input-border rounded-xl shadow-md overflow-hidden p-3 space-y-3 text-content -translate-x-3/4"
|
class="menu absolute z-10 top-8 bg-menu-background border border-input-border rounded-xl shadow-md overflow-hidden p-3 space-y-3 text-content -translate-x-3/4"
|
||||||
in:fly={{y: -10, duration: 150}} out:fly={{y: -10, duration: 150}}
|
in:fly={{ y: -10, duration: 150 }}
|
||||||
>
|
out:fly={{ y: -10, duration: 150 }}
|
||||||
|
>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
<div class="spinner spinner-dark"></div>
|
<div class="spinner spinner-dark"></div>
|
||||||
{:else if infoLoaded && shareData}
|
{:else if infoLoaded && shareData}
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createBubbler } from "svelte/legacy";
|
|
||||||
|
|
||||||
const bubble = createBubbler();
|
|
||||||
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
||||||
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { theme } from "$lib/stores/theme_store";
|
import { theme } from "$lib/stores/theme_store";
|
||||||
|
import { currentUser } from "$lib/stores/user_store";
|
||||||
import { getFileURL, isVideoURL } from "$lib/util/file_util";
|
import { getFileURL, isVideoURL } from "$lib/util/file_util";
|
||||||
import {
|
import {
|
||||||
formatDistance,
|
formatDistance,
|
||||||
@@ -14,7 +12,6 @@
|
|||||||
formatTimeHHMM,
|
formatTimeHHMM,
|
||||||
} from "$lib/util/format_util";
|
} from "$lib/util/format_util";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import ShareInfo from "../share_info.svelte";
|
|
||||||
import type { MouseEventHandler } from "svelte/elements";
|
import type { MouseEventHandler } from "svelte/elements";
|
||||||
import Chip from "../base/chip.svelte";
|
import Chip from "../base/chip.svelte";
|
||||||
|
|
||||||
@@ -75,13 +72,13 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if (trail.public || trailIsShared) && pb.authStore.record}
|
{#if (trail.public || trailIsShared) && $currentUser}
|
||||||
<div
|
<div
|
||||||
class="flex absolute top-4 right-4 {trail.public && trailIsShared
|
class="flex absolute top-4 right-4 {trail.public && trailIsShared
|
||||||
? 'w-14'
|
? 'w-14'
|
||||||
: 'w-8'} h-8 rounded-full items-center justify-center bg-background text-content"
|
: 'w-8'} h-8 rounded-full items-center justify-center bg-background text-content"
|
||||||
>
|
>
|
||||||
{#if trail.public && pb.authStore.record}
|
{#if trail.public && $currentUser}
|
||||||
<span
|
<span
|
||||||
class="tooltip"
|
class="tooltip"
|
||||||
class:mr-2={trail.public && trailIsShared}
|
class:mr-2={trail.public && trailIsShared}
|
||||||
|
|||||||
@@ -9,18 +9,17 @@
|
|||||||
} from "$lib/stores/list_store";
|
} from "$lib/stores/list_store";
|
||||||
import { show_toast } from "$lib/stores/toast_store.svelte";
|
import { show_toast } from "$lib/stores/toast_store.svelte";
|
||||||
import { trails_delete } from "$lib/stores/trail_store";
|
import { trails_delete } from "$lib/stores/trail_store";
|
||||||
|
import { currentUser } from "$lib/stores/user_store";
|
||||||
|
import { getFileURL, saveAs } from "$lib/util/file_util";
|
||||||
import { trail2gpx } from "$lib/util/gpx_util";
|
import { trail2gpx } from "$lib/util/gpx_util";
|
||||||
import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
import { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||||
|
import JSZip from "jszip";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import Dropdown, { type DropdownItem } from "../base/dropdown.svelte";
|
import Dropdown, { type DropdownItem } from "../base/dropdown.svelte";
|
||||||
import ConfirmModal from "../confirm_modal.svelte";
|
import ConfirmModal from "../confirm_modal.svelte";
|
||||||
import ListSelectModal from "../list/list_select_modal.svelte";
|
import ListSelectModal from "../list/list_select_modal.svelte";
|
||||||
import TrailExportModal from "./trail_export_modal.svelte";
|
import TrailExportModal from "./trail_export_modal.svelte";
|
||||||
import JSZip from "jszip";
|
|
||||||
import { getFileURL, saveAs } from "$lib/util/file_util";
|
|
||||||
import TrailShareModal from "./trail_share_modal.svelte";
|
import TrailShareModal from "./trail_share_modal.svelte";
|
||||||
import { currentUser } from "$lib/stores/user_store";
|
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
trail: Trail;
|
trail: Trail;
|
||||||
@@ -62,10 +61,10 @@
|
|||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
{ text: $_("print"), value: "print", icon: "print" },
|
{ text: $_("print"), value: "print", icon: "print" },
|
||||||
...(trail.author != pb.authStore.record?.id
|
...(trail.author != $currentUser?.id
|
||||||
? []
|
? []
|
||||||
: [{ text: $_("add-to-list"), value: "list", icon: "bookmark" }]),
|
: [{ text: $_("add-to-list"), value: "list", icon: "bookmark" }]),
|
||||||
...(trail.author != pb.authStore.record?.id
|
...(trail.author != $currentUser?.id
|
||||||
? []
|
? []
|
||||||
: [{ text: $_("share"), value: "share", icon: "share" }]),
|
: [{ text: $_("share"), value: "share", icon: "share" }]),
|
||||||
...(allowEdit
|
...(allowEdit
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Category } from "$lib/models/category";
|
import type { Category } from "$lib/models/category";
|
||||||
import type { TrailFilter } from "$lib/models/trail";
|
import type { TrailFilter } from "$lib/models/trail";
|
||||||
import { country_codes } from "$lib/util/country_code_util";
|
import { searchLocations } from "$lib/stores/search_store";
|
||||||
|
import { tags_index } from "$lib/stores/tag_store";
|
||||||
import { formatDistance, formatElevation } from "$lib/util/format_util";
|
import { formatDistance, formatElevation } from "$lib/util/format_util";
|
||||||
|
import { getIconForLocation } from "$lib/util/icon_util";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { slide } from "svelte/transition";
|
import { slide } from "svelte/transition";
|
||||||
|
import Combobox, { type ComboboxItem } from "../base/combobox.svelte";
|
||||||
import Datepicker from "../base/datepicker.svelte";
|
import Datepicker from "../base/datepicker.svelte";
|
||||||
import DoubleSlider from "../base/double_slider.svelte";
|
import DoubleSlider from "../base/double_slider.svelte";
|
||||||
import MultiSelect from "../base/multi_select.svelte";
|
import MultiSelect from "../base/multi_select.svelte";
|
||||||
@@ -14,12 +17,7 @@
|
|||||||
import type { SelectItem } from "../base/select.svelte";
|
import type { SelectItem } from "../base/select.svelte";
|
||||||
import Slider from "../base/slider.svelte";
|
import Slider from "../base/slider.svelte";
|
||||||
import UserSearch from "../user_search.svelte";
|
import UserSearch from "../user_search.svelte";
|
||||||
import { pb } from "$lib/pocketbase";
|
import { currentUser } from "$lib/stores/user_store";
|
||||||
import { searchLocations } from "$lib/stores/search_store";
|
|
||||||
import { getIconForLocation } from "$lib/util/icon_util";
|
|
||||||
import { tags_index } from "$lib/stores/tag_store";
|
|
||||||
import Combobox, { type ComboboxItem } from "../base/combobox.svelte";
|
|
||||||
import { T } from "@threlte/core";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
categories: Category[];
|
categories: Category[];
|
||||||
@@ -199,7 +197,7 @@
|
|||||||
></Combobox>
|
></Combobox>
|
||||||
<hr class="my-4 border-separator" />
|
<hr class="my-4 border-separator" />
|
||||||
|
|
||||||
{#if pb.authStore.record}
|
{#if $currentUser}
|
||||||
<UserSearch
|
<UserSearch
|
||||||
onclick={(item) => setAuthorFilter(item)}
|
onclick={(item) => setAuthorFilter(item)}
|
||||||
onclear={() => {
|
onclear={() => {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
import { browser } from "$app/environment";
|
import { browser } from "$app/environment";
|
||||||
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
||||||
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { theme } from "$lib/stores/theme_store";
|
import { theme } from "$lib/stores/theme_store";
|
||||||
import { show_toast } from "$lib/stores/toast_store.svelte";
|
import { show_toast } from "$lib/stores/toast_store.svelte";
|
||||||
import * as M from "maplibre-gl";
|
import * as M from "maplibre-gl";
|
||||||
@@ -31,6 +30,7 @@
|
|||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import Button from "../base/button.svelte";
|
import Button from "../base/button.svelte";
|
||||||
|
import Chip from "../base/chip.svelte";
|
||||||
import SkeletonNotificationCard from "../base/skeleton_notification_card.svelte";
|
import SkeletonNotificationCard from "../base/skeleton_notification_card.svelte";
|
||||||
import Textarea from "../base/textarea.svelte";
|
import Textarea from "../base/textarea.svelte";
|
||||||
import CommentCard from "../comment/comment_card.svelte";
|
import CommentCard from "../comment/comment_card.svelte";
|
||||||
@@ -42,7 +42,6 @@
|
|||||||
import SummitLogTable from "../summit_log/summit_log_table.svelte";
|
import SummitLogTable from "../summit_log/summit_log_table.svelte";
|
||||||
import MapWithElevationMaplibre from "./map_with_elevation_maplibre.svelte";
|
import MapWithElevationMaplibre from "./map_with_elevation_maplibre.svelte";
|
||||||
import TrailTimeline from "./trail_timeline.svelte";
|
import TrailTimeline from "./trail_timeline.svelte";
|
||||||
import Chip from "../base/chip.svelte";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
initTrail: Trail;
|
initTrail: Trail;
|
||||||
@@ -63,7 +62,7 @@
|
|||||||
const tabs = [
|
const tabs = [
|
||||||
$_("summit-book"),
|
$_("summit-book"),
|
||||||
$_("photos"),
|
$_("photos"),
|
||||||
...(pb.authStore.record ? [$_("comment", { values: { n: 2 } })] : []),
|
...($currentUser ? [$_("comment", { values: { n: 2 } })] : []),
|
||||||
];
|
];
|
||||||
|
|
||||||
const trailIsShared =
|
const trailIsShared =
|
||||||
@@ -234,13 +233,13 @@
|
|||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if (trail.public || trailIsShared) && pb.authStore.record}
|
{#if (trail.public || trailIsShared) && $currentUser}
|
||||||
<div
|
<div
|
||||||
class="flex {trail.public && trailIsShared
|
class="flex {trail.public && trailIsShared
|
||||||
? 'w-16'
|
? 'w-16'
|
||||||
: 'w-8'} h-8 rounded-full items-center"
|
: 'w-8'} h-8 rounded-full items-center"
|
||||||
>
|
>
|
||||||
{#if trail.public && pb.authStore.record}
|
{#if trail.public && $currentUser}
|
||||||
<span
|
<span
|
||||||
class:tooltip={mode != "map"}
|
class:tooltip={mode != "map"}
|
||||||
class:mr-3={trail.public && trailIsShared}
|
class:mr-3={trail.public && trailIsShared}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
import emptyStateTrailDark from "$lib/assets/svgs/empty_states/empty_state_trail_dark.svg";
|
||||||
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
import emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { theme } from "$lib/stores/theme_store";
|
import { theme } from "$lib/stores/theme_store";
|
||||||
|
import { currentUser } from "$lib/stores/user_store";
|
||||||
import { getFileURL, isVideoURL } from "$lib/util/file_util";
|
import { getFileURL, isVideoURL } from "$lib/util/file_util";
|
||||||
import {
|
import {
|
||||||
formatDistance,
|
formatDistance,
|
||||||
@@ -12,7 +12,6 @@
|
|||||||
} from "$lib/util/format_util";
|
} from "$lib/util/format_util";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import ShareInfo from "../share_info.svelte";
|
import ShareInfo from "../share_info.svelte";
|
||||||
import Chip from "../base/chip.svelte";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
trail: Trail;
|
trail: Trail;
|
||||||
@@ -55,7 +54,7 @@
|
|||||||
<h4 class="font-semibold text-lg">
|
<h4 class="font-semibold text-lg">
|
||||||
{trail.name}
|
{trail.name}
|
||||||
</h4>
|
</h4>
|
||||||
{#if trail.public && pb.authStore.record}
|
{#if trail.public && $currentUser}
|
||||||
<span class="tooltip ml-3" data-title={$_("public")}>
|
<span class="tooltip ml-3" data-title={$_("public")}>
|
||||||
<i class="fa fa-globe"></i>
|
<i class="fa fa-globe"></i>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { browser } from '$app/environment'
|
import { browser } from '$app/environment';
|
||||||
import { pb } from '$lib/pocketbase'
|
import { getPb } from '$lib/pocketbase';
|
||||||
import { currentUser } from '$lib/stores/user_store'
|
import { init, register } from 'svelte-i18n';
|
||||||
import { init, register } from 'svelte-i18n'
|
|
||||||
import { get } from 'svelte/store'
|
|
||||||
|
|
||||||
const defaultLocale = 'en'
|
const defaultLocale = 'en'
|
||||||
|
|
||||||
@@ -18,5 +16,5 @@ register('zh', () => import('./locales/zh.json'))
|
|||||||
|
|
||||||
init({
|
init({
|
||||||
fallbackLocale: defaultLocale,
|
fallbackLocale: defaultLocale,
|
||||||
initialLocale: browser ? pb.authStore.record?.language ?? window.navigator.language : defaultLocale,
|
initialLocale: browser ? getPb().authStore.record?.language ?? window.navigator.language : defaultLocale,
|
||||||
})
|
})
|
||||||
@@ -1,8 +1,15 @@
|
|||||||
|
import { browser } from '$app/environment';
|
||||||
import { env } from '$env/dynamic/public'
|
import { env } from '$env/dynamic/public'
|
||||||
import PocketBase from 'pocketbase'
|
import PocketBase from 'pocketbase'
|
||||||
|
|
||||||
export function createInstance() {
|
let pb: PocketBase;
|
||||||
return new PocketBase(env.PUBLIC_POCKETBASE_URL)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const pb = createInstance()
|
export function getPb(): PocketBase {
|
||||||
|
if(!browser) {
|
||||||
|
throw Error("Only available client side!")
|
||||||
|
}
|
||||||
|
if (!pb) {
|
||||||
|
pb = new PocketBase(env.PUBLIC_POCKETBASE_URL);
|
||||||
|
}
|
||||||
|
return pb;
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Comment } from "$lib/models/comment";
|
import { Comment } from "$lib/models/comment";
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import { type ListResult } from "pocketbase";
|
import { type ListResult } from "pocketbase";
|
||||||
import { writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
import { currentUser } from "./user_store";
|
||||||
|
|
||||||
export const comments: Writable<Comment[]> = writable([])
|
export const comments: Writable<Comment[]> = writable([])
|
||||||
|
|
||||||
@@ -28,11 +28,12 @@ export async function comments_index(trail: Trail) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function comments_create(comment: Comment) {
|
export async function comments_create(comment: Comment) {
|
||||||
if (!pb.authStore.record) {
|
const user = get(currentUser)
|
||||||
throw new Error("Unauthenticated");
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
}
|
}
|
||||||
|
|
||||||
comment.author = pb.authStore.record!.id;
|
comment.author = user.authStore.record!.id;
|
||||||
|
|
||||||
let r = await fetch('/api/v1/comment', {
|
let r = await fetch('/api/v1/comment', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { Integration } from "$lib/models/integration";
|
import { Integration } from "$lib/models/integration";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import { type ListResult } from "pocketbase";
|
import { type ListResult } from "pocketbase";
|
||||||
import { writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
import { currentUser } from "./user_store";
|
||||||
|
|
||||||
export const integrations: Writable<Integration[]> = writable([])
|
export const integrations: Writable<Integration[]> = writable([])
|
||||||
|
|
||||||
@@ -25,11 +25,12 @@ export async function integrations_index(f: (url: RequestInfo | URL, config?: Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function integrations_create(integration: Integration) {
|
export async function integrations_create(integration: Integration) {
|
||||||
if (!pb.authStore.record) {
|
const user = get(currentUser)
|
||||||
throw new Error("Unauthenticated");
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
}
|
}
|
||||||
|
|
||||||
integration.user = pb.authStore.record!.id;
|
integration.user = user.id;
|
||||||
|
|
||||||
let r = await fetch('/api/v1/integration', {
|
let r = await fetch('/api/v1/integration', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import { List, type ListFilter, ExpandType, ExpandTypeToString } from "$lib/models/list";
|
import { ExpandType, ExpandTypeToString, List, type ListFilter } from "$lib/models/list";
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { type ListResult } from "pocketbase";
|
|
||||||
import { writable, type Writable } from "svelte/store";
|
|
||||||
import { fetchGPX } from "./trail_store";
|
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import type { Hits } from "meilisearch";
|
import type { Hits } from "meilisearch";
|
||||||
|
import { type AuthRecord, type ListResult } from "pocketbase";
|
||||||
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
import { fetchGPX } from "./trail_store";
|
||||||
|
import { currentUser } from "./user_store";
|
||||||
|
|
||||||
let lists: List[] = []
|
let lists: List[] = []
|
||||||
export const list: Writable<List | null> = writable(null)
|
export const list: Writable<List | null> = writable(null)
|
||||||
export const listTrail: Writable<Trail | null> = writable(null);
|
export const listTrail: Writable<Trail | null> = writable(null);
|
||||||
|
|
||||||
export async function lists_index(filter?: ListFilter, page: number = 1, perPage: number = 5,
|
export async function lists_index(filter?: ListFilter, page: number = 1, perPage: number = 5,
|
||||||
f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch,
|
f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch,
|
||||||
e: ExpandType = ExpandType.All) {
|
e: ExpandType = ExpandType.All) {
|
||||||
const filterText = filter ? buildFilterText(filter) : ""
|
const user = get(currentUser)
|
||||||
|
|
||||||
|
const filterText = filter ? buildFilterText(user, filter) : ""
|
||||||
|
|
||||||
const r = await f('/api/v1/list?' + new URLSearchParams({
|
const r = await f('/api/v1/list?' + new URLSearchParams({
|
||||||
sort: `${filter?.sortOrder ?? "-"}${filter?.sort ?? "name"}`,
|
sort: `${filter?.sortOrder ?? "-"}${filter?.sort ?? "name"}`,
|
||||||
@@ -42,8 +44,9 @@ export async function lists_index(filter?: ListFilter, page: number = 1, perPage
|
|||||||
|
|
||||||
|
|
||||||
export async function lists_search_filter(filter: ListFilter, page: number = 1, perPage: number = 5, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch): Promise<ListResult<List>> {
|
export async function lists_search_filter(filter: ListFilter, page: number = 1, perPage: number = 5, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch): Promise<ListResult<List>> {
|
||||||
|
const user = get(currentUser)
|
||||||
|
|
||||||
const filterText = buildSearchFilterText(filter)
|
const filterText = buildSearchFilterText(user, filter)
|
||||||
|
|
||||||
let r = await f("/api/v1/search/lists", {
|
let r = await f("/api/v1/search/lists", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -96,7 +99,7 @@ export async function lists_search_filter(filter: ListFilter, page: number = 1,
|
|||||||
|
|
||||||
export async function lists_show(id: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch
|
export async function lists_show(id: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch
|
||||||
, e: ExpandType = ExpandType.All) {
|
, e: ExpandType = ExpandType.All) {
|
||||||
|
|
||||||
const r = await f(`/api/v1/list/${id}?` + new URLSearchParams({
|
const r = await f(`/api/v1/list/${id}?` + new URLSearchParams({
|
||||||
expand: ExpandTypeToString(e)
|
expand: ExpandTypeToString(e)
|
||||||
}), {
|
}), {
|
||||||
@@ -125,11 +128,11 @@ export async function lists_show(id: string, f: (url: RequestInfo | URL, config?
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function lists_create(list: List, avatar?: File) {
|
export async function lists_create(list: List, avatar?: File) {
|
||||||
if (!pb.authStore.record) {
|
const user = get(currentUser)
|
||||||
throw new Error("Unauthenticated");
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
}
|
}
|
||||||
|
list.author = user.id;
|
||||||
list.author = pb.authStore.record!.id;
|
|
||||||
|
|
||||||
let r = await fetch('/api/v1/list', {
|
let r = await fetch('/api/v1/list', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
@@ -240,24 +243,24 @@ export async function lists_delete(list: List) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function buildFilterText(filter: ListFilter): string {
|
function buildFilterText(user: AuthRecord | undefined, filter: ListFilter): string {
|
||||||
let filterText = `(name~"${filter.q}"||description~"${filter.q}")`
|
let filterText = `(name~"${filter.q}"||description~"${filter.q}")`
|
||||||
if (filter.author?.length) {
|
if (filter.author?.length) {
|
||||||
filterText += `&&author="${filter.author}"`
|
filterText += `&&author="${filter.author}"`
|
||||||
}
|
}
|
||||||
if (pb.authStore.record) {
|
if (user) {
|
||||||
if (filter.public === false && filter.shared === false) {
|
if (filter.public === false && filter.shared === false) {
|
||||||
filterText += `&&author="${pb.authStore.record.id}"`
|
filterText += `&&author="${user.id}"`
|
||||||
} else if (filter.public === true && filter.shared === false) {
|
} else if (filter.public === true && filter.shared === false) {
|
||||||
filterText += `&&(public=true||list_share_via_list.user!="${pb.authStore.record.id}"||author="${pb.authStore.record.id}")`
|
filterText += `&&(public=true||list_share_via_list.user!="${user.id}"||author="${user.id}")`
|
||||||
} else if (filter.public === false && filter.shared === true) {
|
} else if (filter.public === false && filter.shared === true) {
|
||||||
filterText += `&&(public=false||list_share_via_list.user="${pb.authStore.record.id}"||author="${pb.authStore.record.id}")`
|
filterText += `&&(public=false||list_share_via_list.user="${user.id}"||author="${user.id}")`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filterText
|
return filterText
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSearchFilterText(filter: ListFilter): string {
|
function buildSearchFilterText(user: AuthRecord, filter: ListFilter): string {
|
||||||
let filterText: string = "";
|
let filterText: string = "";
|
||||||
|
|
||||||
if (filter.author?.length) {
|
if (filter.author?.length) {
|
||||||
@@ -272,17 +275,17 @@ function buildSearchFilterText(filter: ListFilter): string {
|
|||||||
if (filter.public !== undefined) {
|
if (filter.public !== undefined) {
|
||||||
filterText += `(public = ${filter.public}`
|
filterText += `(public = ${filter.public}`
|
||||||
|
|
||||||
if (!filter.author?.length || filter.author == pb.authStore.record?.id) {
|
if (!filter.author?.length || filter.author == user?.id) {
|
||||||
filterText += ` OR author = ${pb.authStore.record?.id}`
|
filterText += ` OR author = ${user?.id}`
|
||||||
}
|
}
|
||||||
filterText += ")"
|
filterText += ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.shared !== undefined) {
|
if (filter.shared !== undefined) {
|
||||||
if (filter.shared === true) {
|
if (filter.shared === true) {
|
||||||
filterText += ` OR shares = ${pb.authStore.record?.id}`
|
filterText += ` OR shares = ${user?.id}`
|
||||||
} else {
|
} else {
|
||||||
filterText += ` AND NOT shares = ${pb.authStore.record?.id}`
|
filterText += ` AND NOT shares = ${user?.id}`
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { SummitLog, type SummitLogFilter } from "$lib/models/summit_log";
|
import { SummitLog, type SummitLogFilter } from "$lib/models/summit_log";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { type ListResult } from "pocketbase";
|
|
||||||
import { writable, type Writable } from "svelte/store";
|
|
||||||
import { fetchGPX } from "./trail_store";
|
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
|
import { type ListResult } from "pocketbase";
|
||||||
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
import { currentUser } from "./user_store";
|
||||||
|
|
||||||
export const summitLog: Writable<SummitLog> = writable(new SummitLog(new Date().toISOString().substring(0, 10)));
|
export const summitLog: Writable<SummitLog> = writable(new SummitLog(new Date().toISOString().substring(0, 10)));
|
||||||
export const summitLogs: Writable<SummitLog[]> = writable([]);
|
export const summitLogs: Writable<SummitLog[]> = writable([]);
|
||||||
@@ -47,7 +46,12 @@ export async function summit_logs_index(author: string, filter?: SummitLogFilter
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function summit_logs_create(summitLog: SummitLog, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
export async function summit_logs_create(summitLog: SummitLog, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
||||||
summitLog.author = pb.authStore.record!.id
|
const user = get(currentUser)
|
||||||
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
|
}
|
||||||
|
|
||||||
|
summitLog.author = user.id
|
||||||
|
|
||||||
let r = await f('/api/v1/summit-log', {
|
let r = await f('/api/v1/summit-log', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
@@ -102,7 +106,12 @@ export async function summit_logs_create(summitLog: SummitLog, f: (url: RequestI
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function summit_logs_update(oldSummitLog: SummitLog, newSummitLog: SummitLog) {
|
export async function summit_logs_update(oldSummitLog: SummitLog, newSummitLog: SummitLog) {
|
||||||
newSummitLog.author = pb.authStore.record!.id
|
const user = get(currentUser)
|
||||||
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
|
}
|
||||||
|
|
||||||
|
newSummitLog.author = user.id
|
||||||
|
|
||||||
let r = await fetch('/api/v1/summit-log/' + newSummitLog.id, {
|
let r = await fetch('/api/v1/summit-log/' + newSummitLog.id, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import type { SummitLog } from "$lib/models/summit_log";
|
import type { SummitLog } from "$lib/models/summit_log";
|
||||||
|
import type { Tag } from "$lib/models/tag";
|
||||||
import { defaultTrailSearchAttributes, Trail, type TrailFilter, type TrailFilterValues, type TrailSearchResult } from "$lib/models/trail";
|
import { defaultTrailSearchAttributes, Trail, type TrailFilter, type TrailFilterValues, type TrailSearchResult } from "$lib/models/trail";
|
||||||
import type { Waypoint } from "$lib/models/waypoint";
|
import type { Waypoint } from "$lib/models/waypoint";
|
||||||
import { pb } from "$lib/pocketbase";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import { deepEqual } from "$lib/util/deep_util";
|
import { deepEqual } from "$lib/util/deep_util";
|
||||||
import { getFileURL } from "$lib/util/file_util";
|
import { getFileURL } from "$lib/util/file_util";
|
||||||
import * as M from "maplibre-gl";
|
import * as M from "maplibre-gl";
|
||||||
import type { Hits } from "meilisearch";
|
import type { Hits } from "meilisearch";
|
||||||
import { type ListResult, type RecordModel } from "pocketbase";
|
import { type AuthRecord, type ListResult, type RecordModel } from "pocketbase";
|
||||||
import { writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
import { summit_logs_create, summit_logs_delete, summit_logs_update } from "./summit_log_store";
|
import { summit_logs_create, summit_logs_delete, summit_logs_update } from "./summit_log_store";
|
||||||
import { waypoints_create, waypoints_delete, waypoints_update } from "./waypoint_store";
|
|
||||||
import { APIError } from "$lib/util/api_util";
|
|
||||||
import { tags_create } from "./tag_store";
|
import { tags_create } from "./tag_store";
|
||||||
import type { Tag } from "$lib/models/tag";
|
import { currentUser } from "./user_store";
|
||||||
|
import { waypoints_create, waypoints_delete, waypoints_update } from "./waypoint_store";
|
||||||
|
|
||||||
let trails: Trail[] = []
|
let trails: Trail[] = []
|
||||||
export const trail: Writable<Trail> = writable(new Trail(""));
|
export const trail: Writable<Trail> = writable(new Trail(""));
|
||||||
@@ -57,7 +57,9 @@ export async function trails_recommend(size: number, f: (url: RequestInfo | URL,
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function trails_search_filter(filter: TrailFilter, page: number = 1, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
export async function trails_search_filter(filter: TrailFilter, page: number = 1, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
||||||
let filterText: string = buildFilterText(filter, true);
|
const user = get(currentUser)
|
||||||
|
|
||||||
|
let filterText: string = buildFilterText(user, filter, true);
|
||||||
|
|
||||||
let r = await f("/api/v1/search/trails", {
|
let r = await f("/api/v1/search/trails", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -91,11 +93,12 @@ export async function trails_search_filter(filter: TrailFilter, page: number = 1
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function trails_search_bounding_box(northEast: M.LngLat, southWest: M.LngLat, filter?: TrailFilter, page: number = 1, includePolyline: boolean = true) {
|
export async function trails_search_bounding_box(northEast: M.LngLat, southWest: M.LngLat, filter?: TrailFilter, page: number = 1, includePolyline: boolean = true) {
|
||||||
|
const user = get(currentUser)
|
||||||
|
|
||||||
let filterText: string = "";
|
let filterText: string = "";
|
||||||
|
|
||||||
if (filter) {
|
if (filter) {
|
||||||
filterText = buildFilterText(filter, false);
|
filterText = buildFilterText(user, filter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = await fetch("/api/v1/search/trails", {
|
let r = await fetch("/api/v1/search/trails", {
|
||||||
@@ -173,6 +176,10 @@ export async function trails_show(id: string, loadGPX?: boolean, f: (url: Reques
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function trails_create(trail: Trail, photos: File[], gpx: File | Blob | null, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
export async function trails_create(trail: Trail, photos: File[], gpx: File | Blob | null, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
||||||
|
const user = get(currentUser)
|
||||||
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
|
}
|
||||||
|
|
||||||
for (const waypoint of trail.expand?.waypoints ?? []) {
|
for (const waypoint of trail.expand?.waypoints ?? []) {
|
||||||
const model = await waypoints_create({
|
const model = await waypoints_create({
|
||||||
@@ -194,7 +201,7 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | Bl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trail.author = pb.authStore.record!.id
|
trail.author = user.id
|
||||||
|
|
||||||
let r = await f(`/api/v1/trail?` + new URLSearchParams({
|
let r = await f(`/api/v1/trail?` + new URLSearchParams({
|
||||||
expand: "category,waypoints,summit_logs,trail_share_via_trail,tags",
|
expand: "category,waypoints,summit_logs,trail_share_via_trail,tags",
|
||||||
@@ -500,7 +507,7 @@ async function searchResultToTrailList(hits: Hits<TrailSearchResult>): Promise<T
|
|||||||
return trails
|
return trails
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildFilterText(filter: TrailFilter, includeGeo: boolean): string {
|
function buildFilterText(user: AuthRecord, filter: TrailFilter, includeGeo: boolean): string {
|
||||||
let filterText: string = "";
|
let filterText: string = "";
|
||||||
|
|
||||||
filterText += `distance >= ${Math.floor(filter.distanceMin)} AND elevation_gain >= ${Math.floor(filter.elevationGainMin)} AND elevation_loss >= ${Math.floor(filter.elevationLossMin)}`
|
filterText += `distance >= ${Math.floor(filter.distanceMin)} AND elevation_gain >= ${Math.floor(filter.elevationGainMin)} AND elevation_loss >= ${Math.floor(filter.elevationLossMin)}`
|
||||||
@@ -530,17 +537,17 @@ function buildFilterText(filter: TrailFilter, includeGeo: boolean): string {
|
|||||||
if (filter.public !== undefined) {
|
if (filter.public !== undefined) {
|
||||||
filterText += `(public = ${filter.public}`
|
filterText += `(public = ${filter.public}`
|
||||||
|
|
||||||
if (!filter.author?.length || filter.author == pb.authStore.record?.id) {
|
if (!filter.author?.length || filter.author == user?.id) {
|
||||||
filterText += ` OR author = ${pb.authStore.record?.id}`
|
filterText += ` OR author = ${user?.id}`
|
||||||
}
|
}
|
||||||
filterText += ")"
|
filterText += ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.shared !== undefined) {
|
if (filter.shared !== undefined) {
|
||||||
if (filter.shared === true) {
|
if (filter.shared === true) {
|
||||||
filterText += ` OR shares = ${pb.authStore.record?.id}`
|
filterText += ` OR shares = ${user?.id}`
|
||||||
} else {
|
} else {
|
||||||
filterText += ` AND NOT shares = ${pb.authStore.record?.id}`
|
filterText += ` AND NOT shares = ${user?.id}`
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import type { User, UserAnonymous } from "$lib/models/user";
|
import type { User, UserAnonymous } from "$lib/models/user";
|
||||||
import { pb } from "$lib/pocketbase";
|
import { getPb } from "$lib/pocketbase";
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import { type AuthMethodsList } from "pocketbase";
|
import { type AuthMethodsList } from "pocketbase";
|
||||||
import { writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
|
||||||
export const currentUser: Writable<User | null> = writable<User | null>()
|
export const currentUser: Writable<User | null> = writable<User | null>()
|
||||||
|
|
||||||
@@ -24,8 +24,10 @@ export async function users_create(user: User) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function users_search(q: string, includeSelf: boolean = true) {
|
export async function users_search(q: string, includeSelf: boolean = true) {
|
||||||
|
const user = get(currentUser)
|
||||||
|
|
||||||
let r = await fetch('/api/v1/user/anonymous?' + new URLSearchParams({
|
let r = await fetch('/api/v1/user/anonymous?' + new URLSearchParams({
|
||||||
"filter": `username~"${q}"${includeSelf ? '' : `&&id!="${pb.authStore.record?.id}"`}`,
|
"filter": `username~"${q}"${includeSelf ? '' : `&&id!="${user?.id}"`}`,
|
||||||
}), {
|
}), {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
})
|
})
|
||||||
@@ -69,6 +71,8 @@ export async function users_auth_methods(f: (url: RequestInfo | URL, config?: Re
|
|||||||
|
|
||||||
|
|
||||||
export async function login(user: User) {
|
export async function login(user: User) {
|
||||||
|
const pb = getPb();
|
||||||
|
|
||||||
const r = await fetch('/api/v1/auth/login', {
|
const r = await fetch('/api/v1/auth/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(user),
|
body: JSON.stringify(user),
|
||||||
@@ -83,6 +87,8 @@ export async function login(user: User) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function oauth_login(data: { name: string, code: string, codeVerifier: string }) {
|
export async function oauth_login(data: { name: string, code: string, codeVerifier: string }) {
|
||||||
|
const pb = getPb();
|
||||||
|
|
||||||
const r = await fetch('/api/v1/auth/oauth', {
|
const r = await fetch('/api/v1/auth/oauth', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
@@ -98,6 +104,8 @@ export async function oauth_login(data: { name: string, code: string, codeVerifi
|
|||||||
|
|
||||||
|
|
||||||
export async function logout() {
|
export async function logout() {
|
||||||
|
const pb = getPb();
|
||||||
|
|
||||||
pb.authStore.clear();
|
pb.authStore.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import { Waypoint } from "$lib/models/waypoint";
|
import { Waypoint } from "$lib/models/waypoint";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { APIError } from "$lib/util/api_util";
|
import { APIError } from "$lib/util/api_util";
|
||||||
import { writable, type Writable } from "svelte/store";
|
import { get, writable, type Writable } from "svelte/store";
|
||||||
|
import { currentUser } from "./user_store";
|
||||||
|
|
||||||
export const waypoint: Writable<Waypoint> = writable(new Waypoint(0, 0));
|
export const waypoint: Writable<Waypoint> = writable(new Waypoint(0, 0));
|
||||||
|
|
||||||
export async function waypoints_create(waypoint: Waypoint, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
export async function waypoints_create(waypoint: Waypoint, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
|
||||||
|
const user = get(currentUser)
|
||||||
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
|
}
|
||||||
|
|
||||||
waypoint.author = pb.authStore.record!.id
|
waypoint.author = user.id
|
||||||
|
|
||||||
let r = await f('/api/v1/waypoint', {
|
let r = await f('/api/v1/waypoint', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
@@ -45,7 +49,11 @@ export async function waypoints_create(waypoint: Waypoint, f: (url: RequestInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function waypoints_update(oldWaypoint: Waypoint, newWaypoint: Waypoint) {
|
export async function waypoints_update(oldWaypoint: Waypoint, newWaypoint: Waypoint) {
|
||||||
newWaypoint.author = pb.authStore.record!.id
|
const user = get(currentUser)
|
||||||
|
if (!user) {
|
||||||
|
throw Error("Unauthenticated")
|
||||||
|
}
|
||||||
|
newWaypoint.author = user.id
|
||||||
|
|
||||||
let r = await fetch('/api/v1/waypoint/' + newWaypoint.id, {
|
let r = await fetch('/api/v1/waypoint/' + newWaypoint.id, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { error, type NumericRange, type RequestEvent } from "@sveltejs/kit";
|
import { error, type NumericRange, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { ClientResponseError, type ListResult } from "pocketbase";
|
import { ClientResponseError, type ListResult } from "pocketbase";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { ZodError, type ZodSchema } from "zod";
|
import { ZodError, type ZodSchema } from "zod";
|
||||||
import { RecordListOptionsSchema, RecordIdSchema, RecordOptionsSchema } from "$lib/models/api/base_schema";
|
import { RecordListOptionsSchema, RecordIdSchema, RecordOptionsSchema } from "$lib/models/api/base_schema";
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ export async function list<T>(event: RequestEvent, collection: Collection) {
|
|||||||
|
|
||||||
let r: ListResult<T>;
|
let r: ListResult<T>;
|
||||||
if ((safeSearchParams.perPage ?? 0) < 0) {
|
if ((safeSearchParams.perPage ?? 0) < 0) {
|
||||||
const activities: T[] = await pb.collection(Collection[collection])
|
const activities: T[] = await event.locals.pb.collection(Collection[collection])
|
||||||
.getFullList<T>(safeSearchParams)
|
.getFullList<T>(safeSearchParams)
|
||||||
r = {
|
r = {
|
||||||
items: activities,
|
items: activities,
|
||||||
@@ -56,7 +55,7 @@ export async function list<T>(event: RequestEvent, collection: Collection) {
|
|||||||
totalPages: 1
|
totalPages: 1
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
r = await pb.collection(Collection[collection])
|
r = await event.locals.pb.collection(Collection[collection])
|
||||||
.getList<T>(safeSearchParams.page, safeSearchParams.perPage, { ...safeSearchParams })
|
.getList<T>(safeSearchParams.page, safeSearchParams.perPage, { ...safeSearchParams })
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
@@ -69,7 +68,7 @@ export async function show<T>(event: RequestEvent, collection: Collection) {
|
|||||||
const searchParams = Object.fromEntries(event.url.searchParams);
|
const searchParams = Object.fromEntries(event.url.searchParams);
|
||||||
const safeSearchParams = RecordOptionsSchema.parse(searchParams);
|
const safeSearchParams = RecordOptionsSchema.parse(searchParams);
|
||||||
|
|
||||||
const r = await pb.collection(collection.toString())
|
const r = await event.locals.pb.collection(collection.toString())
|
||||||
.getOne<T>(safeParams.id, safeSearchParams)
|
.getOne<T>(safeParams.id, safeSearchParams)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
@@ -82,7 +81,7 @@ export async function create<T>(event: RequestEvent, schema: ZodSchema, collecti
|
|||||||
const data = await event.request.json();
|
const data = await event.request.json();
|
||||||
const safeData = schema.parse(data);
|
const safeData = schema.parse(data);
|
||||||
|
|
||||||
const r = await pb.collection(Collection[collection]).create<T>(safeData, {...safeSearchParams, requestKey: null})
|
const r = await event.locals.pb.collection(Collection[collection]).create<T>(safeData, {...safeSearchParams, requestKey: null})
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -97,7 +96,7 @@ export async function update<T>(event: RequestEvent, schema: ZodSchema, collecti
|
|||||||
const data = await event.request.json();
|
const data = await event.request.json();
|
||||||
const safeData = schema.parse(data);
|
const safeData = schema.parse(data);
|
||||||
|
|
||||||
const r = await pb.collection(Collection[collection]).update<T>(safeParams.id, safeData, safeSearchParams)
|
const r = await event.locals.pb.collection(Collection[collection]).update<T>(safeParams.id, safeData, safeSearchParams)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -108,7 +107,7 @@ export async function upload<T>(event: RequestEvent, collection: Collection) {
|
|||||||
|
|
||||||
const data = await event.request.formData();
|
const data = await event.request.formData();
|
||||||
|
|
||||||
const r = await pb.collection(Collection[collection]).update<T>(safeParams.id, data)
|
const r = await event.locals.pb.collection(Collection[collection]).update<T>(safeParams.id, data)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -117,7 +116,7 @@ export async function remove(event: RequestEvent, collection: Collection) {
|
|||||||
const params = event.params
|
const params = event.params
|
||||||
const safeParams = RecordIdSchema.parse(params);
|
const safeParams = RecordIdSchema.parse(params);
|
||||||
|
|
||||||
const r = await pb.collection(Collection[collection]).delete(safeParams.id)
|
const r = await event.locals.pb.collection(Collection[collection]).delete(safeParams.id)
|
||||||
|
|
||||||
return { 'acknowledged': r }
|
return { 'acknowledged': r }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { LayoutServerLoad } from './$types';
|
|||||||
import { env } from "$env/dynamic/private";
|
import { env } from "$env/dynamic/private";
|
||||||
import type { Settings } from '$lib/models/settings';
|
import type { Settings } from '$lib/models/settings';
|
||||||
import { notifications_index } from '$lib/stores/notification_store';
|
import { notifications_index } from '$lib/stores/notification_store';
|
||||||
|
import type { AuthRecord } from 'pocketbase';
|
||||||
|
|
||||||
export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
|
export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
|
||||||
|
|
||||||
@@ -11,5 +12,5 @@ export const load: LayoutServerLoad = async ({ locals, url, fetch }) => {
|
|||||||
if (locals.user?.id) {
|
if (locals.user?.id) {
|
||||||
notifications = await notifications_index({ recipient: locals.user.id }, 1, 10, fetch);
|
notifications = await notifications_index({ recipient: locals.user.id }, 1, 10, fetch);
|
||||||
}
|
}
|
||||||
return { settings: locals.settings as Settings, notifications, origin: env.ORIGIN }
|
return { settings: locals.settings as Settings, user: locals.user as AuthRecord, notifications, origin: env.ORIGIN }
|
||||||
}
|
}
|
||||||
@@ -15,11 +15,14 @@
|
|||||||
import "../css/app.css";
|
import "../css/app.css";
|
||||||
import "../css/components.css";
|
import "../css/components.css";
|
||||||
import "../css/theme.css";
|
import "../css/theme.css";
|
||||||
|
import type { LayoutData } from "./$types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
data: LayoutData;
|
||||||
children?: Snippet;
|
children?: Snippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { children }: Props = $props();
|
let { data, children }: Props = $props();
|
||||||
|
|
||||||
beforeNavigate((n) => {
|
beforeNavigate((n) => {
|
||||||
if (!$currentUser && isRouteProtected(n.to?.url?.pathname ?? "")) {
|
if (!$currentUser && isRouteProtected(n.to?.url?.pathname ?? "")) {
|
||||||
@@ -80,7 +83,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<NavBar></NavBar>
|
<NavBar user={data.user}></NavBar>
|
||||||
<PageLoadingBar class="text-content"></PageLoadingBar>
|
<PageLoadingBar class="text-content"></PageLoadingBar>
|
||||||
<Toast></Toast>
|
<Toast></Toast>
|
||||||
<UploadDialog></UploadDialog>
|
<UploadDialog></UploadDialog>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { handleError } from "$lib/util/api_util";
|
import { handleError } from "$lib/util/api_util";
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export async function POST(event: RequestEvent) {
|
export async function POST(event: RequestEvent) {
|
||||||
@@ -11,7 +10,7 @@ export async function POST(event: RequestEvent) {
|
|||||||
password: z.string().min(8).max(72),
|
password: z.string().min(8).max(72),
|
||||||
passwordConfirm: z.string().min(8).max(72)
|
passwordConfirm: z.string().min(8).max(72)
|
||||||
}).refine(d => d.password === d.passwordConfirm).parse(data)
|
}).refine(d => d.password === d.passwordConfirm).parse(data)
|
||||||
const r = await pb.collection('users').confirmPasswordReset(safeData.token, safeData.password, safeData.passwordConfirm);
|
const r = await event.locals.pb.collection('users').confirmPasswordReset(safeData.token, safeData.password, safeData.passwordConfirm);
|
||||||
return json(r);
|
return json(r);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw handleError(e);
|
throw handleError(e);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { handleError } from "$lib/util/api_util";
|
import { handleError } from "$lib/util/api_util";
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export async function POST(event: RequestEvent) {
|
export async function POST(event: RequestEvent) {
|
||||||
@@ -13,7 +12,7 @@ export async function POST(event: RequestEvent) {
|
|||||||
}).refine(d => d.email !== undefined || d.username !== undefined).parse(data);
|
}).refine(d => d.email !== undefined || d.username !== undefined).parse(data);
|
||||||
|
|
||||||
|
|
||||||
const r = await pb.collection('users').authWithPassword(safeData.email ?? safeData.username!, data.password);
|
const r = await event.locals.pb.collection('users').authWithPassword(safeData.email ?? safeData.username!, data.password);
|
||||||
return json(r);
|
return json(r);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw handleError(e);
|
throw handleError(e);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { env } from "$env/dynamic/public";
|
import { env } from "$env/dynamic/public";
|
||||||
import { env as private_env } from "$env/dynamic/private";
|
import { env as private_env } from "$env/dynamic/private";
|
||||||
|
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { handleError } from "$lib/util/api_util";
|
import { handleError } from "$lib/util/api_util";
|
||||||
@@ -10,7 +9,7 @@ const redirectURL = private_env.ORIGIN + "/login/redirect"
|
|||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
const r = await pb.collection('users').listAuthMethods();
|
const r = await event.locals.pb.collection('users').listAuthMethods();
|
||||||
|
|
||||||
for (const provider of r.oauth2.providers) {
|
for (const provider of r.oauth2.providers) {
|
||||||
const imageURL = `${env.PUBLIC_POCKETBASE_URL}/_/images/oauth2/${provider.name}.svg`
|
const imageURL = `${env.PUBLIC_POCKETBASE_URL}/_/images/oauth2/${provider.name}.svg`
|
||||||
@@ -33,7 +32,7 @@ export async function POST(event: RequestEvent) {
|
|||||||
codeVerifier: z.string()
|
codeVerifier: z.string()
|
||||||
}).parse(data)
|
}).parse(data)
|
||||||
|
|
||||||
const r = await pb.collection('users').authWithOAuth2Code(
|
const r = await event.locals.pb.collection('users').authWithOAuth2Code(
|
||||||
safeData.name,
|
safeData.name,
|
||||||
safeData.code,
|
safeData.code,
|
||||||
safeData.codeVerifier,
|
safeData.codeVerifier,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { handleError } from "$lib/util/api_util";
|
import { handleError } from "$lib/util/api_util";
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
@@ -10,7 +9,7 @@ export async function POST(event: RequestEvent) {
|
|||||||
email: z.string().email()
|
email: z.string().email()
|
||||||
}).parse(data)
|
}).parse(data)
|
||||||
|
|
||||||
const r = await pb.collection('users').requestPasswordReset(safeData.email);
|
const r = await event.locals.pb.collection('users').requestPasswordReset(safeData.email);
|
||||||
return json(r);
|
return json(r);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw handleError(e);
|
throw handleError(e);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { CommentCreateSchema } from '$lib/models/api/comment_schema';
|
import { CommentCreateSchema } from '$lib/models/api/comment_schema';
|
||||||
import type { Comment } from '$lib/models/comment';
|
import type { Comment } from '$lib/models/comment';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
for (const comment of r.items) {
|
for (const comment of r.items) {
|
||||||
if (!comment.expand?.author) {
|
if (!comment.expand?.author) {
|
||||||
comment.expand = {
|
comment.expand = {
|
||||||
author: await pb.collection('users_anonymous').getOne(comment.author)
|
author: await event.locals.pb.collection('users_anonymous').getOne(comment.author)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { CommentUpdateSchema } from "$lib/models/api/comment_schema";
|
import { CommentUpdateSchema } from "$lib/models/api/comment_schema";
|
||||||
import type { Comment } from "$lib/models/comment";
|
import type { Comment } from "$lib/models/comment";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
||||||
import { json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
if (!r.expand) {
|
if (!r.expand) {
|
||||||
r.expand = {} as any
|
r.expand = {} as any
|
||||||
}
|
}
|
||||||
r.expand!.author = await pb.collection('users_anonymous').getOne(r.author)
|
r.expand!.author = await event.locals.pb.collection('users_anonymous').getOne(r.author)
|
||||||
|
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { error, type RequestEvent } from "@sveltejs/kit";
|
import { error, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
parts.push(encodeURIComponent(safeParams.data.record));
|
parts.push(encodeURIComponent(safeParams.data.record));
|
||||||
parts.push(encodeURIComponent(safeParams.data.file));
|
parts.push(encodeURIComponent(safeParams.data.file));
|
||||||
|
|
||||||
let fileURL = pb.buildURL(parts.join("/"));
|
let fileURL = event.locals.pb.buildURL(parts.join("/"));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await event.fetch(fileURL)
|
const r = await event.fetch(fileURL)
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { FollowCreateSchema } from '$lib/models/api/follow_schema';
|
import { FollowCreateSchema } from '$lib/models/api/follow_schema';
|
||||||
import type { Follow } from '$lib/models/follow';
|
import type { Follow } from '$lib/models/follow';
|
||||||
import type { UserAnonymous } from '$lib/models/user';
|
import type { UserAnonymous } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
@@ -9,8 +8,8 @@ export async function GET(event: RequestEvent) {
|
|||||||
try {
|
try {
|
||||||
const r = await list<Follow>(event, Collection.follows);
|
const r = await list<Follow>(event, Collection.follows);
|
||||||
for (const follow of r.items) {
|
for (const follow of r.items) {
|
||||||
const follower = await pb.collection('users_anonymous').getOne<UserAnonymous>(follow.follower, { requestKey: null })
|
const follower = await event.locals.pb.collection('users_anonymous').getOne<UserAnonymous>(follow.follower, { requestKey: null })
|
||||||
const followee = await pb.collection('users_anonymous').getOne<UserAnonymous>(follow.followee, { requestKey: null })
|
const followee = await event.locals.pb.collection('users_anonymous').getOne<UserAnonymous>(follow.followee, { requestKey: null })
|
||||||
follow.expand = {
|
follow.expand = {
|
||||||
follower, followee
|
follower, followee
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { handleError } from "$lib/util/api_util";
|
import { handleError } from "$lib/util/api_util";
|
||||||
import { json } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
const r = await pb.send("/integration/komoot/login", {
|
const r = await event.locals.pb.send("/integration/komoot/login", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
return json(r);
|
return json(r);
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import { ListShareCreateSchema } from '$lib/models/api/list_share_schema';
|
import { ListShareCreateSchema } from '$lib/models/api/list_share_schema';
|
||||||
import type { ListShare } from '$lib/models/list_share';
|
import type { ListShare } from '$lib/models/list_share';
|
||||||
import type { User } from '$lib/models/user';
|
import type { User } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
const r = await list<ListShare>(event, Collection.list_share);
|
const r = await list<ListShare>(event, Collection.list_share);
|
||||||
|
|
||||||
for (const share of r.items) {
|
for (const share of r.items) {
|
||||||
const anonymous_user = await pb.collection('users_anonymous').getOne<User>(share.user)
|
const anonymous_user = await event.locals.pb.collection('users_anonymous').getOne<User>(share.user)
|
||||||
share.expand = {
|
share.expand = {
|
||||||
user: anonymous_user
|
user: anonymous_user
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ListCreateSchema } from '$lib/models/api/list_schema';
|
import { ListCreateSchema } from '$lib/models/api/list_schema';
|
||||||
import type { List } from '$lib/models/list';
|
import type { List } from '$lib/models/list';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
@@ -8,13 +7,13 @@ export async function GET(event: RequestEvent) {
|
|||||||
try {
|
try {
|
||||||
const r = await list<List>(event, Collection.lists);
|
const r = await list<List>(event, Collection.lists);
|
||||||
for (const t of r.items) {
|
for (const t of r.items) {
|
||||||
if (!t.author || !pb.authStore.record) {
|
if (!t.author || !event.locals.pb.authStore.record) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!t.expand) {
|
if (!t.expand) {
|
||||||
t.expand = {}
|
t.expand = {}
|
||||||
}
|
}
|
||||||
t.expand!.author = await pb.collection("users_anonymous").getOne(t.author);
|
t.expand!.author = await event.locals.pb.collection("users_anonymous").getOne(t.author);
|
||||||
}
|
}
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ListUpdateSchema } from "$lib/models/api/list_schema";
|
import { ListUpdateSchema } from "$lib/models/api/list_schema";
|
||||||
import type { List } from "$lib/models/list";
|
import type { List } from "$lib/models/list";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
||||||
import { json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
if (!r.expand) {
|
if (!r.expand) {
|
||||||
r.expand = {} as any
|
r.expand = {} as any
|
||||||
}
|
}
|
||||||
r.expand!.author = await pb.collection('users_anonymous').getOne(r.author!)
|
r.expand!.author = await event.locals.pb.collection('users_anonymous').getOne(r.author!)
|
||||||
|
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection, handleError, upload } from "$lib/util/api_util";
|
import { Collection, handleError, upload } from "$lib/util/api_util";
|
||||||
import { json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import type { List } from "postcss/lib/list";
|
import type { List } from "postcss/lib/list";
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import type { Notification } from '$lib/models/notification';
|
import type { Notification } from '$lib/models/notification';
|
||||||
import type { UserAnonymous } from '$lib/models/user';
|
import type { UserAnonymous } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, handleError, list } from '$lib/util/api_util';
|
import { Collection, handleError, list } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
const r = await list<Notification>(event, Collection.notifications);
|
const r = await list<Notification>(event, Collection.notifications);
|
||||||
|
|
||||||
for (const notification of r.items) {
|
for (const notification of r.items) {
|
||||||
const recipient = await pb.collection('users_anonymous').getOne<UserAnonymous>(notification.recipient, { requestKey: null })
|
const recipient = await event.locals.pb.collection('users_anonymous').getOne<UserAnonymous>(notification.recipient, { requestKey: null })
|
||||||
const author = await pb.collection('users_anonymous').getOne<UserAnonymous>(notification.author, { requestKey: null })
|
const author = await event.locals.pb.collection('users_anonymous').getOne<UserAnonymous>(notification.author, { requestKey: null })
|
||||||
notification.expand = {
|
notification.expand = {
|
||||||
recipient, author
|
recipient, author
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { SettingsCreateSchema } from '$lib/models/api/settings_schema';
|
import { SettingsCreateSchema } from '$lib/models/api/settings_schema';
|
||||||
import type { Settings } from "$lib/models/settings";
|
import type { Settings } from "$lib/models/settings";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { SummitLogUpdateSchema } from "$lib/models/api/summit_log_schema";
|
import { SummitLogUpdateSchema } from "$lib/models/api/summit_log_schema";
|
||||||
import type { SummitLog } from "$lib/models/summit_log";
|
import type { SummitLog } from "$lib/models/summit_log";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
||||||
|
|
||||||
@@ -12,7 +11,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
if (!r.expand) {
|
if (!r.expand) {
|
||||||
r.expand = {} as any
|
r.expand = {} as any
|
||||||
}
|
}
|
||||||
r.expand!.author = await pb.collection("users_anonymous").getOne(r.author!);
|
r.expand!.author = await event.locals.pb.collection("users_anonymous").getOne(r.author!);
|
||||||
|
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { TrailShareCreateSchema } from '$lib/models/api/trail_share_schema';
|
import { TrailShareCreateSchema } from '$lib/models/api/trail_share_schema';
|
||||||
import type { TrailShare } from '$lib/models/trail_share';
|
import type { TrailShare } from '$lib/models/trail_share';
|
||||||
import type { UserAnonymous } from '$lib/models/user';
|
import type { UserAnonymous } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, handleError, list, create } from '$lib/util/api_util';
|
import { Collection, handleError, list, create } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
@@ -9,7 +8,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
try {
|
try {
|
||||||
const r = await list<TrailShare>(event, Collection.trail_share);
|
const r = await list<TrailShare>(event, Collection.trail_share);
|
||||||
for (const share of r.items) {
|
for (const share of r.items) {
|
||||||
const anonymous_user = await pb.collection('users_anonymous').getOne<UserAnonymous>(share.user)
|
const anonymous_user = await event.locals.pb.collection('users_anonymous').getOne<UserAnonymous>(share.user)
|
||||||
share.expand = {
|
share.expand = {
|
||||||
user: anonymous_user
|
user: anonymous_user
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { TrailCreateSchema } from '$lib/models/api/trail_schema';
|
import { TrailCreateSchema } from '$lib/models/api/trail_schema';
|
||||||
import type { Trail } from '$lib/models/trail';
|
import type { Trail } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
import { Collection, create, handleError, list } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
@@ -9,14 +8,13 @@ export async function GET(event: RequestEvent) {
|
|||||||
const r = await list<Trail>(event, Collection.trails);
|
const r = await list<Trail>(event, Collection.trails);
|
||||||
|
|
||||||
for (const t of r.items) {
|
for (const t of r.items) {
|
||||||
if (!t.author || !pb.authStore.record) {
|
if (!t.author || !event.locals.pb.authStore.record) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!t.expand) {
|
if (!t.expand) {
|
||||||
t.expand = {} as any
|
t.expand = {} as any
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.expand!.author = await pb.collection("users_anonymous").getOne(t.author);
|
|
||||||
t.expand?.waypoints?.sort((a, b) => (a.distance_from_start ?? 0) - (b.distance_from_start ?? 0))
|
t.expand?.waypoints?.sort((a, b) => (a.distance_from_start ?? 0) - (b.distance_from_start ?? 0))
|
||||||
}
|
}
|
||||||
return json(r)
|
return json(r)
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
import { Collection, handleError, remove, show, update } from "$lib/util/api_util";
|
||||||
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
import { error, json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { TrailUpdateSchema } from '$lib/models/api/trail_schema';
|
import { TrailUpdateSchema } from '$lib/models/api/trail_schema';
|
||||||
|
import type PocketBase from "pocketbase";
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
const r = await show<Trail>(event, Collection.trails)
|
const r = await show<Trail>(event, Collection.trails)
|
||||||
|
|
||||||
if (pb.authStore.record) {
|
if (event.locals.pb.authStore.record) {
|
||||||
if (!r.expand) {
|
if (!r.expand) {
|
||||||
r.expand = {} as any
|
r.expand = {} as any
|
||||||
}
|
}
|
||||||
r.expand!.author = await pb.collection("users_anonymous").getOne(r.author!);
|
r.expand!.author = await event.locals.pb.collection("users_anonymous").getOne(r.author!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove time from dates
|
// remove time from dates
|
||||||
await enrichRecord(r);
|
await enrichRecord(event.locals.pb, r);
|
||||||
|
|
||||||
// sort waypoints by distance
|
// sort waypoints by distance
|
||||||
r.expand?.waypoints?.sort((a, b) => (a.distance_from_start ?? 0) - (b.distance_from_start ?? 0))
|
r.expand?.waypoints?.sort((a, b) => (a.distance_from_start ?? 0) - (b.distance_from_start ?? 0))
|
||||||
@@ -29,7 +29,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
export async function POST(event: RequestEvent) {
|
export async function POST(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
const r = await update<Trail>(event, TrailUpdateSchema, Collection.trails)
|
const r = await update<Trail>(event, TrailUpdateSchema, Collection.trails)
|
||||||
await enrichRecord(r)
|
await enrichRecord(event.locals.pb, r)
|
||||||
return json(r);
|
return json(r);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw handleError(e)
|
throw handleError(e)
|
||||||
@@ -47,7 +47,7 @@ export async function DELETE(event: RequestEvent) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function enrichRecord(r: Trail) {
|
async function enrichRecord(pb: PocketBase, r: Trail) {
|
||||||
r.date = r.date?.substring(0, 10) ?? "";
|
r.date = r.date?.substring(0, 10) ?? "";
|
||||||
for (const log of r.expand?.summit_logs ?? []) {
|
for (const log of r.expand?.summit_logs ?? []) {
|
||||||
log.date = log.date.substring(0, 10);
|
log.date = log.date.substring(0, 10);
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { type TrailBoundingBox, type TrailFilterValues } from '$lib/models/trail';
|
import { type TrailBoundingBox, type TrailFilterValues } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { handleError } from '$lib/util/api_util';
|
import { handleError } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
if (!pb.authStore.record) {
|
if (!event.locals.pb.authStore.record) {
|
||||||
return json({
|
return json({
|
||||||
max_lat: 0,
|
max_lat: 0,
|
||||||
min_lat: 0,
|
min_lat: 0,
|
||||||
@@ -13,7 +12,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const r = await pb.collection('trails_bounding_box').getOne<TrailBoundingBox>(pb.authStore.record!.id)
|
const r = await event.locals.pb.collection('trails_bounding_box').getOne<TrailBoundingBox>(event.locals.pb.authStore.record!.id)
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw handleError(e);
|
throw handleError(e);
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { type TrailFilterValues } from '$lib/models/trail';
|
import { type TrailFilterValues } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { handleError } from '$lib/util/api_util';
|
import { handleError } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
if (!pb.authStore.record) {
|
if (!event.locals.pb.authStore.record) {
|
||||||
return json({
|
return json({
|
||||||
min_distance: 0,
|
min_distance: 0,
|
||||||
max_distance: 20000,
|
max_distance: 20000,
|
||||||
@@ -15,7 +14,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const r = await pb.collection('trails_filter').getOne<TrailFilterValues>(pb.authStore.record!.id)
|
const r = await event.locals.pb.collection('trails_filter').getOne<TrailFilterValues>(event.locals.pb.authStore.record!.id)
|
||||||
return json(r)
|
return json(r)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw handleError(e);
|
throw handleError(e);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { TrailRecommendSchema } from '$lib/models/api/trail_schema';
|
import { TrailRecommendSchema } from '$lib/models/api/trail_schema';
|
||||||
import type { Trail } from '$lib/models/trail';
|
import type { Trail } from '$lib/models/trail';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { handleError } from '$lib/util/api_util';
|
import { handleError } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
@@ -9,7 +8,7 @@ export async function GET(event: RequestEvent) {
|
|||||||
const searchParams = Object.fromEntries(event.url.searchParams);
|
const searchParams = Object.fromEntries(event.url.searchParams);
|
||||||
const safeSearchParams = TrailRecommendSchema.parse(searchParams);
|
const safeSearchParams = TrailRecommendSchema.parse(searchParams);
|
||||||
|
|
||||||
const r = await pb.send("/trail/recommend?" + new URLSearchParams({
|
const r = await event.locals.pb.send("/trail/recommend?" + new URLSearchParams({
|
||||||
size: safeSearchParams.size?.toString() ?? ""
|
size: safeSearchParams.size?.toString() ?? ""
|
||||||
}), {
|
}), {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -18,13 +17,13 @@ export async function GET(event: RequestEvent) {
|
|||||||
const result: Trail[] = r;
|
const result: Trail[] = r;
|
||||||
|
|
||||||
for (const t of result) {
|
for (const t of result) {
|
||||||
if (!t.author || !pb.authStore.record) {
|
if (!t.author || !event.locals.pb.authStore.record) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!t.expand) {
|
if (!t.expand) {
|
||||||
t.expand = {} as any
|
t.expand = {} as any
|
||||||
}
|
}
|
||||||
t.expand!.author = await pb.collection("users_anonymous").getOne(t.author);
|
t.expand!.author = await event.locals.pb.collection("users_anonymous").getOne(t.author);
|
||||||
}
|
}
|
||||||
|
|
||||||
return json(result)
|
return json(result)
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import GPX from "$lib/models/gpx/gpx";
|
import GPX from "$lib/models/gpx/gpx";
|
||||||
import { haversineDistance } from "$lib/models/gpx/utils";
|
import { haversineDistance } from "$lib/models/gpx/utils";
|
||||||
import { SummitLog } from "$lib/models/summit_log";
|
|
||||||
import type { Trail } from "$lib/models/trail";
|
import type { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
import { trails_create } from "$lib/stores/trail_store";
|
||||||
import { fetchGPX, trails_create } from "$lib/stores/trail_store";
|
|
||||||
import { handleError } from "$lib/util/api_util";
|
import { handleError } from "$lib/util/api_util";
|
||||||
import { fromFile, gpx2trail } from "$lib/util/gpx_util";
|
import { fromFile, gpx2trail } from "$lib/util/gpx_util";
|
||||||
import { json, type RequestEvent } from "@sveltejs/kit";
|
import { json, type RequestEvent } from "@sveltejs/kit";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
|
import type PocketBase from 'pocketbase';
|
||||||
|
|
||||||
export async function PUT(event: RequestEvent) {
|
export async function PUT(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
@@ -31,7 +30,7 @@ export async function PUT(event: RequestEvent) {
|
|||||||
if (!ignoreDuplicates) {
|
if (!ignoreDuplicates) {
|
||||||
let duplicate: Trail | null = null;
|
let duplicate: Trail | null = null;
|
||||||
try {
|
try {
|
||||||
duplicate = await findDuplicate(trail)
|
duplicate = await findDuplicate(event.locals.pb, trail)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
throw new ClientResponseError({ status: 500, response: { message: "Error checking for duplicates" } })
|
throw new ClientResponseError({ status: 500, response: { message: "Error checking for duplicates" } })
|
||||||
}
|
}
|
||||||
@@ -66,7 +65,7 @@ export async function PUT(event: RequestEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findDuplicate(t1: Trail) {
|
async function findDuplicate(pb: PocketBase, t1: Trail) {
|
||||||
const trails: Trail[] = await pb.collection('trails').getFullList({ requestKey: null });
|
const trails: Trail[] = await pb.collection('trails').getFullList({ requestKey: null });
|
||||||
|
|
||||||
const distanceThreshold = 100;
|
const distanceThreshold = 100;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { env } from '$env/dynamic/public';
|
import { env } from '$env/dynamic/public';
|
||||||
import { UserCreateSchema } from '$lib/models/api/user_schema';
|
import { UserCreateSchema } from '$lib/models/api/user_schema';
|
||||||
import type { User } from '$lib/models/user';
|
import type { User } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
import { Collection, handleError } from '$lib/util/api_util';
|
||||||
import { Collection, create, handleError } from '$lib/util/api_util';
|
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
import { ClientResponseError } from 'pocketbase';
|
import { ClientResponseError } from 'pocketbase';
|
||||||
|
|
||||||
@@ -16,9 +15,9 @@ export async function PUT(event: RequestEvent) {
|
|||||||
const data = await event.request.json();
|
const data = await event.request.json();
|
||||||
const safeData = UserCreateSchema.parse(data);
|
const safeData = UserCreateSchema.parse(data);
|
||||||
|
|
||||||
const r = await pb.collection(Collection.users).create<User>(safeData)
|
const r = await event.locals.pb.collection(Collection.users).create<User>(safeData)
|
||||||
|
|
||||||
await pb.collection('users').requestVerification(safeData.email);
|
await event.locals.pb.collection('users').requestVerification(safeData.email);
|
||||||
|
|
||||||
return json(r);
|
return json(r);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { RecordIdSchema } from '$lib/models/api/base_schema';
|
import { RecordIdSchema } from '$lib/models/api/base_schema';
|
||||||
import { UserUpdateSchema } from '$lib/models/api/user_schema';
|
import { UserUpdateSchema } from '$lib/models/api/user_schema';
|
||||||
import type { User } from '$lib/models/user';
|
import type { User } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, handleError, remove, show } from '$lib/util/api_util';
|
import { Collection, handleError, remove, show } from '$lib/util/api_util';
|
||||||
import { error, json, type RequestEvent } from '@sveltejs/kit'
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
export async function GET(event: RequestEvent) {
|
export async function GET(event: RequestEvent) {
|
||||||
try {
|
try {
|
||||||
@@ -23,13 +22,13 @@ export async function POST(event: RequestEvent) {
|
|||||||
|
|
||||||
const safeData = UserUpdateSchema.parse(data);
|
const safeData = UserUpdateSchema.parse(data);
|
||||||
|
|
||||||
if (safeData.email && safeData.email != pb.authStore.record!.email) {
|
if (safeData.email && safeData.email != event.locals.pb.authStore.record!.email) {
|
||||||
const r = await pb.collection('users').requestEmailChange(safeData.email);
|
const r = await event.locals.pb.collection('users').requestEmailChange(safeData.email);
|
||||||
pb.authStore.record!.email = safeData.email;
|
event.locals.pb.authStore.record!.email = safeData.email;
|
||||||
}
|
}
|
||||||
const r = await pb.collection('users').update<User>(safeParams.id, safeData)
|
const r = await event.locals.pb.collection('users').update<User>(safeParams.id, safeData)
|
||||||
if (safeData.password) {
|
if (safeData.password) {
|
||||||
const r = await pb.collection('users').authWithPassword(safeData.email ?? safeData.username!, safeData.password);
|
const r = await event.locals.pb.collection('users').authWithPassword(safeData.email ?? safeData.username!, safeData.password);
|
||||||
return json(r.record)
|
return json(r.record)
|
||||||
} else {
|
} else {
|
||||||
return json(r);
|
return json(r);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { UserAnonymous } from '$lib/models/user';
|
import type { UserAnonymous } from '$lib/models/user';
|
||||||
import { pb } from '$lib/pocketbase';
|
|
||||||
import { Collection, handleError, list } from '$lib/util/api_util';
|
import { Collection, handleError, list } from '$lib/util/api_util';
|
||||||
import { json, type RequestEvent } from '@sveltejs/kit';
|
import { json, type RequestEvent } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { Collection } from "$lib/util/api_util";
|
import { Collection } from "$lib/util/api_util";
|
||||||
import { error, type ServerLoad } from "@sveltejs/kit";
|
import { error, type ServerLoad } from "@sveltejs/kit";
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
@@ -9,7 +8,7 @@ export const load: ServerLoad = async ({ params, locals, url, fetch }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await pb.collection(Collection.users).confirmVerification(params.token)
|
await locals.pb.collection(Collection.users).confirmVerification(params.token)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ClientResponseError) {
|
if (e instanceof ClientResponseError) {
|
||||||
error(400, e.message);
|
error(400, e.message);
|
||||||
|
|||||||
@@ -5,11 +5,9 @@
|
|||||||
import StravaSettingsModal from "$lib/components/settings/integrations/strava_settings_modal.svelte";
|
import StravaSettingsModal from "$lib/components/settings/integrations/strava_settings_modal.svelte";
|
||||||
import {
|
import {
|
||||||
Integration,
|
Integration,
|
||||||
type BaseIntegration,
|
|
||||||
type KomootIntegration,
|
type KomootIntegration,
|
||||||
type StravaIntegration,
|
type StravaIntegration
|
||||||
} from "$lib/models/integration.js";
|
} from "$lib/models/integration.js";
|
||||||
import { pb } from "$lib/pocketbase.js";
|
|
||||||
import {
|
import {
|
||||||
integrations_create,
|
integrations_create,
|
||||||
integrations_update,
|
integrations_update,
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { pb } from "$lib/pocketbase";
|
import { error, redirect, type ServerLoad } from "@sveltejs/kit";
|
||||||
import { integrations_index, integrations_update } from "$lib/stores/integration_store";
|
|
||||||
import { error, redirect, type RequestEvent, type ServerLoad } from "@sveltejs/kit";
|
|
||||||
import { ClientResponseError } from "pocketbase";
|
import { ClientResponseError } from "pocketbase";
|
||||||
|
|
||||||
export const load: ServerLoad = async ({ url, fetch }) => {
|
export const load: ServerLoad = async ({ url, fetch, locals }) => {
|
||||||
const oauthError = url.searchParams.get('error');
|
const oauthError = url.searchParams.get('error');
|
||||||
if (oauthError) {
|
if (oauthError) {
|
||||||
// user cancelled
|
// user cancelled
|
||||||
@@ -22,7 +20,7 @@ export const load: ServerLoad = async ({ url, fetch }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await pb.send("/integration/strava/token", {
|
await locals.pb.send("/integration/strava/token", {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import { ExpandType } from "$lib/models/list";
|
import { ExpandType } from "$lib/models/list";
|
||||||
import { Trail } from "$lib/models/trail";
|
import { Trail } from "$lib/models/trail";
|
||||||
import { pb } from "$lib/pocketbase";
|
|
||||||
import { categories_index } from "$lib/stores/category_store";
|
import { categories_index } from "$lib/stores/category_store";
|
||||||
import { lists_index } from "$lib/stores/list_store";
|
import { lists_index } from "$lib/stores/list_store";
|
||||||
import { trails_show } from "$lib/stores/trail_store";
|
import { trails_show } from "$lib/stores/trail_store";
|
||||||
|
import { currentUser } from "$lib/stores/user_store";
|
||||||
import { error, type Load } from "@sveltejs/kit";
|
import { error, type Load } from "@sveltejs/kit";
|
||||||
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
export const load: Load = async ({ params, fetch }) => {
|
export const load: Load = async ({ params, fetch }) => {
|
||||||
|
const user = get(currentUser)
|
||||||
|
|
||||||
if (!params.id) {
|
if (!params.id) {
|
||||||
return error(400, "Bad Request")
|
return error(400, "Bad Request")
|
||||||
}
|
}
|
||||||
const categories = await categories_index(fetch)
|
const categories = await categories_index(fetch)
|
||||||
const lists = await lists_index({ q: "", author: pb.authStore.record?.id ?? "" }, 1, -1, fetch, ExpandType.None)
|
const lists = await lists_index({ q: "", author: user?.id ?? "" }, 1, -1, fetch, ExpandType.None)
|
||||||
|
|
||||||
let trail: Trail;
|
let trail: Trail;
|
||||||
if (params.id === "new") {
|
if (params.id === "new") {
|
||||||
trail = new Trail("", { category: categories[0] });
|
trail = new Trail("", { category: categories[0] });
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"tileSize": 256
|
"tileSize": 256
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"glyphs": "https://tiles.basemaps.cartocdn.com/fonts/{fontstack}/{range}.pbf",
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"id": "osm-tiles",
|
"id": "osm-tiles",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"tileSize": 256
|
"tileSize": 256
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"glyphs": "https://tiles.basemaps.cartocdn.com/fonts/{fontstack}/{range}.pbf",
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"id": "osm-tiles",
|
"id": "osm-tiles",
|
||||||
|
|||||||
Reference in New Issue
Block a user