if logged in user is not part of any orgs, still allow logging in, instead of throwing an exception due to accessing non-existent org --------- Co-authored-by: sua yoo <sua@suayoo.com>
This commit is contained in:
parent
0bc210d905
commit
c9c32d86e2
@ -5,7 +5,7 @@ import { restore, stub } from "sinon";
|
|||||||
import { NavigateController } from "./controllers/navigate";
|
import { NavigateController } from "./controllers/navigate";
|
||||||
import { NotifyController } from "./controllers/notify";
|
import { NotifyController } from "./controllers/notify";
|
||||||
import { type AppSettings } from "./utils/app";
|
import { type AppSettings } from "./utils/app";
|
||||||
import AuthService from "./utils/AuthService";
|
import AuthService, { type LoggedInEventDetail } from "./utils/AuthService";
|
||||||
import { AppStateService } from "./utils/state";
|
import { AppStateService } from "./utils/state";
|
||||||
import { formatAPIUser } from "./utils/user";
|
import { formatAPIUser } from "./utils/user";
|
||||||
|
|
||||||
@ -27,6 +27,12 @@ const mockAPIUser: APIUser = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
const mockUserInfo = formatAPIUser(mockAPIUser);
|
const mockUserInfo = formatAPIUser(mockAPIUser);
|
||||||
|
const mockAuth = {
|
||||||
|
headers: { Authorization: self.crypto.randomUUID() },
|
||||||
|
tokenExpiresAt: Date.now(),
|
||||||
|
username: "test-auth@example.com",
|
||||||
|
user: mockAPIUser,
|
||||||
|
};
|
||||||
|
|
||||||
const mockAppSettings: AppSettings = {
|
const mockAppSettings: AppSettings = {
|
||||||
registrationEnabled: false,
|
registrationEnabled: false,
|
||||||
@ -203,4 +209,41 @@ describe("browsertrix-app", () => {
|
|||||||
|
|
||||||
expect(el.appState.orgSlug).to.equal(id);
|
expect(el.appState.orgSlug).to.equal(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe(".onLoggedIn()", () => {
|
||||||
|
describe("routing", () => {
|
||||||
|
it("routes to redirect URL if specified", async () => {
|
||||||
|
stub(App.prototype, "routeTo");
|
||||||
|
|
||||||
|
const event = new CustomEvent<LoggedInEventDetail>("btrix-logged-in", {
|
||||||
|
detail: {
|
||||||
|
...mockAuth,
|
||||||
|
redirectUrl: "/fake-page",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const el = await fixture<App>("<browsertrix-app></browsertrix-app>");
|
||||||
|
|
||||||
|
el.onLoggedIn(event);
|
||||||
|
|
||||||
|
expect(el.routeTo).to.have.been.calledWith("/fake-page");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to account settings", async () => {
|
||||||
|
stub(App.prototype, "routeTo");
|
||||||
|
|
||||||
|
const event = new CustomEvent<LoggedInEventDetail>("btrix-logged-in", {
|
||||||
|
detail: {
|
||||||
|
...mockAuth,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const el = await fixture<App>("<browsertrix-app></browsertrix-app>");
|
||||||
|
|
||||||
|
el.onLoggedIn(event);
|
||||||
|
|
||||||
|
expect(el.routeTo).to.have.been.calledWith("/account/settings");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
132
frontend/src/pages/log-in.test.ts
Normal file
132
frontend/src/pages/log-in.test.ts
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import { expect, fixture, oneEvent } from "@open-wc/testing";
|
||||||
|
import { html } from "lit/static-html.js";
|
||||||
|
import { match, restore, stub } from "sinon";
|
||||||
|
|
||||||
|
import type { APIUser } from "..";
|
||||||
|
|
||||||
|
import { LogInPage } from "./log-in";
|
||||||
|
|
||||||
|
import { ROUTES } from "@/routes";
|
||||||
|
import APIRouter from "@/utils/APIRouter";
|
||||||
|
import AuthService from "@/utils/AuthService";
|
||||||
|
import { AppStateService } from "@/utils/state";
|
||||||
|
|
||||||
|
const router = new APIRouter(ROUTES);
|
||||||
|
const viewState = router.match("/log-in");
|
||||||
|
const mockAPIUser: APIUser = {
|
||||||
|
id: "740d7b63-b257-4311-ba3f-adc46a5fafb8",
|
||||||
|
email: "test-user@example.com",
|
||||||
|
name: "Test User",
|
||||||
|
is_verified: false,
|
||||||
|
is_superuser: false,
|
||||||
|
orgs: [
|
||||||
|
{
|
||||||
|
id: "e21ab647-2d0e-489d-97d1-88ac91774942",
|
||||||
|
name: "test org",
|
||||||
|
slug: "test-org",
|
||||||
|
role: 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const mockAuth = {
|
||||||
|
headers: { Authorization: self.crypto.randomUUID() },
|
||||||
|
tokenExpiresAt: Date.now(),
|
||||||
|
username: "test-auth@example.com",
|
||||||
|
user: mockAPIUser,
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("<btrix-log-in>", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
AppStateService.resetAll();
|
||||||
|
stub(window.history, "pushState");
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is defined", async () => {
|
||||||
|
const el = await fixture<LogInPage>(
|
||||||
|
html`<btrix-log-in .viewState=${viewState}></btrix-log-in>`,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(el).instanceOf(LogInPage);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("form submit", () => {
|
||||||
|
it("creates logged in event on success", async () => {
|
||||||
|
stub(AuthService, "login").callsFake(async () =>
|
||||||
|
Promise.resolve(mockAuth),
|
||||||
|
);
|
||||||
|
|
||||||
|
const el = await fixture<LogInPage>(
|
||||||
|
html`<btrix-log-in .viewState=${viewState}></btrix-log-in>`,
|
||||||
|
);
|
||||||
|
const form = el.shadowRoot!.querySelector<HTMLFormElement>("form")!;
|
||||||
|
|
||||||
|
const loggedInListener = oneEvent(el, "btrix-logged-in");
|
||||||
|
const submitListener = oneEvent(form, "submit");
|
||||||
|
|
||||||
|
form.requestSubmit();
|
||||||
|
|
||||||
|
await submitListener;
|
||||||
|
const loggedInEvent = await loggedInListener;
|
||||||
|
|
||||||
|
expect(loggedInEvent.detail.user).to.exist;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("updates org slug in state", async () => {
|
||||||
|
stub(AuthService, "login").callsFake(async () =>
|
||||||
|
Promise.resolve(mockAuth),
|
||||||
|
);
|
||||||
|
stub(AppStateService, "updateUser");
|
||||||
|
|
||||||
|
const el = await fixture<LogInPage>(
|
||||||
|
html`<btrix-log-in .viewState=${viewState}></btrix-log-in>`,
|
||||||
|
);
|
||||||
|
const form = el.shadowRoot!.querySelector<HTMLFormElement>("form")!;
|
||||||
|
|
||||||
|
const loggedInListener = oneEvent(el, "btrix-logged-in");
|
||||||
|
const submitListener = oneEvent(form, "submit");
|
||||||
|
|
||||||
|
form.requestSubmit();
|
||||||
|
|
||||||
|
await submitListener;
|
||||||
|
await loggedInListener;
|
||||||
|
|
||||||
|
expect(AppStateService.updateUser).to.have.been.calledWith(
|
||||||
|
match.any,
|
||||||
|
"test-org",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("handles users without org", async () => {
|
||||||
|
stub(AuthService, "login").callsFake(async () =>
|
||||||
|
Promise.resolve({
|
||||||
|
...mockAuth,
|
||||||
|
user: {
|
||||||
|
...mockAPIUser,
|
||||||
|
orgs: [],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
stub(AppStateService, "updateUser");
|
||||||
|
|
||||||
|
const el = await fixture<LogInPage>(
|
||||||
|
html`<btrix-log-in .viewState=${viewState}></btrix-log-in>`,
|
||||||
|
);
|
||||||
|
const form = el.shadowRoot!.querySelector<HTMLFormElement>("form")!;
|
||||||
|
|
||||||
|
const loggedInListener = oneEvent(el, "btrix-logged-in");
|
||||||
|
const submitListener = oneEvent(form, "submit");
|
||||||
|
|
||||||
|
form.requestSubmit();
|
||||||
|
|
||||||
|
await submitListener;
|
||||||
|
const loggedInEvent = await loggedInListener;
|
||||||
|
|
||||||
|
expect(AppStateService.updateUser).not.to.have.been.called;
|
||||||
|
expect(loggedInEvent.detail.user).to.exist;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -398,9 +398,13 @@ export class LogInPage extends BtrixElement {
|
|||||||
this.orgSlugState &&
|
this.orgSlugState &&
|
||||||
data.user.orgs.some((org) => org.slug === this.orgSlugState)
|
data.user.orgs.some((org) => org.slug === this.orgSlugState)
|
||||||
? this.orgSlugState
|
? this.orgSlugState
|
||||||
: data.user.orgs[0].slug;
|
: data.user.orgs.length
|
||||||
|
? data.user.orgs[0].slug
|
||||||
|
: "";
|
||||||
|
|
||||||
AppStateService.updateUser(formatAPIUser(data.user), slug);
|
if (slug) {
|
||||||
|
AppStateService.updateUser(formatAPIUser(data.user), slug);
|
||||||
|
}
|
||||||
|
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user