This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch 
gh-readonly-queue/main/pr-5311-6d604f340911153995c15bae5071723127b852e6
in repository https://gitbox.apache.org/repos/asf/texera.git

commit af664995e78e1cef5b9c727998cd335d98f0d92c
Author: Matthew B. <[email protected]>
AuthorDate: Wed Jun 3 16:04:55 2026 -0700

    fix(frontend): stop forum login from looping when Flarum auth fails (#5311)
    
    ### What changes were proposed in this PR?
    - Add an `attemptRegister` flag to `DashboardComponent.forumLogin` so a
    Flarum registration is attempted at most once, breaking the infinite
    `auth -> register -> auth` cycle that occurred when `auth()` kept
    failing with a non-404/500 status.
    - After registering, the recursive call now passes `forumLogin(false)`;
    if auth still fails on that pass it falls through to `displayForum =
    false` instead of looping.
    - Add an error handler to the `register()` subscription so a failed
    registration hides the forum rather than being silently dropped.
    ### Any related issues, documentation, or discussions?
    Closes: #5310
    ### How was this PR tested?
    - Ran `yarn format:fix` (clean, no files changed).
    - Manually traced the control flow: auth fail (non-404/500) now does
    auth, register, auth, then stop, instead of recursing without bound.
    ### Was this PR authored or co-authored using generative AI tooling?
    Co-authored with Claude Opus 4.8 in compliance with ASF
    
    ---------
    
    Signed-off-by: Matthew B. <[email protected]>
---
 .../component/dashboard.component.spec.ts          | 67 +++++++++++++++++++++-
 .../app/dashboard/component/dashboard.component.ts | 12 +++-
 2 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/frontend/src/app/dashboard/component/dashboard.component.spec.ts 
b/frontend/src/app/dashboard/component/dashboard.component.spec.ts
index 29ed8426fe..a53244b3cd 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 aadf07d54b..8f8ba03b08 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),
+                });
             }
           },
         });

Reply via email to