Files
flxn-app/src/features/teams/server.ts
2025-09-09 23:20:19 -05:00

98 lines
3.3 KiB
TypeScript

import { superTokensFunctionMiddleware, superTokensAdminFunctionMiddleware } from "@/utils/supertokens";
import { createServerFn } from "@tanstack/react-start";
import { pbAdmin } from "@/lib/pocketbase/client";
import { z } from "zod";
import { toServerResult } from "@/lib/tanstack-query/utils/to-server-result";
import { teamInputSchema, teamUpdateSchema } from "./types";
import { logger } from "@/lib/logger";
export const listTeams = createServerFn()
.middleware([superTokensFunctionMiddleware])
.handler(async () =>
toServerResult(() => pbAdmin.listTeams())
);
export const listTeamInfos = createServerFn()
.middleware([superTokensFunctionMiddleware])
.handler(async () =>
toServerResult(() => pbAdmin.listTeamInfos())
);
export const getTeam = createServerFn()
.validator(z.string())
.middleware([superTokensFunctionMiddleware])
.handler(async ({ data: teamId }) =>
toServerResult(() => pbAdmin.getTeam(teamId))
);
export const getTeamInfo = createServerFn()
.validator(z.string())
.middleware([superTokensFunctionMiddleware])
.handler(async ({ data: teamId }) =>
toServerResult(() => pbAdmin.getTeamInfo(teamId))
);
export const createTeam = createServerFn()
.validator(teamInputSchema)
.middleware([superTokensFunctionMiddleware])
.handler(async ({ data, context }) =>
toServerResult(async () => {
const userId = context.userAuthId;
const isAdmin = context.roles.includes("Admin");
// Check if user is trying to create a team with themselves as a player
if (!isAdmin && !data.players.includes(userId)) {
throw new Error("You can only create teams that include yourself as a player");
}
// Additional validation: ensure user is not already on another team
if (!isAdmin) {
const userTeams = await pbAdmin.listTeams();
const existingTeam = userTeams.find(team =>
team.players.some(player => player.id === userId)
);
if (existingTeam) {
throw new Error(`You are already a member of team "${existingTeam.name}"`);
}
}
logger.info("Creating team", { name: data.name, userId, isAdmin });
return pbAdmin.createTeam(data);
})
);
export const updateTeam = createServerFn()
.validator(z.object({
id: z.string(),
updates: teamUpdateSchema
}))
.middleware([superTokensFunctionMiddleware])
.handler(async ({ data: { id, updates }, context }) =>
toServerResult(async () => {
const userId = context.userAuthId;
const isAdmin = context.roles.includes("Admin");
// Get the team to verify ownership
const team = await pbAdmin.getTeam(id);
if (!team) {
throw new Error("Team not found");
}
// Check if user has permission to update this team
const isPlayerOnTeam = team.players.some(player => player.id === userId);
if (!isAdmin && !isPlayerOnTeam) {
throw new Error("You can only update teams that you are a member of");
}
logger.info("Updating team", { teamId: id, userId, isAdmin });
return pbAdmin.updateTeam(id, updates);
})
);
export const deleteTeam = createServerFn()
.validator(z.string())
.middleware([superTokensAdminFunctionMiddleware])
.handler(async ({ data: teamId }) =>
toServerResult(() => pbAdmin.deleteTeam(teamId))
);