mirror of
https://github.com/seanmorley15/AdventureLog.git
synced 2025-07-20 13:29:37 +02:00
Open Locations in Maps and new API Routes
This commit is contained in:
commit
ed76c1426e
31 changed files with 105 additions and 222 deletions
|
@ -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)
|
|
@ -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)
|
||||||
|
|
|
@ -14,13 +14,13 @@ class StatsViewSet(viewsets.ViewSet):
|
||||||
"""
|
"""
|
||||||
A simple ViewSet for listing the stats of a user.
|
A simple ViewSet for listing the stats of a user.
|
||||||
"""
|
"""
|
||||||
@action(detail=False, methods=['get'], url_path='counts/(?P<username>[^/]+)')
|
@action(detail=False, methods=['get'], url_path='counts/(?P<username>[\w.@+-]+)')
|
||||||
def counts(self, request, username):
|
def counts(self, request, username):
|
||||||
if request.user.username == username:
|
if request.user.username == username:
|
||||||
user = get_object_or_404(User, username=username)
|
user = get_object_or_404(User, username=username)
|
||||||
else:
|
else:
|
||||||
user = get_object_or_404(User, username=username, public_profile=True)
|
user = get_object_or_404(User, username=username, public_profile=True)
|
||||||
serializer = PublicUserSerializer(user)
|
# serializer = PublicUserSerializer(user)
|
||||||
|
|
||||||
# remove the email address from the response
|
# remove the email address from the response
|
||||||
user.email = None
|
user.email = None
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -49,9 +49,9 @@
|
||||||
reverseGeocode();
|
reverseGeocode();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.name) {
|
// if (!item.name) {
|
||||||
item.name = markers[0].name;
|
// item.name = markers[0].name;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
$: if (triggerMarkVisted && willBeMarkedVisited) {
|
$: if (triggerMarkVisted && willBeMarkedVisited) {
|
||||||
|
@ -193,7 +193,7 @@
|
||||||
) {
|
) {
|
||||||
old_display_name = reverseGeocodePlace.display_name;
|
old_display_name = reverseGeocodePlace.display_name;
|
||||||
item.location = reverseGeocodePlace.display_name;
|
item.location = reverseGeocodePlace.display_name;
|
||||||
if (reverseGeocodePlace.location_name) {
|
if (reverseGeocodePlace.location_name && !item.name) {
|
||||||
item.name = reverseGeocodePlace.location_name;
|
item.name = reverseGeocodePlace.location_name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,6 +270,8 @@
|
||||||
activity_type: place.type
|
activity_type: place.type
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
item.name = place.name;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{place.display_name}
|
{place.display_name}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"lodging_information": "Unterkunftsinformationen",
|
"lodging_information": "Unterkunftsinformationen",
|
||||||
"price": "Preis",
|
"price": "Preis",
|
||||||
"reservation_number": "Reservierungsnummer",
|
"reservation_number": "Reservierungsnummer",
|
||||||
"welcome_map_info": "Öffentliche Abenteuer auf diesem Server"
|
"welcome_map_info": "Öffentliche Abenteuer auf diesem Server",
|
||||||
|
"open_in_maps": "In Karten geöffnet"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit",
|
"desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit",
|
||||||
|
|
|
@ -113,6 +113,7 @@
|
||||||
"copy_link": "Copy Link",
|
"copy_link": "Copy Link",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"upload_image": "Upload Image",
|
"upload_image": "Upload Image",
|
||||||
|
"open_in_maps": "Open in Maps",
|
||||||
"url": "URL",
|
"url": "URL",
|
||||||
"fetch_image": "Fetch Image",
|
"fetch_image": "Fetch Image",
|
||||||
"wikipedia": "Wikipedia",
|
"wikipedia": "Wikipedia",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"price": "Precio",
|
"price": "Precio",
|
||||||
"region": "Región",
|
"region": "Región",
|
||||||
"reservation_number": "Número de reserva",
|
"reservation_number": "Número de reserva",
|
||||||
"welcome_map_info": "Aventuras públicas en este servidor"
|
"welcome_map_info": "Aventuras públicas en este servidor",
|
||||||
|
"open_in_maps": "Abrir en mapas"
|
||||||
},
|
},
|
||||||
"worldtravel": {
|
"worldtravel": {
|
||||||
"all": "Todo",
|
"all": "Todo",
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"price": "Prix",
|
"price": "Prix",
|
||||||
"region": "Région",
|
"region": "Région",
|
||||||
"reservation_number": "Numéro de réservation",
|
"reservation_number": "Numéro de réservation",
|
||||||
"welcome_map_info": "Aventures publiques sur ce serveur"
|
"welcome_map_info": "Aventures publiques sur ce serveur",
|
||||||
|
"open_in_maps": "Ouvert dans les cartes"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"desc_1": "Découvrez, planifiez et explorez en toute simplicité",
|
"desc_1": "Découvrez, planifiez et explorez en toute simplicité",
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"price": "Prezzo",
|
"price": "Prezzo",
|
||||||
"region": "Regione",
|
"region": "Regione",
|
||||||
"welcome_map_info": "Avventure pubbliche su questo server",
|
"welcome_map_info": "Avventure pubbliche su questo server",
|
||||||
"reservation_number": "Numero di prenotazione"
|
"reservation_number": "Numero di prenotazione",
|
||||||
|
"open_in_maps": "Aperto in mappe"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"desc_1": "Scopri, pianifica ed esplora con facilità",
|
"desc_1": "Scopri, pianifica ed esplora con facilità",
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"price": "가격",
|
"price": "가격",
|
||||||
"region": "지역",
|
"region": "지역",
|
||||||
"reservation_number": "예약 번호",
|
"reservation_number": "예약 번호",
|
||||||
"welcome_map_info": "이 서버의 공개 모험"
|
"welcome_map_info": "이 서버의 공개 모험",
|
||||||
|
"open_in_maps": "지도에서 열립니다"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"both_passwords_required": "두 암호 모두 필요합니다",
|
"both_passwords_required": "두 암호 모두 필요합니다",
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"lodging_delete_confirm": "Weet u zeker dat u deze accommodatielocatie wilt verwijderen? \nDeze actie kan niet ongedaan worden gemaakt.",
|
"lodging_delete_confirm": "Weet u zeker dat u deze accommodatielocatie wilt verwijderen? \nDeze actie kan niet ongedaan worden gemaakt.",
|
||||||
"lodging_information": "Informatie overliggen",
|
"lodging_information": "Informatie overliggen",
|
||||||
"price": "Prijs",
|
"price": "Prijs",
|
||||||
"region": "Regio"
|
"region": "Regio",
|
||||||
|
"open_in_maps": "Open in kaarten"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"desc_1": "Ontdek, plan en verken met gemak",
|
"desc_1": "Ontdek, plan en verken met gemak",
|
||||||
|
|
|
@ -294,7 +294,8 @@
|
||||||
"price": "Cena",
|
"price": "Cena",
|
||||||
"region": "Region",
|
"region": "Region",
|
||||||
"reservation_number": "Numer rezerwacji",
|
"reservation_number": "Numer rezerwacji",
|
||||||
"welcome_map_info": "Publiczne przygody na tym serwerze"
|
"welcome_map_info": "Publiczne przygody na tym serwerze",
|
||||||
|
"open_in_maps": "Otwarte w mapach"
|
||||||
},
|
},
|
||||||
"worldtravel": {
|
"worldtravel": {
|
||||||
"country_list": "Lista krajów",
|
"country_list": "Lista krajów",
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"lodging_information": "Logi information",
|
"lodging_information": "Logi information",
|
||||||
"price": "Pris",
|
"price": "Pris",
|
||||||
"region": "Område",
|
"region": "Område",
|
||||||
"reservation_number": "Bokningsnummer"
|
"reservation_number": "Bokningsnummer",
|
||||||
|
"open_in_maps": "Kappas in"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"desc_1": "Upptäck, planera och utforska med lätthet",
|
"desc_1": "Upptäck, planera och utforska med lätthet",
|
||||||
|
|
|
@ -246,7 +246,8 @@
|
||||||
"price": "价格",
|
"price": "价格",
|
||||||
"region": "地区",
|
"region": "地区",
|
||||||
"reservation_number": "预订号",
|
"reservation_number": "预订号",
|
||||||
"welcome_map_info": "该服务器上的公共冒险"
|
"welcome_map_info": "该服务器上的公共冒险",
|
||||||
|
"open_in_maps": "在地图上打开"
|
||||||
},
|
},
|
||||||
"home": {
|
"home": {
|
||||||
"desc_1": "轻松发现、规划和探索",
|
"desc_1": "轻松发现、规划和探索",
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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 });
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -436,6 +436,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
<a
|
||||||
|
class="btn btn-neutral btn-sm max-w-32"
|
||||||
|
href={`https://maps.apple.com/?q=${adventure.latitude},${adventure.longitude}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">{$t('adventures.open_in_maps')}</a
|
||||||
|
>
|
||||||
<MapLibre
|
<MapLibre
|
||||||
style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
|
style="https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json"
|
||||||
class="flex items-center self-center justify-center aspect-[9/16] max-h-[70vh] sm:aspect-video sm:max-h-full w-10/12 rounded-lg"
|
class="flex items-center self-center justify-center aspect-[9/16] max-h-[70vh] sm:aspect-video sm:max-h-full w-10/12 rounded-lg"
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const load = (async (event) => {
|
||||||
let stats = null;
|
let stats = null;
|
||||||
|
|
||||||
let res = await event.fetch(
|
let res = await event.fetch(
|
||||||
`${serverEndpoint}/api/stats/counts/${event.locals.user.username}`,
|
`${serverEndpoint}/api/stats/counts/${event.locals.user.username}/`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
Cookie: `sessionid=${event.cookies.get('sessionid')}`
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -163,10 +163,21 @@
|
||||||
{/each}
|
{/each}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
<button
|
<div class="flex flex-col">
|
||||||
|
{#if adventure.longitude && adventure.latitude}
|
||||||
|
<a
|
||||||
class="btn btn-neutral btn-wide btn-sm mt-4"
|
class="btn btn-neutral btn-wide btn-sm mt-4"
|
||||||
on:click={() => goto(`/adventures/${adventure.id}`)}>{$t('map.view_details')}</button
|
href={`https://maps.apple.com/?q=${adventure.latitude},${adventure.longitude}`}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer">{$t('adventures.open_in_maps')}</a
|
||||||
>
|
>
|
||||||
|
{/if}
|
||||||
|
<button
|
||||||
|
class="btn btn-neutral btn-wide btn-sm mt-2"
|
||||||
|
on:click={() => goto(`/adventures/${adventure.id}`)}
|
||||||
|
>{$t('map.view_details')}</button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</Popup>
|
</Popup>
|
||||||
{/if}
|
{/if}
|
||||||
</Marker>
|
</Marker>
|
||||||
|
|
|
@ -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: {
|
headers: {
|
||||||
Cookie: `sessionid=${sessionId}`
|
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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -29,9 +29,7 @@ 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: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
Cookie: `csrftoken=${csrfToken}`,
|
Cookie: `csrftoken=${csrfToken}`,
|
||||||
|
@ -41,8 +39,7 @@ export const actions: Actions = {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
body: JSON.stringify({ key: key, password: password })
|
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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue