fix(cloud): launch newly registered accounts through Space (#2499)

* fix(cloud): launch new accounts through Space

* style: format Cloud entry URL

* fix(cloud): wait for launch workspace projection

---------

Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
Hyu
2026-09-02 21:41:35 +08:00
committed by GitHub
parent 7b7d3f04e8
commit 018dd7a363
6 changed files with 143 additions and 9 deletions
+8 -2
View File
@@ -1385,12 +1385,18 @@ export class BackendClient extends BaseHttpClient {
}
// ============ Space OAuth API (Redirect Flow) ============
public getSpaceAuthorizeUrl(redirectUri: string): Promise<{
public getSpaceAuthorizeUrl(
redirectUri: string,
options?: { cloudEntry?: boolean },
): Promise<{
authorize_url: string;
}> {
return this.get(
'/api/v1/user/space/authorize-url',
{ redirect_uri: redirectUri },
{
redirect_uri: redirectUri,
...(options?.cloudEntry ? { cloud_entry: '1' } : {}),
},
{ skipWorkspace: true },
);
}
+7 -1
View File
@@ -202,7 +202,13 @@ export default function Login() {
try {
const currentOrigin = window.location.origin;
const redirectUri = `${currentOrigin}/auth/space/callback`;
const response = await httpClient.getSpaceAuthorizeUrl(redirectUri);
const response = await httpClient.getSpaceAuthorizeUrl(redirectUri, {
// Cloud Accounts must be launched from Space so a first visit can
// lazily create and project the personal Workspace. Invitation login
// remains on the OAuth callback path because it targets the invited
// Workspace instead.
cloudEntry: !getPendingInvitationToken(),
});
window.location.href = response.authorize_url;
} catch {
toast.error(t('common.spaceLoginFailed'));
@@ -0,0 +1,17 @@
import assert from 'node:assert/strict';
import fs from 'node:fs';
import test from 'node:test';
const source = fs.readFileSync(
new URL('../../src/app/login/page.tsx', import.meta.url),
'utf8',
);
test('normal Cloud login enters through the Space Workspace launcher', () => {
assert.match(source, /cloudEntry:\s*!getPendingInvitationToken\(\)/);
assert.match(source, /getSpaceAuthorizeUrl\(redirectUri,\s*\{/);
});
test('invitation login remains on the OAuth callback path', () => {
assert.match(source, /cloudEntry:\s*!getPendingInvitationToken\(\)/);
});