mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-09 04:40:57 +00:00
fix(cloud): accept invitations with current account
This commit is contained in:
@@ -1179,6 +1179,7 @@ export class BackendClient extends BaseHttpClient {
|
||||
|
||||
public getAccountInfo(): Promise<{
|
||||
initialized: boolean;
|
||||
authenticated_invitation_acceptance_enabled?: boolean;
|
||||
password_login_enabled?: boolean;
|
||||
space_login_enabled?: boolean;
|
||||
}> {
|
||||
|
||||
@@ -93,6 +93,10 @@ export default function AcceptInvitationPage() {
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [passwordRegistrationEnabled, setPasswordRegistrationEnabled] =
|
||||
useState(false);
|
||||
const [
|
||||
authenticatedInvitationAcceptanceEnabled,
|
||||
setAuthenticatedInvitationAcceptanceEnabled,
|
||||
] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleHashChange = () => setInvitationHash(window.location.hash);
|
||||
@@ -113,6 +117,9 @@ export default function AcceptInvitationPage() {
|
||||
.getAccountInfo()
|
||||
.then((info) => {
|
||||
setPasswordRegistrationEnabled(info.password_login_enabled !== false);
|
||||
setAuthenticatedInvitationAcceptanceEnabled(
|
||||
info.authenticated_invitation_acceptance_enabled === true,
|
||||
);
|
||||
})
|
||||
.catch(() => setPasswordRegistrationEnabled(false));
|
||||
if (!invitationToken) {
|
||||
@@ -304,7 +311,18 @@ export default function AcceptInvitationPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasLoginToken ? (
|
||||
{hasLoginToken && authenticatedInvitationAcceptanceEnabled ? (
|
||||
<Button
|
||||
className="w-full"
|
||||
disabled={status === 'submitting'}
|
||||
onClick={() => void finishAcceptance()}
|
||||
>
|
||||
{status === 'submitting' ? (
|
||||
<Loader2 className="mr-2 size-4 animate-spin" />
|
||||
) : null}
|
||||
{t('workspace.acceptInvitation')}
|
||||
</Button>
|
||||
) : hasLoginToken ? (
|
||||
<div className="space-y-3">
|
||||
<div className="rounded-lg border border-amber-300 bg-amber-50 p-3 text-sm text-amber-900 dark:bg-amber-950/30 dark:text-amber-100">
|
||||
{t('workspace.authenticatedInvitationNotice')}
|
||||
|
||||
@@ -166,6 +166,83 @@ test('an authenticated OSS invitation requires logout before registration', asyn
|
||||
});
|
||||
});
|
||||
|
||||
test('an authenticated Cloud Account can accept its invitation directly', async ({
|
||||
page,
|
||||
}) => {
|
||||
await installLangBotApiMocks(page, {
|
||||
authenticated: true,
|
||||
storage: {
|
||||
token: 'invited-account-token',
|
||||
userEmail: 'invited@example.com',
|
||||
},
|
||||
});
|
||||
await page.route('**/api/v1/user/account-info', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
code: 0,
|
||||
data: {
|
||||
initialized: true,
|
||||
authenticated_invitation_acceptance_enabled: true,
|
||||
password_login_enabled: false,
|
||||
space_login_enabled: true,
|
||||
},
|
||||
msg: 'ok',
|
||||
}),
|
||||
});
|
||||
});
|
||||
await page.route('**/api/v1/invitations/inspect', async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
code: 0,
|
||||
data: {
|
||||
invitation: {
|
||||
uuid: 'cloud-invitation',
|
||||
workspace_uuid: 'workspace-playwright',
|
||||
normalized_email: 'invited@example.com',
|
||||
role: 'viewer',
|
||||
status: 'pending',
|
||||
},
|
||||
workspace: {
|
||||
uuid: 'workspace-playwright',
|
||||
name: 'Playwright Workspace',
|
||||
},
|
||||
},
|
||||
msg: 'ok',
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
let acceptanceAuthorization = '';
|
||||
await page.route('**/api/v1/invitations/accept', async (route) => {
|
||||
acceptanceAuthorization = route.request().headers().authorization ?? '';
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify({
|
||||
code: 0,
|
||||
data: {
|
||||
token: 'accepted-cloud-account-token',
|
||||
workspace_uuid: 'workspace-playwright',
|
||||
},
|
||||
msg: 'ok',
|
||||
}),
|
||||
});
|
||||
});
|
||||
|
||||
await page.goto('/invitations/accept#token=cloud-invitation');
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Accept Invitation' }),
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Accept Invitation' }).click();
|
||||
await expect(page).toHaveURL(/\/home(?:\/monitoring)?$/);
|
||||
expect(acceptanceAuthorization).toBe('Bearer invited-account-token');
|
||||
});
|
||||
|
||||
test('Space OAuth accepts a pending invitation with the freshly authenticated account', async ({
|
||||
page,
|
||||
}) => {
|
||||
|
||||
Reference in New Issue
Block a user