diff --git a/frontend/src/app/dashboard/component/dashboard.component.spec.ts b/frontend/src/app/dashboard/component/dashboard.component.spec.ts index 29ed8426fe2..a53244b3cdd 100644 --- a/frontend/src/app/dashboard/component/dashboard.component.spec.ts +++ b/frontend/src/app/dashboard/component/dashboard.component.spec.ts @@ -21,7 +21,7 @@ import { ComponentFixture, TestBed } from "@angular/core/testing"; import { DashboardComponent } from "./dashboard.component"; import { ChangeDetectorRef, EventEmitter, NgZone } from "@angular/core"; import { By } from "@angular/platform-browser"; -import { EMPTY, of } from "rxjs"; +import { EMPTY, of, throwError } from "rxjs"; import { UserService } from "../../common/service/user/user.service"; import { FlarumService } from "../service/user/flarum/flarum.service"; @@ -178,6 +178,71 @@ describe("DashboardComponent", () => { expect(fixture.debugElement.query(By.css("#powered-by"))).toBeTruthy(); }); + describe("forumLogin", () => { + const clearForumCookie = () => + (document.cookie = "flarum_remember=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"); + + beforeEach(() => { + clearForumCookie(); + (userServiceMock.isLogin as Mock).mockReturnValue(true); + component.isLogin = true; + component.displayForum = true; + (flarumServiceMock.auth as Mock).mockClear(); + (flarumServiceMock.register as Mock).mockClear(); + }); + + afterEach(() => clearForumCookie()); + + it("stores the flarum_remember cookie on successful auth and does not register", () => { + (flarumServiceMock.auth as Mock).mockReturnValue(of({ token: "tok123" })); + + component.forumLogin(); + + expect(document.cookie).toContain("flarum_remember=tok123"); + expect(flarumServiceMock.register).not.toHaveBeenCalled(); + }); + + it("hides the forum and does not register when auth fails with 404/500", () => { + (flarumServiceMock.auth as Mock).mockReturnValue(throwError(() => ({ status: 404 }))); + + component.forumLogin(); + + expect(component.displayForum).toBe(false); + expect(flarumServiceMock.register).not.toHaveBeenCalled(); + }); + + it("registers at most once and stops when auth keeps failing (no infinite loop)", () => { + (flarumServiceMock.auth as Mock).mockReturnValue(throwError(() => ({ status: 401 }))); + (flarumServiceMock.register as Mock).mockReturnValue(of(null)); + + component.forumLogin(); + + // auth -> register -> auth -> stop: register fires once, auth twice, then it terminates. + expect(flarumServiceMock.register).toHaveBeenCalledTimes(1); + expect(flarumServiceMock.auth).toHaveBeenCalledTimes(2); + expect(component.displayForum).toBe(false); + }); + + it("hides the forum when registration fails", () => { + (flarumServiceMock.auth as Mock).mockReturnValue(throwError(() => ({ status: 401 }))); + (flarumServiceMock.register as Mock).mockReturnValue(throwError(() => ({ status: 500 }))); + + component.forumLogin(); + + expect(flarumServiceMock.register).toHaveBeenCalledTimes(1); + expect(component.displayForum).toBe(false); + }); + + it("does nothing when a flarum_remember cookie is already present", () => { + document.cookie = "flarum_remember=existing;path=/"; + + component.forumLogin(); + + expect(flarumServiceMock.auth).not.toHaveBeenCalled(); + expect(flarumServiceMock.register).not.toHaveBeenCalled(); + }); + }); + it("should hide the navbar on workflow workspace routes", () => { expect(component.isNavbarEnabled("/user/workflow/42")).toBe(false); expect(component.isNavbarEnabled("/user/workflow")).toBe(true); diff --git a/frontend/src/app/dashboard/component/dashboard.component.ts b/frontend/src/app/dashboard/component/dashboard.component.ts index aadf07d54b0..8f8ba03b082 100644 --- a/frontend/src/app/dashboard/component/dashboard.component.ts +++ b/frontend/src/app/dashboard/component/dashboard.component.ts @@ -204,7 +204,7 @@ export class DashboardComponent implements OnInit { }); } - forumLogin() { + forumLogin(attemptRegister: boolean = true) { if (!document.cookie.includes("flarum_remember") && this.isLogin) { this.flarumService .auth() @@ -214,13 +214,19 @@ export class DashboardComponent implements OnInit { document.cookie = `flarum_remember=${response.token};path=/`; }, error: (err: unknown) => { - if ([404, 500].includes((err as HttpErrorResponse).status)) { + // Stop retrying on a missing/broken forum service, or once we have + // already attempted a registration, to avoid an infinite + // auth -> register -> auth loop when auth keeps failing. + if ([404, 500].includes((err as HttpErrorResponse).status) || !attemptRegister) { this.displayForum = false; } else { this.flarumService .register() .pipe(untilDestroyed(this)) - .subscribe(() => this.forumLogin()); + .subscribe({ + next: () => this.forumLogin(false), + error: () => (this.displayForum = false), + }); } }, });