9bd3781c03
Cast Zod schemas with .refine()/.superRefine() to z.ZodType<InferredType> at the procedure level. This short-circuits TypeScript's deep type recursion through tRPC's middleware chain, eliminating 4 of 5 @ts-expect-error TS2589 suppressions in web components (VacationModal, ProjectModal, UsersClient, CountriesClient). Applied same pattern to allocation, timeline, staffing, dashboard, project, and resource query/mutation procedures to reduce client-side type depth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
156 lines
5.4 KiB
TypeScript
156 lines
5.4 KiB
TypeScript
import type { z } from "zod";
|
|
import {
|
|
adminProcedure,
|
|
createTRPCRouter,
|
|
managerProcedure,
|
|
protectedProcedure,
|
|
publicProcedure,
|
|
} from "../trpc.js";
|
|
import {
|
|
autoLinkUsersByEmail,
|
|
countActiveUsers,
|
|
CreateUserInputSchema,
|
|
createUser,
|
|
deactivateUser,
|
|
reactivateUser,
|
|
deleteUser,
|
|
disableTotp,
|
|
getEffectiveUserPermissions,
|
|
LinkUserResourceInputSchema,
|
|
linkUserResource,
|
|
listAssignableUsers,
|
|
listUsers,
|
|
SetUserPasswordInputSchema,
|
|
setUserPassword,
|
|
SetUserPermissionsInputSchema,
|
|
setUserPermissions,
|
|
UpdateUserNameInputSchema,
|
|
updateUserName,
|
|
UpdateUserRoleInputSchema,
|
|
updateUserRole,
|
|
UserIdInputSchema,
|
|
resetUserPermissions,
|
|
} from "./user-procedure-support.js";
|
|
import {
|
|
generateTotpSecret,
|
|
getColumnPreferences,
|
|
getCurrentMfaStatus,
|
|
getCurrentUserProfile,
|
|
getDashboardLayout,
|
|
getFavoriteProjectIds,
|
|
SaveDashboardLayoutInputSchema,
|
|
saveDashboardLayout,
|
|
SetColumnPreferencesInputSchema,
|
|
setColumnPreferences,
|
|
ToggleFavoriteProjectInputSchema,
|
|
toggleFavoriteProject,
|
|
verifyAndEnableTotp as verifyAndEnableTotpSelfService,
|
|
VerifyAndEnableTotpInputSchema,
|
|
verifyTotp,
|
|
VerifyTotpInputSchema,
|
|
} from "./user-self-service-procedure-support.js";
|
|
|
|
export const userRouter = createTRPCRouter({
|
|
/** Lightweight user list for task assignment (ADMIN + MANAGER) */
|
|
listAssignable: managerProcedure.query(({ ctx }) => listAssignableUsers(ctx)),
|
|
|
|
list: adminProcedure.query(({ ctx }) => listUsers(ctx)),
|
|
|
|
/** Count of users active in the last 5 minutes */
|
|
activeCount: adminProcedure.query(({ ctx }) => countActiveUsers(ctx)),
|
|
|
|
me: protectedProcedure.query(({ ctx }) => getCurrentUserProfile(ctx)),
|
|
|
|
create: adminProcedure
|
|
.input(CreateUserInputSchema)
|
|
.mutation(({ ctx, input }) => createUser(ctx, input)),
|
|
|
|
setPassword: adminProcedure
|
|
.input(SetUserPasswordInputSchema)
|
|
.mutation(({ ctx, input }) => setUserPassword(ctx, input)),
|
|
|
|
updateRole: adminProcedure
|
|
.input(UpdateUserRoleInputSchema)
|
|
.mutation(({ ctx, input }) => updateUserRole(ctx, input)),
|
|
|
|
updateName: adminProcedure
|
|
.input(UpdateUserNameInputSchema)
|
|
.mutation(({ ctx, input }) => updateUserName(ctx, input)),
|
|
|
|
// ─── Resource Linking ──────────────────────────────────────────────────
|
|
|
|
linkResource: adminProcedure
|
|
.input(LinkUserResourceInputSchema)
|
|
.mutation(({ ctx, input }) => linkUserResource(ctx, input)),
|
|
|
|
autoLinkAllByEmail: adminProcedure.mutation(({ ctx }) => autoLinkUsersByEmail(ctx)),
|
|
|
|
getDashboardLayout: protectedProcedure.query(({ ctx }) => getDashboardLayout(ctx)),
|
|
|
|
saveDashboardLayout: protectedProcedure
|
|
.input(SaveDashboardLayoutInputSchema)
|
|
.mutation(({ ctx, input }) => saveDashboardLayout(ctx, input)),
|
|
|
|
// ─── Favorite Projects ──────────────────────────────────────────────────
|
|
getFavoriteProjectIds: protectedProcedure.query(({ ctx }) => getFavoriteProjectIds(ctx)),
|
|
|
|
toggleFavoriteProject: protectedProcedure
|
|
.input(ToggleFavoriteProjectInputSchema)
|
|
.mutation(({ ctx, input }) => toggleFavoriteProject(ctx, input)),
|
|
|
|
setPermissions: adminProcedure
|
|
.input(
|
|
SetUserPermissionsInputSchema as z.ZodType<z.infer<typeof SetUserPermissionsInputSchema>>,
|
|
)
|
|
.mutation(({ ctx, input }) => setUserPermissions(ctx, input)),
|
|
|
|
resetPermissions: adminProcedure
|
|
.input(UserIdInputSchema)
|
|
.mutation(({ ctx, input }) => resetUserPermissions(ctx, input)),
|
|
|
|
getColumnPreferences: protectedProcedure.query(({ ctx }) => getColumnPreferences(ctx)),
|
|
|
|
setColumnPreferences: protectedProcedure
|
|
.input(SetColumnPreferencesInputSchema)
|
|
.mutation(({ ctx, input }) => setColumnPreferences(ctx, input)),
|
|
|
|
getEffectivePermissions: adminProcedure
|
|
.input(UserIdInputSchema)
|
|
.query(({ ctx, input }) => getEffectiveUserPermissions(ctx, input)),
|
|
|
|
// ─── TOTP / MFA ─────────────────────────────────────────────────────────────
|
|
|
|
/** Generate a new TOTP secret for the current user (not yet enabled). */
|
|
generateTotpSecret: protectedProcedure.mutation(({ ctx }) => generateTotpSecret(ctx)),
|
|
|
|
/** Verify a TOTP token and enable MFA for the current user. */
|
|
verifyAndEnableTotp: protectedProcedure
|
|
.input(VerifyAndEnableTotpInputSchema)
|
|
.mutation(({ ctx, input }) => verifyAndEnableTotpSelfService(ctx, input)),
|
|
|
|
deactivate: adminProcedure
|
|
.input(UserIdInputSchema)
|
|
.mutation(({ ctx, input }) => deactivateUser(ctx, input)),
|
|
|
|
reactivate: adminProcedure
|
|
.input(UserIdInputSchema)
|
|
.mutation(({ ctx, input }) => reactivateUser(ctx, input)),
|
|
|
|
delete: adminProcedure
|
|
.input(UserIdInputSchema)
|
|
.mutation(({ ctx, input }) => deleteUser(ctx, input)),
|
|
|
|
/** Admin override: disable TOTP for a specific user. */
|
|
disableTotp: adminProcedure
|
|
.input(UserIdInputSchema)
|
|
.mutation(({ ctx, input }) => disableTotp(ctx, input)),
|
|
|
|
/** Verify a TOTP token (used during the login flow — public procedure). */
|
|
verifyTotp: publicProcedure
|
|
.input(VerifyTotpInputSchema)
|
|
.mutation(({ ctx, input }) => verifyTotp(ctx, input)),
|
|
|
|
/** Get MFA status for the current user. */
|
|
getMfaStatus: protectedProcedure.query(({ ctx }) => getCurrentMfaStatus(ctx)),
|
|
});
|