1
0
Fork 0
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:
Sean Morley 2024-11-29 14:41:13 -05:00
parent 7defdac3a8
commit 9bc20be70e
24 changed files with 313 additions and 773 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -444,6 +444,7 @@
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify(adventure)
});
let data = await res.json();

View file

@ -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;

View file

@ -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) {

View file

@ -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
});

View file

@ -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) {

View file

@ -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

View file

@ -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
});

View file

@ -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, '/');
}
}
};

View file

@ -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 };
}

View file

@ -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, '/');
}
}
};

View file

@ -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');