1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-08-02 19:55:18 +02:00

Merge branch 'development' into fix/zh-translation

This commit is contained in:
Sean Morley 2025-03-03 23:37:56 -05:00 committed by GitHub
commit b7d6d6af56
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 180 additions and 262 deletions

View file

@ -1,31 +1,6 @@
class AppVersionMiddleware:
def __init__(self, get_response):
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
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
import os
from django.http import HttpRequest
class OverrideHostMiddleware:
def __init__(self, get_response):
@ -44,3 +19,14 @@ class OverrideHostMiddleware:
response = self.get_response(request)
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)
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):
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=True)

View file

@ -14,13 +14,13 @@ class StatsViewSet(viewsets.ViewSet):
"""
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):
if request.user.username == username:
user = get_object_or_404(User, username=username)
else:
user = get_object_or_404(User, username=username, public_profile=True)
serializer = PublicUserSerializer(user)
# serializer = PublicUserSerializer(user)
# remove the email address from the response
user.email = None

View file

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

View file

@ -15,7 +15,7 @@ schema_view = get_schema_view(
urlpatterns = [
path('api/', include('adventures.urls')),
path('api/', include('worldtravel.urls')),
path("_allauth/", include("allauth.headless.urls")),
path("auth/", include("allauth.headless.urls")),
# Serve protected media files
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):
# Signup a new user
response = self.client.post('/_allauth/browser/v1/auth/signup', {
response = self.client.post('/auth/browser/v1/auth/signup', {
'username': 'testuser',
'email': 'testuser@example.com',
'password': 'testpassword',
@ -63,7 +63,7 @@ class UserAPITestCase(APITestCase):
def test_003_user_add_email(self):
# 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',
}, format='json')
self.assertEqual(response.status_code, 200)

View file

@ -49,9 +49,9 @@
reverseGeocode();
}
if (!item.name) {
item.name = markers[0].name;
}
// if (!item.name) {
// item.name = markers[0].name;
// }
}
$: if (triggerMarkVisted && willBeMarkedVisited) {
@ -193,7 +193,7 @@
) {
old_display_name = reverseGeocodePlace.display_name;
item.location = reverseGeocodePlace.display_name;
if (reverseGeocodePlace.location_name) {
if (reverseGeocodePlace.location_name && !item.name) {
item.name = reverseGeocodePlace.location_name;
}
}
@ -270,6 +270,8 @@
activity_type: place.type
}
];
item.name = place.name;
}}
>
{place.display_name}

View file

@ -37,7 +37,7 @@
}
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'
});
const data = await res.json();
@ -53,7 +53,7 @@
}
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',
headers: {
'Content-Type': 'application/json'
@ -78,7 +78,7 @@
async function getRecoveryCodes() {
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'
});
if (res.ok) {

View file

@ -246,7 +246,8 @@
"lodging_information": "Unterkunftsinformationen",
"price": "Preis",
"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": {
"desc_1": "Entdecken, planen und erkunden Sie mit Leichtigkeit",

View file

@ -113,6 +113,7 @@
"copy_link": "Copy Link",
"image": "Image",
"upload_image": "Upload Image",
"open_in_maps": "Open in Maps",
"url": "URL",
"fetch_image": "Fetch Image",
"wikipedia": "Wikipedia",

View file

@ -294,7 +294,8 @@
"price": "Precio",
"region": "Región",
"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": {
"all": "Todo",

View file

@ -246,7 +246,8 @@
"price": "Prix",
"region": "Région",
"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": {
"desc_1": "Découvrez, planifiez et explorez en toute simplicité",

View file

@ -246,7 +246,8 @@
"price": "Prezzo",
"region": "Regione",
"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": {
"desc_1": "Scopri, pianifica ed esplora con facilità",

View file

@ -246,7 +246,8 @@
"price": "가격",
"region": "지역",
"reservation_number": "예약 번호",
"welcome_map_info": "이 서버의 공개 모험"
"welcome_map_info": "이 서버의 공개 모험",
"open_in_maps": "지도에서 열립니다"
},
"auth": {
"both_passwords_required": "두 암호 모두 필요합니다",

View file

@ -246,7 +246,8 @@
"lodging_delete_confirm": "Weet u zeker dat u deze accommodatielocatie wilt verwijderen? \nDeze actie kan niet ongedaan worden gemaakt.",
"lodging_information": "Informatie overliggen",
"price": "Prijs",
"region": "Regio"
"region": "Regio",
"open_in_maps": "Open in kaarten"
},
"home": {
"desc_1": "Ontdek, plan en verken met gemak",

View file

@ -294,7 +294,8 @@
"price": "Cena",
"region": "Region",
"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": {
"country_list": "Lista krajów",

View file

@ -246,7 +246,8 @@
"lodging_information": "Logi information",
"price": "Pris",
"region": "Område",
"reservation_number": "Bokningsnummer"
"reservation_number": "Bokningsnummer",
"open_in_maps": "Kappas in"
},
"home": {
"desc_1": "Upptäck, planera och utforska med lätthet",

View file

@ -294,7 +294,83 @@
},
"lodging_information": "住宿信息",
"price": "价格",
"reservation_number": "预订号码"
"region": "地区",
"reservation_number": "预订号",
"welcome_map_info": "该服务器上的公共冒险",
"open_in_maps": "在地图上打开"
},
"home": {
"desc_1": "轻松发现、规划和探索",
"desc_2": "AdventureLog 旨在简化您的旅程,为您提供工具和资源来计划、打包和导航您的下一次难忘的冒险。",
"feature_1": "旅行日志",
"feature_1_desc": "通过个性化的旅行日志记录您的冒险经历,并与朋友和家人分享您的经历。",
"feature_2": "旅行计划",
"feature_2_desc": "轻松创建自定义行程并获取行程的每日详细信息。",
"feature_3": "旅游地图",
"feature_3_desc": "使用交互式地图查看您在世界各地的旅行并探索新的目的地。",
"go_to": "前往冒险日志",
"hero_1": "探索世界上最惊险的冒险",
"hero_2": "使用 AdventureLog 发现并计划您的下一次冒险。\n探索令人惊叹的目的地、创建定制行程并随时随地保持联系。",
"key_features": "主要特点"
},
"navbar": {
"about": "关于冒险日志",
"adventures": "冒险",
"collections": "收藏",
"discord": "不和谐",
"documentation": "文档",
"greeting": "你好",
"logout": "退出",
"map": "地图",
"my_adventures": "我的冒险",
"profile": "轮廓",
"search": "搜索",
"settings": "设置",
"shared_with_me": "与我分享",
"theme_selection": "主题选择",
"themes": {
"aqua": "阿夸",
"dark": "黑暗的",
"forest": "森林",
"light": "光",
"night": "夜晚",
"aestheticDark": "审美黑暗",
"aestheticLight": "美学之光",
"northernLights": "北极光"
},
"users": "用户",
"worldtravel": "环球旅行",
"my_tags": "我的标签",
"tag": "标签",
"language_selection": "语言",
"support": "支持",
"calendar": "日历",
"admin_panel": "管理面板"
},
"auth": {
"forgot_password": "忘记密码?",
"login": "登录",
"login_error": "无法使用提供的凭据登录。",
"password": "密码",
"signup": "报名",
"username": "用户名",
"confirm_password": "确认密码",
"email": "电子邮件",
"first_name": "名",
"last_name": "姓",
"registration_disabled": "目前已禁用注册。",
"profile_picture": "个人资料图片",
"public_profile": "公开资料",
"public_tooltip": "通过公开个人资料,用户可以与您共享收藏并在用户页面上查看您的个人资料。",
"email_required": "电子邮件为必填项",
"both_passwords_required": "两个密码都需要",
"new_password": "新密码",
"reset_failed": "重置密码失败",
"or_3rd_party": "或者使用第三方服务登录",
"no_public_adventures": "找不到公共冒险",
"no_public_collections": "找不到公共收藏",
"user_adventures": "用户冒险",
"user_collections": "用户收集"
},
"worldtravel": {
"all": "全部",

View file

@ -41,7 +41,7 @@ export const actions: Actions = {
return;
}
const res = await fetch(`${serverEndpoint}/_allauth/browser/v1/auth/session`, {
const res = await fetch(`${serverEndpoint}/auth/browser/v1/auth/session`, {
method: 'DELETE',
headers: {
'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

@ -436,6 +436,12 @@
</div>
</div>
{/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
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"

View file

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

View file

@ -773,46 +773,6 @@
</div>
{/if}
{#if notes.length > 0}
<h1 class="text-center font-bold text-4xl mt-4 mb-4">{$t('adventures.notes')}</h1>
<div class="flex flex-wrap gap-4 mr-4 justify-center content-center">
{#each notes as note}
<NoteCard
{note}
user={data.user || null}
on:edit={(event) => {
noteToEdit = event.detail;
isNoteModalOpen = true;
}}
on:delete={(event) => {
notes = notes.filter((n) => n.id != event.detail);
}}
{collection}
/>
{/each}
</div>
{/if}
{#if checklists.length > 0}
<h1 class="text-center font-bold text-4xl mt-4 mb-4">{$t('adventures.checklists')}</h1>
<div class="flex flex-wrap gap-4 mr-4 justify-center content-center">
{#each checklists as checklist}
<ChecklistCard
{checklist}
user={data.user || null}
on:delete={(event) => {
checklists = checklists.filter((n) => n.id != event.detail);
}}
on:edit={(event) => {
checklistToEdit = event.detail;
isShowingChecklistModal = true;
}}
{collection}
/>
{/each}
</div>
{/if}
<!-- if none found -->
{#if adventures.length == 0 && transportations.length == 0 && notes.length == 0 && checklists.length == 0 && lodging.length == 0}
<NotFound error={undefined} />

View file

@ -21,7 +21,7 @@ export const load = (async (event) => {
let stats = null;
let res = await event.fetch(
`${serverEndpoint}/api/stats/counts/${event.locals.user.username}`,
`${serverEndpoint}/api/stats/counts/${event.locals.user.username}/`,
{
headers: {
Cookie: `sessionid=${event.cookies.get('sessionid')}`

View file

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

View file

@ -163,10 +163,21 @@
{/each}
</p>
{/if}
<button
class="btn btn-neutral btn-wide btn-sm mt-4"
on:click={() => goto(`/adventures/${adventure.id}`)}>{$t('map.view_details')}</button
>
<div class="flex flex-col">
{#if adventure.longitude && adventure.latitude}
<a
class="btn btn-neutral btn-wide btn-sm mt-4"
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>
{/if}
</Marker>

View file

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

View file

@ -72,7 +72,7 @@
}
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',
headers: {
'Content-Type': 'application/json'
@ -88,7 +88,7 @@
}
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',
headers: {
'Content-Type': 'application/json'
@ -103,7 +103,7 @@
}
async function addEmail() {
let res = await fetch('/_allauth/browser/v1/account/email/', {
let res = await fetch('/auth/browser/v1/account/email/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
@ -122,7 +122,7 @@
}
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',
headers: {
'Content-Type': 'application/json'
@ -194,7 +194,7 @@
}
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'
});
if (res.ok) {

View file

@ -51,7 +51,7 @@ export const actions: Actions = {
const tokenPromise = await csrfTokenFetch.json();
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',
headers: {
'X-CSRFToken': csrfToken,

View file

@ -16,7 +16,7 @@ export const actions: Actions = {
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',
headers: {
'Content-Type': 'application/json',

View file

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