fixes auto upload

This commit is contained in:
Christian Beutel
2024-11-09 11:57:55 +01:00
parent ce3d65d324
commit 00f689ec2f
7 changed files with 64 additions and 12 deletions

View File

@@ -32,7 +32,7 @@ upload_and_delete() {
ls $file ls $file
# API call to upload file # API call to upload file
response=$(curl -b cookie.txt --location --request PUT "$API_URL/trail/upload" --header 'Content-Type: application/gpx+xml' --data-binary "@$file") response=$(curl -b cookie.txt --location --request PUT "$API_URL/trail/upload" --header 'Content-Type: multipart/form-data' -F "file=@$file" -F "name=$base_name")
# Check if API call was successful (status code 200) # Check if API call was successful (status code 200)
if [ $? -eq 0 ] && [ "$(echo "$response" | grep -c "author")" -eq 1 ]; then if [ $? -eq 0 ] && [ "$(echo "$response" | grep -c "author")" -eq 1 ]; then

View File

@@ -4,11 +4,51 @@ import type { Settings } from '$lib/models/settings'
import { pb } from '$lib/pocketbase' import { pb } from '$lib/pocketbase'
import { isRouteProtected } from '$lib/util/authorization_util' import { isRouteProtected } from '$lib/util/authorization_util'
import { redirect, type Handle } from '@sveltejs/kit' import { json, redirect, text, type Handle } from '@sveltejs/kit'
import { sequence } from '@sveltejs/kit/hooks'
import { MeiliSearch } from 'meilisearch' import { MeiliSearch } from 'meilisearch'
import { locale } from 'svelte-i18n' import { locale } from 'svelte-i18n'
export const handle: Handle = async ({ event, resolve }) => {
function csrf(allowedPaths: string[]): Handle {
return async ({ event, resolve }) => {
const { request, url } = event;
const forbidden =
isFormContentType(request) &&
(request.method === "POST" ||
request.method === "PUT" ||
request.method === "PATCH" ||
request.method === "DELETE") &&
request.headers.get("origin") !== url.origin &&
!allowedPaths.includes(url.pathname);
if (forbidden) {
const message = `Cross-site ${request.method} form submissions are forbidden`;
if (request.headers.get("accept") === "application/json") {
return json({ message }, { status: 403 });
}
return text(message, { status: 403 });
}
return resolve(event);
};
}
function isContentType(request: Request, ...types: string[]) {
const type = request.headers.get("content-type")?.split(";", 1)[0].trim() ?? "";
return types.includes(type.toLowerCase());
}
function isFormContentType(request: Request) {
return isContentType(
request,
"application/x-www-form-urlencoded",
"multipart/form-data",
"text/plain",
);
}
const auth: Handle = async ({ event, resolve }) => {
// 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') || '')
@@ -69,4 +109,6 @@ export const handle: Handle = async ({ event, resolve }) => {
) )
return response return response
} }
export const handle = sequence(csrf(['/api/v1/trail/upload']), auth)

View File

@@ -5,7 +5,7 @@ class SummitLog {
date: string; date: string;
text?: string; text?: string;
gpx?: string; gpx?: string;
_gpx: File | null; _gpx: File | Blob | null;
distance?: number distance?: number
elevation_gain?: number elevation_gain?: number
elevation_loss?: number elevation_loss?: number

View File

@@ -39,10 +39,10 @@ export async function summit_logs_index(filter?: SummitLogFilter, f: (url: Reque
return fetchedSummitLogs; return fetchedSummitLogs;
} }
export async function summit_logs_create(summitLog: SummitLog) { export async function summit_logs_create(summitLog: SummitLog, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
summitLog.author = pb.authStore.model!.id summitLog.author = pb.authStore.model!.id
let r = await fetch('/api/v1/summit-log', { let r = await f('/api/v1/summit-log', {
method: 'PUT', method: 'PUT',
body: JSON.stringify(summitLog), body: JSON.stringify(summitLog),
}) })
@@ -58,7 +58,7 @@ export async function summit_logs_create(summitLog: SummitLog) {
formData.append("gpx", summitLog._gpx) formData.append("gpx", summitLog._gpx)
r = await fetch(`/api/v1/summit-log/${model.id!}/file`, { r = await f(`/api/v1/summit-log/${model.id!}/file`, {
method: 'POST', method: 'POST',
body: formData, body: formData,
}) })

View File

@@ -186,7 +186,7 @@ export async function trails_create(trail: Trail, photos: File[], gpx: File | Bl
trail.waypoints.push(model.id!); trail.waypoints.push(model.id!);
} }
for (const summitLog of trail.expand.summit_logs) { for (const summitLog of trail.expand.summit_logs) {
const model = await summit_logs_create(summitLog); const model = await summit_logs_create(summitLog, f);
trail.summit_logs.push(model.id!); trail.summit_logs.push(model.id!);
} }
@@ -373,7 +373,7 @@ export async function trails_upload(file: File, f: (url: RequestInfo | URL, conf
} }
} }
export async function fetchGPX(trail: { gpx: string } & Record<string, any>, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) { export async function fetchGPX(trail: { gpx?: string } & Record<string, any>, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
if (!trail.gpx) { if (!trail.gpx) {
return ""; return "";
} }

View File

@@ -1,3 +1,4 @@
import { SummitLog } from "$lib/models/summit_log";
import type { Trail } from "$lib/models/trail"; import type { Trail } from "$lib/models/trail";
import { trails_create } from "$lib/stores/trail_store"; import { trails_create } from "$lib/stores/trail_store";
import { fromFIT, fromKML, fromTCX, gpx2trail, isFITFile } from "$lib/util/gpx_util"; import { fromFIT, fromKML, fromTCX, gpx2trail, isFITFile } from "$lib/util/gpx_util";
@@ -11,8 +12,8 @@ export async function PUT(event: RequestEvent) {
const fileContent = await (data.get("file") as Blob).text(); const fileContent = await (data.get("file") as Blob).text();
let gpxData = "" let gpxData = ""
let gpxFile: Blob; let gpxFile: Blob;
if (isFITFile(fileBuffer)) { if (isFITFile(fileBuffer)) {
gpxData = await fromFIT(fileBuffer); gpxData = await fromFIT(fileBuffer);
gpxFile = new Blob([gpxData], { gpxFile = new Blob([gpxData], {
type: "application/gpx+xml", type: "application/gpx+xml",
}); });
@@ -37,6 +38,12 @@ export async function PUT(event: RequestEvent) {
let trail: Trail; let trail: Trail;
try { try {
trail = (await gpx2trail(gpxData, data.get("name") as string | undefined)).trail; trail = (await gpx2trail(gpxData, data.get("name") as string | undefined)).trail;
const log = new SummitLog(trail.date as string, {})
log.expand.gpx_data = gpxData;
log._gpx = gpxFile;
trail.expand.summit_logs.push(log);
} catch (e: any) { } catch (e: any) {
throw new ClientResponseError({ status: 400, response: { message: "Invalid file" } }) throw new ClientResponseError({ status: 400, response: { message: "Invalid file" } })
} }

View File

@@ -8,6 +8,9 @@ const config = {
preprocess: vitePreprocess(), preprocess: vitePreprocess(),
kit: { kit: {
csrf: {
checkOrigin: false
},
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter. // If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters. // See https://kit.svelte.dev/docs/adapters for more information about adapters.