mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-08-01 19:25:17 +02:00
Initial migration to new session based auth system with AllAuth
This commit is contained in:
parent
7defdac3a8
commit
9bc20be70e
24 changed files with 313 additions and 773 deletions
|
@ -1,95 +1,75 @@
|
|||
import type { Handle } from '@sveltejs/kit';
|
||||
import { sequence } from '@sveltejs/kit/hooks';
|
||||
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||
import { fetchCSRFToken, tryRefreshToken } from '$lib/index.server';
|
||||
|
||||
export const authHook: Handle = async ({ event, resolve }) => {
|
||||
try {
|
||||
let authCookie = event.cookies.get('auth');
|
||||
let refreshCookie = event.cookies.get('refresh');
|
||||
let sessionid = event.cookies.get('sessionid');
|
||||
console.log('sessionid:', sessionid);
|
||||
|
||||
if (!authCookie && !refreshCookie) {
|
||||
if (!sessionid) {
|
||||
console.log('No sessionid cookie');
|
||||
event.locals.user = null;
|
||||
return await resolve(event);
|
||||
}
|
||||
|
||||
if (!authCookie && refreshCookie) {
|
||||
event.locals.user = null;
|
||||
const token = await tryRefreshToken(event.cookies.get('refresh') || '');
|
||||
if (token) {
|
||||
authCookie = token;
|
||||
event.cookies.set('auth', authCookie, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
} else {
|
||||
return await resolve(event);
|
||||
}
|
||||
}
|
||||
// print all cookies in the request
|
||||
console.log('Cookies:', event.request.headers.get('cookie'));
|
||||
|
||||
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
|
||||
let userFetch = await event.fetch(`${serverEndpoint}/auth/user/`, {
|
||||
const cookie = event.request.headers.get('cookie') || '';
|
||||
|
||||
let userFetch = await event.fetch(`${serverEndpoint}/auth/user-metadata/`, {
|
||||
headers: {
|
||||
Cookie: `${authCookie}`
|
||||
cookie
|
||||
}
|
||||
});
|
||||
|
||||
if (!userFetch.ok) {
|
||||
console.log('Refreshing token');
|
||||
const refreshCookie = event.cookies.get('refresh');
|
||||
|
||||
if (refreshCookie) {
|
||||
const csrfToken = await fetchCSRFToken();
|
||||
if (!csrfToken) {
|
||||
console.error('Failed to fetch CSRF token');
|
||||
event.locals.user = null;
|
||||
return await resolve(event);
|
||||
}
|
||||
|
||||
const refreshFetch = await event.fetch(`${serverEndpoint}/auth/token/refresh/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ refresh: refreshCookie })
|
||||
});
|
||||
|
||||
if (refreshFetch.ok) {
|
||||
const refresh = await refreshFetch.json();
|
||||
event.cookies.set('auth', 'auth=' + refresh.access, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
|
||||
userFetch = await event.fetch(`${serverEndpoint}/auth/user/`, {
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: `auth=${refresh.access}`
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
event.locals.user = null;
|
||||
event.cookies.delete('sessionid', { path: '/' });
|
||||
return await resolve(event);
|
||||
}
|
||||
|
||||
if (userFetch.ok) {
|
||||
const user = await userFetch.json();
|
||||
event.locals.user = user;
|
||||
const setCookieHeader = userFetch.headers.get('Set-Cookie');
|
||||
|
||||
console.log('setCookieHeader:', setCookieHeader);
|
||||
|
||||
if (setCookieHeader) {
|
||||
// Regular expression to match sessionid cookie and its expiry
|
||||
const sessionIdRegex = /sessionid=([^;]+).*?expires=([^;]+)/;
|
||||
const match = setCookieHeader.match(sessionIdRegex);
|
||||
|
||||
if (match) {
|
||||
const sessionId = match[1];
|
||||
const expiryString = match[2];
|
||||
const expiryDate = new Date(expiryString);
|
||||
|
||||
console.log('Session ID:', sessionId);
|
||||
console.log('Expiry Date:', expiryDate);
|
||||
|
||||
// Set the sessionid cookie
|
||||
event.cookies.set('sessionid', sessionId, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: true,
|
||||
expires: expiryDate
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
event.locals.user = null;
|
||||
event.cookies.delete('auth', { path: '/' });
|
||||
event.cookies.delete('refresh', { path: '/' });
|
||||
event.cookies.delete('sessionid', { path: '/' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in authHook:', error);
|
||||
event.locals.user = null;
|
||||
event.cookies.delete('auth', { path: '/' });
|
||||
event.cookies.delete('refresh', { path: '/' });
|
||||
event.cookies.delete('sessionid', { path: '/' });
|
||||
}
|
||||
|
||||
return await resolve(event);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
console.log(res);
|
||||
let data = await res.json();
|
||||
console.log('ACTIVITIES' + data.activities);
|
||||
if (data && data.activities) {
|
||||
|
|
|
@ -444,6 +444,7 @@
|
|||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify(adventure)
|
||||
});
|
||||
let data = await res.json();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { redirect, type Actions } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||
const endpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
|
||||
|
@ -7,13 +8,16 @@ export const load = (async (event) => {
|
|||
if (!event.locals.user) {
|
||||
return redirect(302, '/login');
|
||||
}
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
let allActivities: string[] = [];
|
||||
let res = await fetch(`${endpoint}/api/activity-types/types/`, {
|
||||
let res = await event.fetch(`${endpoint}/api/activity-types/types/`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: `csrftoken=${csrfToken}`
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
console.log(res);
|
||||
let data = await res.json();
|
||||
if (data) {
|
||||
allActivities = data;
|
||||
|
@ -27,13 +31,16 @@ export const load = (async (event) => {
|
|||
|
||||
export const actions: Actions = {
|
||||
getActivities: async (event) => {
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
let allActivities: string[] = [];
|
||||
let res = await fetch(`${endpoint}/api/activity-types/types/`, {
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json',
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
Cookie: `csrftoken=${csrfToken}`
|
||||
}
|
||||
});
|
||||
console.log(res);
|
||||
let data = await res.json();
|
||||
if (data) {
|
||||
allActivities = data;
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
import { json } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from '../data/$types';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||
const endpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
|
||||
export const POST: RequestHandler = async (event) => {
|
||||
let allActivities: string[] = [];
|
||||
let res = await fetch(`${endpoint}/api/activity-types/types/`, {
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
let sessionId = event.cookies.get('sessionid');
|
||||
let res = await event.fetch(`${endpoint}/api/activity-types/types/`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: `csrftoken=${csrfToken}; sessionid=${sessionId}`
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
let data = await res.json();
|
||||
if (data) {
|
||||
|
|
|
@ -4,8 +4,7 @@ const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
|||
import type { Adventure } from '$lib/types';
|
||||
|
||||
import type { Actions } from '@sveltejs/kit';
|
||||
import { fetchCSRFToken, tryRefreshToken } from '$lib/index.server';
|
||||
import { checkLink } from '$lib';
|
||||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
|
||||
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
|
||||
|
@ -29,12 +28,13 @@ export const load = (async (event) => {
|
|||
const page = event.url.searchParams.get('page') || '1';
|
||||
const is_visited = event.url.searchParams.get('is_visited') || 'all';
|
||||
|
||||
let initialFetch = await fetch(
|
||||
let initialFetch = await event.fetch(
|
||||
`${serverEndpoint}/api/adventures/filtered?types=${typeString}&order_by=${order_by}&order_direction=${order_direction}&include_collections=${include_collections}&page=${page}&is_visited=${is_visited}`,
|
||||
{
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
||||
},
|
||||
credentials: 'include'
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -61,371 +61,15 @@ export const load = (async (event) => {
|
|||
}) satisfies PageServerLoad;
|
||||
|
||||
export const actions: Actions = {
|
||||
create: async (event) => {
|
||||
const formData = await event.request.formData();
|
||||
|
||||
const type = formData.get('type') as string;
|
||||
const name = formData.get('name') as string;
|
||||
const location = formData.get('location') as string | null;
|
||||
let date = (formData.get('date') as string | null) ?? null;
|
||||
const description = formData.get('description') as string | null;
|
||||
const activity_types = formData.get('activity_types')
|
||||
? (formData.get('activity_types') as string).split(',')
|
||||
: null;
|
||||
const rating = formData.get('rating') ? Number(formData.get('rating')) : null;
|
||||
let link = formData.get('link') as string | null;
|
||||
let latitude = formData.get('latitude') as string | null;
|
||||
let longitude = formData.get('longitude') as string | null;
|
||||
let collection = formData.get('collection') as string | null;
|
||||
let is_public = formData.get('is_public') as string | null | boolean;
|
||||
|
||||
if (is_public) {
|
||||
is_public = true;
|
||||
} else {
|
||||
is_public = false;
|
||||
}
|
||||
|
||||
// check if latitude and longitude are valid
|
||||
if (latitude && longitude) {
|
||||
if (isNaN(Number(latitude)) || isNaN(Number(longitude))) {
|
||||
return {
|
||||
status: 400,
|
||||
body: { error: 'Invalid latitude or longitude' }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// round latitude and longitude to 6 decimal places
|
||||
if (latitude) {
|
||||
latitude = Number(latitude).toFixed(6);
|
||||
}
|
||||
if (longitude) {
|
||||
longitude = Number(longitude).toFixed(6);
|
||||
}
|
||||
|
||||
const image = formData.get('image') as File;
|
||||
|
||||
if (!type || !name) {
|
||||
return {
|
||||
status: 400,
|
||||
body: { error: 'Missing required fields' }
|
||||
};
|
||||
}
|
||||
|
||||
if (date == null || date == '') {
|
||||
date = null;
|
||||
}
|
||||
|
||||
if (link) {
|
||||
link = checkLink(link);
|
||||
}
|
||||
|
||||
const formDataToSend = new FormData();
|
||||
formDataToSend.append('type', type);
|
||||
formDataToSend.append('name', name);
|
||||
formDataToSend.append('location', location || '');
|
||||
formDataToSend.append('date', date || '');
|
||||
formDataToSend.append('description', description || '');
|
||||
formDataToSend.append('latitude', latitude || '');
|
||||
formDataToSend.append('longitude', longitude || '');
|
||||
formDataToSend.append('is_public', is_public.toString());
|
||||
|
||||
if (!isNaN(Number(collection))) {
|
||||
if (collection !== null) {
|
||||
formDataToSend.append('collection', collection);
|
||||
}
|
||||
}
|
||||
|
||||
if (activity_types) {
|
||||
// Filter out empty and duplicate activity types, then trim each activity type
|
||||
const cleanedActivityTypes = Array.from(
|
||||
new Set(
|
||||
activity_types
|
||||
.map((activity_type) => activity_type.trim())
|
||||
.filter((activity_type) => activity_type !== '' && activity_type !== ',')
|
||||
)
|
||||
);
|
||||
|
||||
// Append each cleaned activity type to formDataToSend
|
||||
cleanedActivityTypes.forEach((activity_type) => {
|
||||
formDataToSend.append('activity_types', activity_type);
|
||||
});
|
||||
}
|
||||
formDataToSend.append('rating', rating ? rating.toString() : '');
|
||||
formDataToSend.append('link', link || '');
|
||||
// formDataToSend.append('image', image);
|
||||
|
||||
// log each key-value pair in the FormData
|
||||
for (let pair of formDataToSend.entries()) {
|
||||
console.log(pair[0] + ', ' + pair[1]);
|
||||
}
|
||||
|
||||
let auth = event.cookies.get('auth');
|
||||
|
||||
if (!auth) {
|
||||
const refresh = event.cookies.get('refresh');
|
||||
if (!refresh) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
let res = await tryRefreshToken(refresh);
|
||||
if (res) {
|
||||
auth = res;
|
||||
event.cookies.set('auth', auth, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
} else {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!auth) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
|
||||
const csrfToken = await fetchCSRFToken();
|
||||
|
||||
if (!csrfToken) {
|
||||
return {
|
||||
status: 500,
|
||||
body: { message: 'Failed to fetch CSRF token' }
|
||||
};
|
||||
}
|
||||
|
||||
const res = await fetch(`${serverEndpoint}/api/adventures/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: auth
|
||||
},
|
||||
body: formDataToSend
|
||||
});
|
||||
|
||||
let new_id = await res.json();
|
||||
|
||||
if (!res.ok) {
|
||||
const errorBody = await res.json();
|
||||
return {
|
||||
status: res.status,
|
||||
body: { error: errorBody }
|
||||
};
|
||||
}
|
||||
|
||||
let id = new_id.id;
|
||||
let user_id = new_id.user_id;
|
||||
let image_url = new_id.image;
|
||||
let link_url = new_id.link;
|
||||
|
||||
if (image && image.size > 0) {
|
||||
let imageForm = new FormData();
|
||||
imageForm.append('image', image);
|
||||
imageForm.append('adventure', id);
|
||||
let imageRes = await fetch(`${serverEndpoint}/api/images/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
},
|
||||
body: imageForm
|
||||
});
|
||||
let data = await imageRes.json();
|
||||
console.log(data);
|
||||
}
|
||||
|
||||
return { id, user_id, image_url, link };
|
||||
},
|
||||
edit: async (event) => {
|
||||
const formData = await event.request.formData();
|
||||
|
||||
const adventureId = formData.get('adventureId') as string;
|
||||
const type = formData.get('type') as string;
|
||||
const name = formData.get('name') as string;
|
||||
const location = formData.get('location') as string | null;
|
||||
let date = (formData.get('date') as string | null) ?? null;
|
||||
const description = formData.get('description') as string | null;
|
||||
let activity_types = formData.get('activity_types')
|
||||
? (formData.get('activity_types') as string).split(',')
|
||||
: null;
|
||||
const rating = formData.get('rating') ? Number(formData.get('rating')) : null;
|
||||
let link = formData.get('link') as string | null;
|
||||
let latitude = formData.get('latitude') as string | null;
|
||||
let longitude = formData.get('longitude') as string | null;
|
||||
let is_public = formData.get('is_public') as string | null | boolean;
|
||||
|
||||
if (is_public) {
|
||||
is_public = true;
|
||||
} else {
|
||||
is_public = false;
|
||||
}
|
||||
|
||||
// check if latitude and longitude are valid
|
||||
if (latitude && longitude) {
|
||||
if (isNaN(Number(latitude)) || isNaN(Number(longitude))) {
|
||||
return {
|
||||
status: 400,
|
||||
body: { error: 'Invalid latitude or longitude' }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// round latitude and longitude to 6 decimal places
|
||||
if (latitude) {
|
||||
latitude = Number(latitude).toFixed(6);
|
||||
}
|
||||
if (longitude) {
|
||||
longitude = Number(longitude).toFixed(6);
|
||||
}
|
||||
|
||||
const image = formData.get('image') as File;
|
||||
|
||||
// console.log(activity_types);
|
||||
|
||||
if (!type || !name) {
|
||||
return {
|
||||
status: 400,
|
||||
body: { error: 'Missing required fields' }
|
||||
};
|
||||
}
|
||||
|
||||
if (date == null || date == '') {
|
||||
date = null;
|
||||
}
|
||||
|
||||
if (link) {
|
||||
link = checkLink(link);
|
||||
}
|
||||
|
||||
const formDataToSend = new FormData();
|
||||
formDataToSend.append('type', type);
|
||||
formDataToSend.append('name', name);
|
||||
formDataToSend.append('location', location || '');
|
||||
formDataToSend.append('date', date || '');
|
||||
formDataToSend.append('description', description || '');
|
||||
formDataToSend.append('latitude', latitude || '');
|
||||
formDataToSend.append('longitude', longitude || '');
|
||||
formDataToSend.append('is_public', is_public.toString());
|
||||
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
|
||||
if (activity_types) {
|
||||
// Filter out empty and duplicate activity types, then trim each activity type
|
||||
const cleanedActivityTypes = Array.from(
|
||||
new Set(
|
||||
activity_types
|
||||
.map((activity_type) => activity_type.trim())
|
||||
.filter((activity_type) => activity_type !== '' && activity_type !== ',')
|
||||
)
|
||||
);
|
||||
|
||||
// Append each cleaned activity type to formDataToSend
|
||||
cleanedActivityTypes.forEach((activity_type) => {
|
||||
formDataToSend.append('activity_types', activity_type);
|
||||
});
|
||||
} else {
|
||||
let res = await fetch(`${serverEndpoint}/api/adventures/${adventureId}/`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`,
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ activity_types: [] })
|
||||
});
|
||||
if (!res.ok) {
|
||||
const errorBody = await res.json();
|
||||
return {
|
||||
status: res.status,
|
||||
body: { error: errorBody }
|
||||
};
|
||||
}
|
||||
}
|
||||
formDataToSend.append('rating', rating ? rating.toString() : '');
|
||||
formDataToSend.append('link', link || '');
|
||||
|
||||
if (image && image.size > 0) {
|
||||
formDataToSend.append('image', image);
|
||||
}
|
||||
|
||||
let auth = event.cookies.get('auth');
|
||||
|
||||
if (!auth) {
|
||||
const refresh = event.cookies.get('refresh');
|
||||
if (!refresh) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
let res = await tryRefreshToken(refresh);
|
||||
if (res) {
|
||||
auth = res;
|
||||
event.cookies.set('auth', auth, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
} else {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!auth) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
|
||||
if (!csrfToken) {
|
||||
return {
|
||||
status: 500,
|
||||
body: { message: 'Failed to fetch CSRF token' }
|
||||
};
|
||||
}
|
||||
|
||||
const res = await fetch(`${serverEndpoint}/api/adventures/${adventureId}/`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: auth
|
||||
},
|
||||
body: formDataToSend
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const errorBody = await res.json();
|
||||
return {
|
||||
status: res.status,
|
||||
body: { error: errorBody }
|
||||
};
|
||||
}
|
||||
|
||||
let adventure = await res.json();
|
||||
|
||||
let image_url = adventure.image;
|
||||
let link_url = adventure.link;
|
||||
return { image_url, link_url };
|
||||
},
|
||||
image: async (event) => {
|
||||
let formData = await event.request.formData();
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
let sessionId = event.cookies.get('sessionid');
|
||||
let res = await fetch(`${serverEndpoint}/api/images/`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
Cookie: `csrftoken=${csrfToken}; sessionid=${sessionId}`,
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
body: formData
|
||||
});
|
||||
|
|
|
@ -7,8 +7,9 @@ export const load = (async (event) => {
|
|||
const id = event.params as { id: string };
|
||||
let request = await fetch(`${endpoint}/api/adventures/${id.id}/`, {
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!request.ok) {
|
||||
console.error('Failed to fetch adventure ' + id.id);
|
||||
|
@ -24,8 +25,9 @@ export const load = (async (event) => {
|
|||
if (adventure.collection) {
|
||||
let res2 = await fetch(`${endpoint}/api/collections/${adventure.collection}/`, {
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
collection = await res2.json();
|
||||
}
|
||||
|
@ -39,8 +41,8 @@ export const load = (async (event) => {
|
|||
}
|
||||
}) satisfies PageServerLoad;
|
||||
|
||||
import type { Actions } from '@sveltejs/kit';
|
||||
import { tryRefreshToken } from '$lib/index.server';
|
||||
import { redirect, type Actions } from '@sveltejs/kit';
|
||||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
|
||||
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
|
||||
|
@ -50,29 +52,7 @@ export const actions: Actions = {
|
|||
const adventureId = id.id;
|
||||
|
||||
if (!event.locals.user) {
|
||||
const refresh = event.cookies.get('refresh');
|
||||
let auth = event.cookies.get('auth');
|
||||
if (!refresh) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
let res = await tryRefreshToken(refresh);
|
||||
if (res) {
|
||||
auth = res;
|
||||
event.cookies.set('auth', auth, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
} else {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
return redirect(302, '/login');
|
||||
}
|
||||
if (!adventureId) {
|
||||
return {
|
||||
|
@ -81,12 +61,15 @@ export const actions: Actions = {
|
|||
};
|
||||
}
|
||||
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
|
||||
let res = await fetch(`${serverEndpoint}/api/adventures/${event.params.id}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
Cookie: `sessionid=${event.cookies.get('sessionid')}; csrftoken=${csrfToken}`,
|
||||
'X-CSRFToken': csrfToken
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
console.log(res);
|
||||
if (!res.ok) {
|
||||
|
|
|
@ -1,69 +1,77 @@
|
|||
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||
const endpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function GET({ url, params, request, fetch, cookies }) {
|
||||
// add the param format = json to the url or add additional if anothre param is already present
|
||||
if (url.search) {
|
||||
url.search = url.search + '&format=json';
|
||||
} else {
|
||||
url.search = '?format=json';
|
||||
}
|
||||
return handleRequest(url, params, request, fetch, cookies);
|
||||
export async function GET(event) {
|
||||
const { url, params, request, fetch, cookies } = event;
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam);
|
||||
}
|
||||
|
||||
/** @type {import('./$types').RequestHandler} */
|
||||
export async function POST({ url, params, request, fetch, cookies }) {
|
||||
return handleRequest(url, params, request, fetch, cookies, true);
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
|
||||
}
|
||||
|
||||
export async function PATCH({ url, params, request, fetch, cookies }) {
|
||||
return handleRequest(url, params, request, fetch, cookies, true);
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
|
||||
}
|
||||
|
||||
export async function PUT({ url, params, request, fetch, cookies }) {
|
||||
return handleRequest(url, params, request, fetch, cookies, true);
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
|
||||
}
|
||||
|
||||
export async function DELETE({ url, params, request, fetch, cookies }) {
|
||||
return handleRequest(url, params, request, fetch, cookies, true);
|
||||
const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
|
||||
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
|
||||
}
|
||||
|
||||
// Implement other HTTP methods as needed (PUT, DELETE, etc.)
|
||||
|
||||
async function handleRequest(
|
||||
url: any,
|
||||
params: any,
|
||||
request: any,
|
||||
fetch: any,
|
||||
cookies: any,
|
||||
searchParam: string,
|
||||
requreTrailingSlash: boolean | undefined = false
|
||||
) {
|
||||
const path = params.path;
|
||||
let targetUrl = `${endpoint}/api/${path}${url.search}`;
|
||||
let targetUrl = `${endpoint}/api/${path}`;
|
||||
|
||||
// Ensure the path ends with a trailing slash
|
||||
if (requreTrailingSlash && !targetUrl.endsWith('/')) {
|
||||
targetUrl += '/';
|
||||
}
|
||||
|
||||
// Append query parameters to the path correctly
|
||||
targetUrl += searchParam; // This will add ?format=json or &format=json to the URL
|
||||
|
||||
const headers = new Headers(request.headers);
|
||||
|
||||
const authCookie = cookies.get('auth');
|
||||
|
||||
if (authCookie) {
|
||||
headers.set('Cookie', `${authCookie}`);
|
||||
const csrfToken = await fetchCSRFToken();
|
||||
if (!csrfToken) {
|
||||
return json({ error: 'CSRF token is missing or invalid' }, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(targetUrl, {
|
||||
method: request.method,
|
||||
headers: headers,
|
||||
body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined
|
||||
headers: {
|
||||
...Object.fromEntries(headers),
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: `csrftoken=${csrfToken}`
|
||||
},
|
||||
body:
|
||||
request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined,
|
||||
credentials: 'include' // This line ensures cookies are sent with the request
|
||||
});
|
||||
|
||||
if (response.status === 204) {
|
||||
// For 204 No Content, return a response with no body
|
||||
return new Response(null, {
|
||||
status: 204,
|
||||
headers: response.headers
|
||||
|
|
|
@ -17,10 +17,12 @@ export const load = (async (event) => {
|
|||
let previous = null;
|
||||
let count = 0;
|
||||
let adventures: Adventure[] = [];
|
||||
let sessionId = event.cookies.get('sessionid');
|
||||
let initialFetch = await fetch(`${serverEndpoint}/api/collections/?order_by=updated_at`, {
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
Cookie: `sessionid=${sessionId}`
|
||||
},
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!initialFetch.ok) {
|
||||
console.error('Failed to fetch visited adventures');
|
||||
|
@ -72,34 +74,9 @@ export const actions: Actions = {
|
|||
formDataToSend.append('start_date', start_date || '');
|
||||
formDataToSend.append('end_date', end_date || '');
|
||||
formDataToSend.append('link', link || '');
|
||||
let auth = event.cookies.get('auth');
|
||||
let sessionid = event.cookies.get('sessionid');
|
||||
|
||||
if (!auth) {
|
||||
const refresh = event.cookies.get('refresh');
|
||||
if (!refresh) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
let res = await tryRefreshToken(refresh);
|
||||
if (res) {
|
||||
auth = res;
|
||||
event.cookies.set('auth', auth, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
} else {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!auth) {
|
||||
if (!sessionid) {
|
||||
return {
|
||||
status: 401,
|
||||
body: { message: 'Unauthorized' }
|
||||
|
@ -119,7 +96,7 @@ export const actions: Actions = {
|
|||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: auth
|
||||
Cookie: `sessionid=${sessionid}; csrftoken=${csrfToken}`
|
||||
},
|
||||
body: formDataToSend
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import { fail, redirect } from '@sveltejs/kit';
|
|||
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
import { getRandomBackground, getRandomQuote } from '$lib';
|
||||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||
|
||||
export const load: PageServerLoad = async (event) => {
|
||||
|
@ -24,37 +25,29 @@ export const actions: Actions = {
|
|||
default: async (event) => {
|
||||
const formData = await event.request.formData();
|
||||
const formUsername = formData.get('username');
|
||||
const formPassword = formData.get('password');
|
||||
|
||||
let username = formUsername?.toString().toLocaleLowerCase();
|
||||
|
||||
const password = formData.get('password');
|
||||
|
||||
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
|
||||
const csrfTokenFetch = await event.fetch(`${serverEndpoint}/csrf/`);
|
||||
|
||||
if (!csrfTokenFetch.ok) {
|
||||
console.error('Failed to fetch CSRF token');
|
||||
event.locals.user = null;
|
||||
return fail(500, {
|
||||
message: 'Failed to fetch CSRF token'
|
||||
});
|
||||
}
|
||||
const csrfToken = await fetchCSRFToken();
|
||||
|
||||
const tokenPromise = await csrfTokenFetch.json();
|
||||
const csrfToken = tokenPromise.csrfToken;
|
||||
|
||||
const loginFetch = await event.fetch(`${serverEndpoint}/auth/login/`, {
|
||||
const loginFetch = await event.fetch(`${serverEndpoint}/_allauth/browser/v1/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json',
|
||||
Cookie: `csrftoken=${csrfToken}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username,
|
||||
password
|
||||
})
|
||||
}),
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
const loginResponse = await loginFetch.json();
|
||||
if (!loginFetch.ok) {
|
||||
// get the value of the first key in the object
|
||||
|
@ -64,25 +57,34 @@ export const actions: Actions = {
|
|||
message: error
|
||||
});
|
||||
} else {
|
||||
const token = loginResponse.access;
|
||||
const tokenFormatted = `auth=${token}`;
|
||||
const refreshToken = `${loginResponse.refresh}`;
|
||||
event.cookies.set('auth', tokenFormatted, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/',
|
||||
secure: false
|
||||
});
|
||||
event.cookies.set('refresh', refreshToken, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // 1 year
|
||||
path: '/',
|
||||
secure: false
|
||||
});
|
||||
const setCookieHeader = loginFetch.headers.get('Set-Cookie');
|
||||
|
||||
return redirect(302, '/');
|
||||
console.log('setCookieHeader:', setCookieHeader);
|
||||
|
||||
if (setCookieHeader) {
|
||||
// Regular expression to match sessionid cookie and its expiry
|
||||
const sessionIdRegex = /sessionid=([^;]+).*?expires=([^;]+)/;
|
||||
const match = setCookieHeader.match(sessionIdRegex);
|
||||
|
||||
if (match) {
|
||||
const sessionId = match[1];
|
||||
const expiryString = match[2];
|
||||
const expiryDate = new Date(expiryString);
|
||||
|
||||
console.log('Session ID:', sessionId);
|
||||
console.log('Expiry Date:', expiryDate);
|
||||
|
||||
// Set the sessionid cookie
|
||||
event.cookies.set('sessionid', sessionId, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: true,
|
||||
expires: expiryDate
|
||||
});
|
||||
}
|
||||
}
|
||||
redirect(302, '/');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { fetchCSRFToken } from '$lib/index.server';
|
||||
import { fail, type Actions } from '@sveltejs/kit';
|
||||
|
||||
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
|
||||
|
@ -13,10 +14,14 @@ export const actions: Actions = {
|
|||
return fail(400, { message: 'missing_email' });
|
||||
}
|
||||
|
||||
let res = await fetch(`${endpoint}/auth/password/reset/`, {
|
||||
let csrfToken = await fetchCSRFToken();
|
||||
|
||||
let res = await fetch(`${endpoint}/_allauth/browser/v1/auth/password/request`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken,
|
||||
Cookie: `csrftoken=${csrfToken}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email
|
||||
|
@ -25,10 +30,7 @@ export const actions: Actions = {
|
|||
|
||||
if (!res.ok) {
|
||||
let message = await res.json();
|
||||
|
||||
const key = Object.keys(message)[0];
|
||||
|
||||
return fail(res.status, { message: message[key] });
|
||||
return fail(res.status, message);
|
||||
}
|
||||
return { success: true };
|
||||
}
|
||||
|
|
|
@ -44,19 +44,23 @@ export const actions: Actions = {
|
|||
return fail(500, { message: 'Failed to fetch CSRF token' });
|
||||
}
|
||||
|
||||
if (password1 !== password2) {
|
||||
return fail(400, { message: 'Passwords do not match' });
|
||||
}
|
||||
|
||||
const tokenPromise = await csrfTokenFetch.json();
|
||||
const csrfToken = tokenPromise.csrfToken;
|
||||
|
||||
const loginFetch = await event.fetch(`${serverEndpoint}/auth/registration/`, {
|
||||
const loginFetch = await event.fetch(`${serverEndpoint}/_allauth/browser/v1/auth/signup`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': csrfToken,
|
||||
'Content-Type': 'application/json'
|
||||
'Content-Type': 'application/json',
|
||||
Cookie: `csrftoken=${csrfToken}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: username,
|
||||
password1: password1,
|
||||
password2: password2,
|
||||
password: password1,
|
||||
email: email,
|
||||
first_name,
|
||||
last_name
|
||||
|
@ -65,31 +69,36 @@ export const actions: Actions = {
|
|||
const loginResponse = await loginFetch.json();
|
||||
|
||||
if (!loginFetch.ok) {
|
||||
// get the value of the first key in the object
|
||||
const firstKey = Object.keys(loginResponse)[0] || 'error';
|
||||
const error =
|
||||
loginResponse[firstKey][0] || 'Failed to register user. Check your inputs and try again.';
|
||||
return fail(400, {
|
||||
message: error
|
||||
});
|
||||
return fail(loginFetch.status, loginResponse);
|
||||
} else {
|
||||
const token = loginResponse.access;
|
||||
const tokenFormatted = `auth=${token}`;
|
||||
const refreshToken = `${loginResponse.refresh}`;
|
||||
event.cookies.set('auth', tokenFormatted, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 60 * 60 * 1000), // 60 minutes
|
||||
path: '/'
|
||||
});
|
||||
event.cookies.set('refresh', refreshToken, {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
expires: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), // 1 year
|
||||
path: '/'
|
||||
});
|
||||
const setCookieHeader = loginFetch.headers.get('Set-Cookie');
|
||||
|
||||
return redirect(302, '/');
|
||||
console.log('setCookieHeader:', setCookieHeader);
|
||||
|
||||
if (setCookieHeader) {
|
||||
// Regular expression to match sessionid cookie and its expiry
|
||||
const sessionIdRegex = /sessionid=([^;]+).*?expires=([^;]+)/;
|
||||
const match = setCookieHeader.match(sessionIdRegex);
|
||||
|
||||
if (match) {
|
||||
const sessionId = match[1];
|
||||
const expiryString = match[2];
|
||||
const expiryDate = new Date(expiryString);
|
||||
|
||||
console.log('Session ID:', sessionId);
|
||||
console.log('Expiry Date:', expiryDate);
|
||||
|
||||
// Set the sessionid cookie
|
||||
event.cookies.set('sessionid', sessionId, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: true,
|
||||
expires: expiryDate
|
||||
});
|
||||
}
|
||||
}
|
||||
redirect(302, '/');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,11 +9,9 @@ export const load = (async (event) => {
|
|||
if (!event.locals.user) {
|
||||
return redirect(302, '/login');
|
||||
} else {
|
||||
const res = await fetch(`${endpoint}/api/countries/`, {
|
||||
const res = await event.fetch(`${endpoint}/api/countries/`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
Cookie: `${event.cookies.get('auth')}`
|
||||
}
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.error('Failed to fetch countries');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue