Skip to content

Commit 78fac21

Browse files
authored
Merge pull request #2791 from appwrite/fix-state-login-issue
2 parents 06d34f2 + 3514c8b commit 78fac21

File tree

6 files changed

+144
-46
lines changed

6 files changed

+144
-46
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
"@melt-ui/svelte": "^0.86.6",
6262
"@playwright/test": "^1.56.0",
6363
"@sveltejs/adapter-static": "^3.0.10",
64-
"@sveltejs/kit": "^2.46.2",
64+
"@sveltejs/kit": "^2.49.5",
6565
"@sveltejs/vite-plugin-svelte": "^5.1.1",
6666
"@testing-library/dom": "^10.4.1",
6767
"@testing-library/jest-dom": "^6.9.1",
@@ -83,7 +83,7 @@
8383
"prettier": "^3.6.2",
8484
"prettier-plugin-svelte": "^3.4.0",
8585
"sass": "^1.93.2",
86-
"svelte": "^5.45.5",
86+
"svelte": "^5.6.2",
8787
"svelte-check": "^4.3.2",
8888
"svelte-preprocess": "^6.0.3",
8989
"svelte-sequential-preprocessor": "^2.0.2",

pnpm-lock.yaml

Lines changed: 21 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/helpers/oauth.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
type BuildOAuthSuccessUrlParams = {
2+
pageUrl: URL;
3+
basePath: string;
4+
origin: string;
5+
isStudio: boolean;
6+
};
7+
8+
export const STUDIO_PROMPT_KEY = 'studioPrompt';
9+
const ABSOLUTE_URL = /^[a-zA-Z][a-zA-Z\d+.-]*:/;
10+
11+
function isAbsoluteUrl(value: string): boolean {
12+
return ABSOLUTE_URL.test(value) || value.startsWith('//');
13+
}
14+
15+
function stashStudioPrompt(prompt: string, isStudio: boolean): void {
16+
if (!isStudio || !prompt) {
17+
return;
18+
}
19+
20+
try {
21+
sessionStorage.setItem(STUDIO_PROMPT_KEY, prompt);
22+
} catch {
23+
// ignore
24+
}
25+
}
26+
27+
function formatUrl(url: URL, original: string): string {
28+
if (isAbsoluteUrl(original)) {
29+
return url.toString();
30+
}
31+
32+
return `${url.pathname}${url.search}${url.hash}`;
33+
}
34+
35+
function stripPromptFromTarget(target: string, isStudio: boolean): string {
36+
if (!isStudio) {
37+
return target;
38+
}
39+
40+
try {
41+
const url = new URL(target, window.location.origin);
42+
const prompt = url.searchParams.get('prompt');
43+
44+
if (prompt) {
45+
stashStudioPrompt(prompt, isStudio);
46+
url.searchParams.delete('prompt');
47+
}
48+
49+
return formatUrl(url, target);
50+
} catch {
51+
return target;
52+
}
53+
}
54+
55+
function appendQuery(target: string, params: URLSearchParams): string {
56+
const query = params.toString();
57+
if (!query) {
58+
return target;
59+
}
60+
61+
const hashIndex = target.indexOf('#');
62+
const hash = hashIndex >= 0 ? target.slice(hashIndex) : '';
63+
const base = hashIndex >= 0 ? target.slice(0, hashIndex) : target;
64+
const separator = base.includes('?') ? '&' : '?';
65+
66+
return `${base}${separator}${query}${hash}`;
67+
}
68+
69+
export function buildOAuthSuccessUrl({
70+
pageUrl,
71+
basePath,
72+
origin,
73+
isStudio
74+
}: BuildOAuthSuccessUrlParams): string {
75+
const params = new URLSearchParams(pageUrl.search);
76+
const redirect = params.get('redirect');
77+
78+
if (redirect) {
79+
params.delete('redirect');
80+
}
81+
82+
if (isStudio) {
83+
const prompt = params.get('prompt');
84+
if (prompt) {
85+
stashStudioPrompt(prompt, isStudio);
86+
params.delete('prompt');
87+
}
88+
}
89+
90+
let target = redirect ? stripPromptFromTarget(redirect, isStudio) : basePath;
91+
target = appendQuery(target, params);
92+
93+
if (isAbsoluteUrl(target)) {
94+
return target;
95+
}
96+
97+
return origin + target;
98+
}

src/routes/(public)/(guest)/login/+page.svelte

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44
import { Button, Form, InputEmail, InputPassword } from '$lib/elements/forms';
55
import { addNotification } from '$lib/stores/notifications';
66
import { sdk } from '$lib/stores/sdk';
7+
import { buildOAuthSuccessUrl } from '$lib/helpers/oauth';
78
import { Dependencies } from '$lib/constants';
89
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
910
import { page } from '$app/state';
1011
import { redirectTo } from '$routes/store';
1112
import { user } from '$lib/stores/user';
1213
import { Layout } from '@appwrite.io/pink-svelte';
13-
import { Logins, resolvedProfile } from '$lib/profiles/index.svelte';
14+
import { Logins, ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte';
1415
import type { OAuthProvider } from '@appwrite.io/console';
1516
import type { PageProps } from './$types.js';
1617
@@ -71,20 +72,17 @@
7172
7273
function onOauthLogin(config: { provider: OAuthProvider; scopes: string[] }) {
7374
clearAuthToken();
74-
let url = window.location.origin;
7575
76-
if (page.url.searchParams) {
77-
const redirect = page.url.searchParams.get('redirect');
78-
page.url.searchParams.delete('redirect');
79-
if (redirect) {
80-
url = `${redirect}${page.url.search}`;
81-
} else {
82-
url = `${base}${page.url.search ?? ''}`;
83-
}
84-
}
76+
const successUrl = buildOAuthSuccessUrl({
77+
pageUrl: page.url,
78+
basePath: base,
79+
origin: window.location.origin,
80+
isStudio: resolvedProfile.id === ProfileMode.STUDIO
81+
});
82+
8583
sdk.forConsole.account.createOAuth2Session({
8684
provider: config.provider,
87-
success: window.location.origin + url,
85+
success: successUrl,
8886
failure: window.location.origin,
8987
scopes: config.scopes
9088
});

src/routes/(public)/auth/preview/access/+page.svelte

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
} from '$lib/elements/forms';
1818
import { logout } from '$lib/helpers/logout';
1919
import { sdk } from '$lib/stores/sdk';
20+
import { buildOAuthSuccessUrl } from '$lib/helpers/oauth';
2021
import { isCloud } from '$lib/system';
2122
import { ID, OAuthProvider } from '@appwrite.io/console';
2223
import { Layout, Typography } from '@appwrite.io/pink-svelte';
2324
import { onMount } from 'svelte';
2425
import BGDark from './bg_dark.jpg';
2526
import BGLight from './bg_light.jpg';
2627
import { app } from '$lib/stores/app.js';
27-
import { resolvedProfile } from '$lib/profiles/index.svelte';
28+
import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte';
2829
2930
export let data;
3031
@@ -88,20 +89,16 @@
8889
}
8990
9091
function onGithubAuth() {
91-
let url = window.location.origin;
92+
const successUrl = buildOAuthSuccessUrl({
93+
pageUrl: page.url,
94+
basePath: base,
95+
origin: window.location.origin,
96+
isStudio: resolvedProfile.id === ProfileMode.STUDIO
97+
});
9298
93-
if (page.url.searchParams) {
94-
const redirect = page.url.searchParams.get('redirect');
95-
page.url.searchParams.delete('redirect');
96-
if (redirect) {
97-
url = `${redirect}${page.url.search}`;
98-
} else {
99-
url = `${base}${page.url.search ?? ''}`;
100-
}
101-
}
10299
sdk.forConsole.account.createOAuth2Session({
103100
provider: OAuthProvider.Github,
104-
success: window.location.origin + url,
101+
success: successUrl,
105102
failure: window.location.origin,
106103
scopes: ['read:user', 'user:email']
107104
});

src/routes/+layout.svelte

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import { feedback } from '$lib/stores/feedback';
2727
import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte';
2828
import { CDN_CSS_URL, CDN_URL } from '$lib/studio/studio-widget';
29+
import { STUDIO_PROMPT_KEY } from '$lib/helpers/oauth';
2930
3031
function resolveTheme(theme: AppStore['themeInUse']) {
3132
switch (theme) {
@@ -45,16 +46,16 @@
4546
const promptParam = currentUrl.searchParams.get('prompt');
4647
4748
if (promptParam) {
48-
sessionStorage.setItem('studioPrompt', promptParam);
49+
sessionStorage.setItem(STUDIO_PROMPT_KEY, promptParam);
4950
return;
5051
}
5152
52-
const storedPrompt = sessionStorage.getItem('studioPrompt');
53+
const storedPrompt = sessionStorage.getItem(STUDIO_PROMPT_KEY);
5354
if (!storedPrompt) return;
5455
5556
currentUrl.searchParams.set('prompt', storedPrompt);
5657
await goto(currentUrl.toString(), { replaceState: true, noScroll: true });
57-
sessionStorage.removeItem('studioPrompt');
58+
sessionStorage.removeItem(STUDIO_PROMPT_KEY);
5859
}
5960
6061
onMount(async () => {

0 commit comments

Comments
 (0)