race condition security patch
This commit is contained in:
@@ -1,21 +1,26 @@
|
||||
<script lang="ts">
|
||||
import { afterNavigate, goto } from "$app/navigation";
|
||||
import { page } from "$app/state";
|
||||
import LogoText from "$lib/components/logo/logo_text.svelte";
|
||||
import { pb } from "$lib/pocketbase";
|
||||
import { theme, toggleTheme } from "$lib/stores/theme_store";
|
||||
import { currentUser, logout } from "$lib/stores/user_store";
|
||||
import { getFileURL } from "$lib/util/file_util";
|
||||
import type { AuthRecord } from "pocketbase";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { backInOut, cubicOut } from "svelte/easing";
|
||||
import { Tween } from "svelte/motion";
|
||||
import Drawer from "./base/drawer.svelte";
|
||||
import Dropdown from "./base/dropdown.svelte";
|
||||
import LogoTextLight from "./logo/logo_text_light.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";
|
||||
|
||||
interface Props {
|
||||
user: AuthRecord;
|
||||
}
|
||||
|
||||
let { user }: Props = $props();
|
||||
|
||||
let navBarItems = [
|
||||
{ text: "Home", value: "/" },
|
||||
{ text: $_("trail", { values: { n: 2 } }), value: "/trails" },
|
||||
@@ -107,8 +112,6 @@
|
||||
urlImportModal.openModal();
|
||||
}
|
||||
}
|
||||
|
||||
let user = $derived(browser ? $currentUser : pb.authStore.record);
|
||||
</script>
|
||||
|
||||
<Drawer bind:open={drawerOpen}>
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { List } from "$lib/models/list";
|
||||
import type { Trail } from "$lib/models/trail";
|
||||
import type { User, UserAnonymous } from "$lib/models/user";
|
||||
import { pb } from "$lib/pocketbase";
|
||||
import { users_show } from "$lib/stores/user_store";
|
||||
import type { UserAnonymous } from "$lib/models/user";
|
||||
import { currentUser, users_show } from "$lib/stores/user_store";
|
||||
import { getFileURL } from "$lib/util/file_util";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { fly, slide } from "svelte/transition";
|
||||
import { fly } from "svelte/transition";
|
||||
|
||||
interface Props {
|
||||
subject: Trail | List;
|
||||
@@ -16,12 +15,15 @@
|
||||
|
||||
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 loading: 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();
|
||||
|
||||
async function fetchInfo() {
|
||||
@@ -57,8 +59,9 @@
|
||||
{#if showInfo}
|
||||
<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"
|
||||
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}
|
||||
<div class="spinner spinner-dark"></div>
|
||||
{:else if infoLoaded && shareData}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
<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 emptyStateTrailLight from "$lib/assets/svgs/empty_states/empty_state_trail_light.svg";
|
||||
import type { Trail } from "$lib/models/trail";
|
||||
import { pb } from "$lib/pocketbase";
|
||||
import { theme } from "$lib/stores/theme_store";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { getFileURL, isVideoURL } from "$lib/util/file_util";
|
||||
import {
|
||||
formatDistance,
|
||||
@@ -14,7 +12,6 @@
|
||||
formatTimeHHMM,
|
||||
} from "$lib/util/format_util";
|
||||
import { _ } from "svelte-i18n";
|
||||
import ShareInfo from "../share_info.svelte";
|
||||
import type { MouseEventHandler } from "svelte/elements";
|
||||
import Chip from "../base/chip.svelte";
|
||||
|
||||
@@ -75,13 +72,13 @@
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if (trail.public || trailIsShared) && pb.authStore.record}
|
||||
{#if (trail.public || trailIsShared) && $currentUser}
|
||||
<div
|
||||
class="flex absolute top-4 right-4 {trail.public && trailIsShared
|
||||
? 'w-14'
|
||||
: '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
|
||||
class="tooltip"
|
||||
class:mr-2={trail.public && trailIsShared}
|
||||
|
||||
@@ -9,18 +9,17 @@
|
||||
} from "$lib/stores/list_store";
|
||||
import { show_toast } from "$lib/stores/toast_store.svelte";
|
||||
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 { gpx } from "$lib/vendor/toGeoJSON/toGeoJSON";
|
||||
import JSZip from "jszip";
|
||||
import { _ } from "svelte-i18n";
|
||||
import Dropdown, { type DropdownItem } from "../base/dropdown.svelte";
|
||||
import ConfirmModal from "../confirm_modal.svelte";
|
||||
import ListSelectModal from "../list/list_select_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 { currentUser } from "$lib/stores/user_store";
|
||||
import { pb } from "$lib/pocketbase";
|
||||
|
||||
interface Props {
|
||||
trail: Trail;
|
||||
@@ -62,10 +61,10 @@
|
||||
]
|
||||
: []),
|
||||
{ text: $_("print"), value: "print", icon: "print" },
|
||||
...(trail.author != pb.authStore.record?.id
|
||||
...(trail.author != $currentUser?.id
|
||||
? []
|
||||
: [{ text: $_("add-to-list"), value: "list", icon: "bookmark" }]),
|
||||
...(trail.author != pb.authStore.record?.id
|
||||
...(trail.author != $currentUser?.id
|
||||
? []
|
||||
: [{ text: $_("share"), value: "share", icon: "share" }]),
|
||||
...(allowEdit
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { Category } from "$lib/models/category";
|
||||
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 { getIconForLocation } from "$lib/util/icon_util";
|
||||
import { _ } from "svelte-i18n";
|
||||
import { slide } from "svelte/transition";
|
||||
import Combobox, { type ComboboxItem } from "../base/combobox.svelte";
|
||||
import Datepicker from "../base/datepicker.svelte";
|
||||
import DoubleSlider from "../base/double_slider.svelte";
|
||||
import MultiSelect from "../base/multi_select.svelte";
|
||||
@@ -14,12 +17,7 @@
|
||||
import type { SelectItem } from "../base/select.svelte";
|
||||
import Slider from "../base/slider.svelte";
|
||||
import UserSearch from "../user_search.svelte";
|
||||
import { pb } from "$lib/pocketbase";
|
||||
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";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
|
||||
interface Props {
|
||||
categories: Category[];
|
||||
@@ -199,7 +197,7 @@
|
||||
></Combobox>
|
||||
<hr class="my-4 border-separator" />
|
||||
|
||||
{#if pb.authStore.record}
|
||||
{#if $currentUser}
|
||||
<UserSearch
|
||||
onclick={(item) => setAuthorFilter(item)}
|
||||
onclear={() => {
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
import { browser } from "$app/environment";
|
||||
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 { pb } from "$lib/pocketbase";
|
||||
import { theme } from "$lib/stores/theme_store";
|
||||
import { show_toast } from "$lib/stores/toast_store.svelte";
|
||||
import * as M from "maplibre-gl";
|
||||
@@ -31,6 +30,7 @@
|
||||
import { onMount } from "svelte";
|
||||
import { _ } from "svelte-i18n";
|
||||
import Button from "../base/button.svelte";
|
||||
import Chip from "../base/chip.svelte";
|
||||
import SkeletonNotificationCard from "../base/skeleton_notification_card.svelte";
|
||||
import Textarea from "../base/textarea.svelte";
|
||||
import CommentCard from "../comment/comment_card.svelte";
|
||||
@@ -42,7 +42,6 @@
|
||||
import SummitLogTable from "../summit_log/summit_log_table.svelte";
|
||||
import MapWithElevationMaplibre from "./map_with_elevation_maplibre.svelte";
|
||||
import TrailTimeline from "./trail_timeline.svelte";
|
||||
import Chip from "../base/chip.svelte";
|
||||
|
||||
interface Props {
|
||||
initTrail: Trail;
|
||||
@@ -63,7 +62,7 @@
|
||||
const tabs = [
|
||||
$_("summit-book"),
|
||||
$_("photos"),
|
||||
...(pb.authStore.record ? [$_("comment", { values: { n: 2 } })] : []),
|
||||
...($currentUser ? [$_("comment", { values: { n: 2 } })] : []),
|
||||
];
|
||||
|
||||
const trailIsShared =
|
||||
@@ -234,13 +233,13 @@
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if (trail.public || trailIsShared) && pb.authStore.record}
|
||||
{#if (trail.public || trailIsShared) && $currentUser}
|
||||
<div
|
||||
class="flex {trail.public && trailIsShared
|
||||
? 'w-16'
|
||||
: 'w-8'} h-8 rounded-full items-center"
|
||||
>
|
||||
{#if trail.public && pb.authStore.record}
|
||||
{#if trail.public && $currentUser}
|
||||
<span
|
||||
class:tooltip={mode != "map"}
|
||||
class:mr-3={trail.public && trailIsShared}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
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 type { Trail } from "$lib/models/trail";
|
||||
import { pb } from "$lib/pocketbase";
|
||||
import { theme } from "$lib/stores/theme_store";
|
||||
import { currentUser } from "$lib/stores/user_store";
|
||||
import { getFileURL, isVideoURL } from "$lib/util/file_util";
|
||||
import {
|
||||
formatDistance,
|
||||
@@ -12,7 +12,6 @@
|
||||
} from "$lib/util/format_util";
|
||||
import { _ } from "svelte-i18n";
|
||||
import ShareInfo from "../share_info.svelte";
|
||||
import Chip from "../base/chip.svelte";
|
||||
|
||||
interface Props {
|
||||
trail: Trail;
|
||||
@@ -55,7 +54,7 @@
|
||||
<h4 class="font-semibold text-lg">
|
||||
{trail.name}
|
||||
</h4>
|
||||
{#if trail.public && pb.authStore.record}
|
||||
{#if trail.public && $currentUser}
|
||||
<span class="tooltip ml-3" data-title={$_("public")}>
|
||||
<i class="fa fa-globe"></i>
|
||||
</span>
|
||||
|
||||
Reference in New Issue
Block a user