1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-21 22:09:36 +02:00

refactor: Update API endpoint paths from "_allauth" to "auth" for consistency

This commit is contained in:
Sean Morley 2025-02-23 17:04:20 -05:00
parent d5311bb71e
commit b1068d27b0
16 changed files with 56 additions and 202 deletions

View file

@ -1,31 +1,6 @@
class AppVersionMiddleware: from django.conf import settings
def __init__(self, get_response): from django.utils.deprecation import MiddlewareMixin
self.get_response = get_response
def __call__(self, request):
# Process request (if needed)
response = self.get_response(request)
# Add custom header to response
# Replace with your app version
response['X-AdventureLog-Version'] = '1.0.0'
return response
# make a middlewra that prints all of the request cookies
class PrintCookiesMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print(request.COOKIES)
response = self.get_response(request)
return response
# middlewares.py
import os import os
from django.http import HttpRequest
class OverrideHostMiddleware: class OverrideHostMiddleware:
def __init__(self, get_response): def __init__(self, get_response):
@ -44,3 +19,14 @@ class OverrideHostMiddleware:
response = self.get_response(request) response = self.get_response(request)
return response return response
class XSessionTokenMiddleware(MiddlewareMixin):
def process_request(self, request):
session_token = request.headers.get('X-Session-Token')
if session_token:
request.COOKIES[settings.SESSION_COOKIE_NAME] = session_token
class DisableCSRFForSessionTokenMiddleware(MiddlewareMixin):
def process_request(self, request):
if 'X-Session-Token' in request.headers:
setattr(request, '_dont_enforce_csrf_checks', True)

View file

@ -133,35 +133,6 @@ class AdventureViewSet(viewsets.ModelViewSet):
serializer = self.get_serializer(queryset, many=True) serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data) return Response(serializer.data)
@action(detail=False, methods=['get'])
def search(self, request):
query = request.query_params.get('query', '')
property = request.query_params.get('property', 'all')
if len(query) < 2:
return Response({"error": "Query must be at least 2 characters long"}, status=400)
valid_properties = ['name', 'location', 'description', 'activity_types']
if property not in valid_properties:
property = 'all'
filters = {
'name': Q(name__icontains=query),
'location': Q(location__icontains=query),
'description': Q(description__icontains=query),
'activity_types': Q(activity_types__icontains=query),
'all': Q(name__icontains=query) | Q(description__icontains=query) |
Q(location__icontains=query) | Q(activity_types__icontains=query)
}
queryset = Adventure.objects.filter(
filters[property] & (Q(user_id=request.user.id) | Q(is_public=True))
)
queryset = self.apply_sorting(queryset)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
instance = self.get_object() instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=True) serializer = self.get_serializer(instance, data=request.data, partial=True)

View file

@ -69,6 +69,8 @@ INSTALLED_APPS = (
MIDDLEWARE = ( MIDDLEWARE = (
'whitenoise.middleware.WhiteNoiseMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware',
'adventures.middleware.XSessionTokenMiddleware',
'adventures.middleware.DisableCSRFForSessionTokenMiddleware',
'corsheaders.middleware.CorsMiddleware', 'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@ -133,6 +135,8 @@ FRONTEND_URL = unParsedFrontenedUrl.translate(str.maketrans('', '', '\'"'))
SESSION_COOKIE_SAMESITE = 'Lax' SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_NAME = 'sessionid'
SESSION_COOKIE_SECURE = FRONTEND_URL.startswith('https') SESSION_COOKIE_SECURE = FRONTEND_URL.startswith('https')
hostname = urlparse(FRONTEND_URL).hostname hostname = urlparse(FRONTEND_URL).hostname

View file

@ -15,7 +15,7 @@ schema_view = get_schema_view(
urlpatterns = [ urlpatterns = [
path('api/', include('adventures.urls')), path('api/', include('adventures.urls')),
path('api/', include('worldtravel.urls')), path('api/', include('worldtravel.urls')),
path("_allauth/", include("allauth.headless.urls")), path("auth/", include("allauth.headless.urls")),
# Serve protected media files # Serve protected media files
re_path(r'^media/(?P<path>.*)$', serve_protected_media, name='serve-protected-media'), re_path(r'^media/(?P<path>.*)$', serve_protected_media, name='serve-protected-media'),

View file

@ -8,7 +8,7 @@ class UserAPITestCase(APITestCase):
def setUp(self): def setUp(self):
# Signup a new user # Signup a new user
response = self.client.post('/_allauth/browser/v1/auth/signup', { response = self.client.post('/auth/browser/v1/auth/signup', {
'username': 'testuser', 'username': 'testuser',
'email': 'testuser@example.com', 'email': 'testuser@example.com',
'password': 'testpassword', 'password': 'testpassword',
@ -63,7 +63,7 @@ class UserAPITestCase(APITestCase):
def test_003_user_add_email(self): def test_003_user_add_email(self):
# Update user email # Update user email
response = self.client.post('/_allauth/browser/v1/account/email', { response = self.client.post('/auth/browser/v1/account/email', {
'email': 'testuser2@example.com', 'email': 'testuser2@example.com',
}, format='json') }, format='json')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)

View file

@ -37,7 +37,7 @@
} }
async function fetchSetupInfo() { async function fetchSetupInfo() {
const res = await fetch('/_allauth/browser/v1/account/authenticators/totp', { const res = await fetch('/auth/browser/v1/account/authenticators/totp', {
method: 'GET' method: 'GET'
}); });
const data = await res.json(); const data = await res.json();
@ -53,7 +53,7 @@
} }
async function sendTotp() { async function sendTotp() {
const res = await fetch('/_allauth/browser/v1/account/authenticators/totp', { const res = await fetch('/auth/browser/v1/account/authenticators/totp', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -78,7 +78,7 @@
async function getRecoveryCodes() { async function getRecoveryCodes() {
console.log('getting recovery codes'); console.log('getting recovery codes');
const res = await fetch('/_allauth/browser/v1/account/authenticators/recovery-codes', { const res = await fetch('/auth/browser/v1/account/authenticators/recovery-codes', {
method: 'GET' method: 'GET'
}); });
if (res.ok) { if (res.ok) {

View file

@ -41,7 +41,7 @@ export const actions: Actions = {
return; return;
} }
const res = await fetch(`${serverEndpoint}/_allauth/browser/v1/auth/session`, { const res = await fetch(`${serverEndpoint}/auth/browser/v1/auth/session`, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View file

@ -1,101 +0,0 @@
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(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 }) {
const searchParam = url.search ? `${url.search}` : '';
return handleRequest(url, params, request, fetch, cookies, searchParam, false);
}
export async function PATCH({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : '';
return handleRequest(url, params, request, fetch, cookies, searchParam, false);
}
export async function PUT({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : '';
return handleRequest(url, params, request, fetch, cookies, searchParam, false);
}
export async function DELETE({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : '';
return handleRequest(url, params, request, fetch, cookies, searchParam, false);
}
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}/_allauth/${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);
// Delete existing csrf cookie by setting an expired date
cookies.delete('csrftoken', { path: '/' });
// Generate a new csrf token (using your existing fetchCSRFToken function)
const csrfToken = await fetchCSRFToken();
if (!csrfToken) {
return json({ error: 'CSRF token is missing or invalid' }, { status: 400 });
}
// Set the new csrf token in both headers and cookies
const cookieHeader = `csrftoken=${csrfToken}; Path=/; HttpOnly; SameSite=Lax`;
try {
const response = await fetch(targetUrl, {
method: request.method,
headers: {
...Object.fromEntries(headers),
'X-CSRFToken': csrfToken,
Cookie: cookieHeader
},
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) {
return new Response(null, {
status: 204,
headers: response.headers
});
}
const responseData = await response.text();
// Create a new Headers object without the 'set-cookie' header
const cleanHeaders = new Headers(response.headers);
cleanHeaders.delete('set-cookie');
return new Response(responseData, {
status: response.status,
headers: cleanHeaders
});
} catch (error) {
console.error('Error forwarding request:', error);
return json({ error: 'Internal Server Error' }, { status: 500 });
}
}

View file

@ -12,8 +12,8 @@ export async function GET(event) {
/** @type {import('./$types').RequestHandler} */ /** @type {import('./$types').RequestHandler} */
export async function POST({ url, params, request, fetch, cookies }) { export async function POST({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}&format=json` : '?format=json'; const searchParam = url.search ? `${url.search}` : '';
return handleRequest(url, params, request, fetch, cookies, searchParam, true); return handleRequest(url, params, request, fetch, cookies, searchParam, false);
} }
export async function PATCH({ url, params, request, fetch, cookies }) { export async function PATCH({ url, params, request, fetch, cookies }) {
@ -27,8 +27,8 @@ export async function PUT({ url, params, request, fetch, cookies }) {
} }
export async function DELETE({ url, params, request, fetch, cookies }) { export async function DELETE({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}&format=json` : '?format=json'; const searchParam = url.search ? `${url.search}` : '';
return handleRequest(url, params, request, fetch, cookies, searchParam, true); return handleRequest(url, params, request, fetch, cookies, searchParam, false);
} }
async function handleRequest( async function handleRequest(

View file

@ -42,7 +42,7 @@ export const actions: Actions = {
const csrfToken = await fetchCSRFToken(); const csrfToken = await fetchCSRFToken();
// Initial login attempt // Initial login attempt
const loginFetch = await event.fetch(`${serverEndpoint}/_allauth/browser/v1/auth/login`, { const loginFetch = await event.fetch(`${serverEndpoint}/auth/browser/v1/auth/login`, {
method: 'POST', method: 'POST',
headers: { headers: {
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
@ -69,7 +69,7 @@ export const actions: Actions = {
// Attempt MFA authentication // Attempt MFA authentication
const sessionId = extractSessionId(loginFetch.headers.get('Set-Cookie')); const sessionId = extractSessionId(loginFetch.headers.get('Set-Cookie'));
const mfaLoginFetch = await event.fetch( const mfaLoginFetch = await event.fetch(
`${serverEndpoint}/_allauth/browser/v1/auth/2fa/authenticate`, `${serverEndpoint}/auth/browser/v1/auth/2fa/authenticate`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {

View file

@ -31,7 +31,7 @@ export const load: PageServerLoad = async (event) => {
}); });
let user = (await res.json()) as User; let user = (await res.json()) as User;
let emailFetch = await fetch(`${endpoint}/_allauth/browser/v1/account/email`, { let emailFetch = await fetch(`${endpoint}/auth/browser/v1/account/email`, {
headers: { headers: {
Cookie: `sessionid=${sessionId}` Cookie: `sessionid=${sessionId}`
} }
@ -45,14 +45,11 @@ export const load: PageServerLoad = async (event) => {
return redirect(302, '/'); return redirect(302, '/');
} }
let mfaAuthenticatorFetch = await fetch( let mfaAuthenticatorFetch = await fetch(`${endpoint}/auth/browser/v1/account/authenticators`, {
`${endpoint}/_allauth/browser/v1/account/authenticators`, headers: {
{ Cookie: `sessionid=${sessionId}`
headers: {
Cookie: `sessionid=${sessionId}`
}
} }
); });
let mfaAuthenticatorResponse = (await mfaAuthenticatorFetch.json()) as MFAAuthenticatorResponse; let mfaAuthenticatorResponse = (await mfaAuthenticatorFetch.json()) as MFAAuthenticatorResponse;
let authenticators = (mfaAuthenticatorResponse.data.length > 0) as boolean; let authenticators = (mfaAuthenticatorResponse.data.length > 0) as boolean;
@ -208,7 +205,7 @@ export const actions: Actions = {
let csrfToken = await fetchCSRFToken(); let csrfToken = await fetchCSRFToken();
if (current_password) { if (current_password) {
let res = await fetch(`${endpoint}/_allauth/browser/v1/account/password/change`, { let res = await fetch(`${endpoint}/auth/browser/v1/account/password/change`, {
method: 'POST', method: 'POST',
headers: { headers: {
Referer: event.url.origin, // Include Referer header Referer: event.url.origin, // Include Referer header
@ -226,7 +223,7 @@ export const actions: Actions = {
} }
return { success: true }; return { success: true };
} else { } else {
let res = await fetch(`${endpoint}/_allauth/browser/v1/account/password/change`, { let res = await fetch(`${endpoint}/auth/browser/v1/account/password/change`, {
method: 'POST', method: 'POST',
headers: { headers: {
Referer: event.url.origin, // Include Referer header Referer: event.url.origin, // Include Referer header

View file

@ -72,7 +72,7 @@
} }
async function removeEmail(email: { email: any; verified?: boolean; primary?: boolean }) { async function removeEmail(email: { email: any; verified?: boolean; primary?: boolean }) {
let res = await fetch('/_allauth/browser/v1/account/email/', { let res = await fetch('/auth/browser/v1/account/email', {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -88,7 +88,7 @@
} }
async function verifyEmail(email: { email: any; verified?: boolean; primary?: boolean }) { async function verifyEmail(email: { email: any; verified?: boolean; primary?: boolean }) {
let res = await fetch('/_allauth/browser/v1/account/email/', { let res = await fetch('/auth/browser/v1/account/email/', {
method: 'PUT', method: 'PUT',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -103,7 +103,7 @@
} }
async function addEmail() { async function addEmail() {
let res = await fetch('/_allauth/browser/v1/account/email/', { let res = await fetch('/auth/browser/v1/account/email/', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -122,7 +122,7 @@
} }
async function primaryEmail(email: { email: any; verified?: boolean; primary?: boolean }) { async function primaryEmail(email: { email: any; verified?: boolean; primary?: boolean }) {
let res = await fetch('/_allauth/browser/v1/account/email/', { let res = await fetch('/auth/browser/v1/account/email/', {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@ -194,7 +194,7 @@
} }
async function disableMfa() { async function disableMfa() {
const res = await fetch('/_allauth/browser/v1/account/authenticators/totp', { const res = await fetch('/auth/browser/v1/account/authenticators/totp', {
method: 'DELETE' method: 'DELETE'
}); });
if (res.ok) { if (res.ok) {

View file

@ -51,7 +51,7 @@ export const actions: Actions = {
const tokenPromise = await csrfTokenFetch.json(); const tokenPromise = await csrfTokenFetch.json();
const csrfToken = tokenPromise.csrfToken; const csrfToken = tokenPromise.csrfToken;
const loginFetch = await event.fetch(`${serverEndpoint}/_allauth/browser/v1/auth/signup`, { const loginFetch = await event.fetch(`${serverEndpoint}/auth/browser/v1/auth/signup`, {
method: 'POST', method: 'POST',
headers: { headers: {
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,

View file

@ -16,7 +16,7 @@ export const actions: Actions = {
let csrfToken = await fetchCSRFToken(); let csrfToken = await fetchCSRFToken();
let res = await fetch(`${endpoint}/_allauth/browser/v1/auth/password/request`, { let res = await fetch(`${endpoint}/auth/browser/v1/auth/password/request`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View file

@ -29,20 +29,17 @@ export const actions: Actions = {
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000'; const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
const csrfToken = await fetchCSRFToken(); const csrfToken = await fetchCSRFToken();
const response = await event.fetch( const response = await event.fetch(`${serverEndpoint}/auth/browser/v1/auth/password/reset`, {
`${serverEndpoint}/_allauth/browser/v1/auth/password/reset`, headers: {
{ 'Content-Type': 'application/json',
headers: { Cookie: `csrftoken=${csrfToken}`,
'Content-Type': 'application/json', 'X-CSRFToken': csrfToken,
Cookie: `csrftoken=${csrfToken}`, Referer: event.url.origin // Include Referer header
'X-CSRFToken': csrfToken, },
Referer: event.url.origin // Include Referer header method: 'POST',
}, credentials: 'include',
method: 'POST', body: JSON.stringify({ key: key, password: password })
credentials: 'include', });
body: JSON.stringify({ key: key, password: password })
}
);
if (response.status !== 401) { if (response.status !== 401) {
const error_message = await response.json(); const error_message = await response.json();

View file

@ -11,7 +11,7 @@ export const load = (async (event) => {
const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000'; const serverEndpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
const csrfToken = await fetchCSRFToken(); const csrfToken = await fetchCSRFToken();
let verifyFetch = await event.fetch(`${serverEndpoint}/_allauth/browser/v1/auth/email/verify`, { let verifyFetch = await event.fetch(`${serverEndpoint}/auth/browser/v1/auth/email/verify`, {
headers: { headers: {
Cookie: `csrftoken=${csrfToken}`, Cookie: `csrftoken=${csrfToken}`,
'X-CSRFToken': csrfToken 'X-CSRFToken': csrfToken