feat(auth): implement Facebook identity binding on external entry

This commit is contained in:
2026-07-13 15:02:01 +08:00
parent 2ebf5b9e97
commit fd631168c8
11 changed files with 278 additions and 40 deletions
@@ -5,6 +5,7 @@ import { ROUTES } from "@/router/routes";
import {
resolveExternalEntryPromotionType,
resolveExternalEntryTarget,
shouldBindExternalFacebookIdentity,
} from "../external_entry";
describe("external entry navigation", () => {
@@ -31,6 +32,69 @@ describe("external entry navigation", () => {
});
});
describe("external entry facebook identity binding", () => {
it("binds only a ready real-user session with an external id", () => {
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: false,
loginStatus: "email",
asid: "asid-1",
}),
).toBe(true);
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: false,
loginStatus: "google",
asid: "asid-1",
}),
).toBe(true);
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: false,
loginStatus: "facebook",
psid: "psid-1",
}),
).toBe(true);
});
it("skips guest, notLoggedIn, loading, and empty identity inputs", () => {
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: false,
loginStatus: "guest",
asid: "asid-1",
}),
).toBe(false);
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: false,
loginStatus: "notLoggedIn",
psid: "psid-1",
}),
).toBe(false);
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: true,
loginStatus: "google",
asid: "asid-1",
}),
).toBe(false);
expect(
shouldBindExternalFacebookIdentity({
hasInitialized: true,
isLoading: false,
loginStatus: "google",
}),
).toBe(false);
});
});
describe("external entry promotion", () => {
it("accepts only explicit promotion mode and supported message types", () => {
expect(
+28
View File
@@ -3,6 +3,7 @@
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { UserStorage } from "@/data/storage/user/user_storage";
import type { PendingChatPromotionType } from "@/data/storage/navigation";
import type { LoginStatus } from "@/data/dto/auth";
import { ROUTES } from "@/router/routes";
export type ExternalEntryTarget =
@@ -26,6 +27,33 @@ export interface ExternalEntryPromotionInput {
promotionType?: string | null;
}
export interface ExternalFacebookIdentityBindingInput {
hasInitialized: boolean;
isLoading: boolean;
loginStatus: LoginStatus;
asid?: string | null;
psid?: string | null;
}
export function shouldBindExternalFacebookIdentity({
hasInitialized,
isLoading,
loginStatus,
asid,
psid,
}: ExternalFacebookIdentityBindingInput): boolean {
const isRealUser =
loginStatus === "email" ||
loginStatus === "google" ||
loginStatus === "facebook";
return (
hasInitialized &&
!isLoading &&
isRealUser &&
(hasValue(asid) || hasValue(psid))
);
}
export function resolveExternalEntryPromotionType({
mode,
promotionType,