Fix recorder finalize path and add invite-gated login

这个提交包含在:
cryptocommuniums-afk
2026-03-15 00:52:11 +08:00
父节点 ad83ce9c68
当前提交 d1b6603061
修改 13 个文件,包含 458 行新增18 行删除

查看文件

@@ -1,8 +1,10 @@
import { describe, expect, it, vi, beforeEach } from "vitest";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { appRouter } from "./routers";
import { COOKIE_NAME } from "../shared/const";
import type { TrpcContext } from "./_core/context";
import * as db from "./db";
import { ENV } from "./_core/env";
import { sdk } from "./_core/sdk";
type AuthenticatedUser = NonNullable<TrpcContext["user"]>;
@@ -114,6 +116,68 @@ describe("auth.loginWithUsername input validation", () => {
});
});
describe("auth.loginWithUsername invite flow", () => {
const originalInviteCode = ENV.registrationInviteCode;
beforeEach(() => {
ENV.registrationInviteCode = "CA2026";
});
afterEach(() => {
ENV.registrationInviteCode = originalInviteCode;
vi.restoreAllMocks();
});
it("allows existing users to log in without an invite code", async () => {
const existingUser = createTestUser({ name: "ExistingPlayer", openId: "existing-1" });
const { ctx, setCookies } = createMockContext(null);
const caller = appRouter.createCaller(ctx);
vi.spyOn(db, "getUserByUsername").mockResolvedValueOnce(existingUser);
const createUsernameAccountSpy = vi.spyOn(db, "createUsernameAccount").mockResolvedValueOnce({
user: existingUser,
isNew: false,
});
vi.spyOn(sdk, "createSessionToken").mockResolvedValueOnce("session-token");
const result = await caller.auth.loginWithUsername({ username: "ExistingPlayer" });
expect(result.isNew).toBe(false);
expect(createUsernameAccountSpy).toHaveBeenCalledWith("ExistingPlayer", undefined);
expect(setCookies[0]?.name).toBe(COOKIE_NAME);
});
it("rejects new users without the correct invite code", async () => {
const { ctx } = createMockContext(null);
const caller = appRouter.createCaller(ctx);
vi.spyOn(db, "getUserByUsername").mockResolvedValueOnce(undefined);
const createUsernameAccountSpy = vi.spyOn(db, "createUsernameAccount");
await expect(caller.auth.loginWithUsername({ username: "NewPlayer" })).rejects.toThrow("新用户注册需要正确的邀请码");
expect(createUsernameAccountSpy).not.toHaveBeenCalled();
});
it("allows new users with the correct invite code", async () => {
const newUser = createTestUser({ name: "NewPlayer", openId: "new-1" });
const { ctx, setCookies } = createMockContext(null);
const caller = appRouter.createCaller(ctx);
vi.spyOn(db, "getUserByUsername").mockResolvedValueOnce(undefined);
const createUsernameAccountSpy = vi.spyOn(db, "createUsernameAccount").mockResolvedValueOnce({
user: newUser,
isNew: true,
});
vi.spyOn(sdk, "createSessionToken").mockResolvedValueOnce("session-token");
const result = await caller.auth.loginWithUsername({ username: "NewPlayer", inviteCode: "CA2026" });
expect(result.isNew).toBe(true);
expect(createUsernameAccountSpy).toHaveBeenCalledWith("NewPlayer", "CA2026");
expect(setCookies[0]?.name).toBe(COOKIE_NAME);
});
});
// ===== PROFILE TESTS =====
describe("profile.stats", () => {