- Add authedProcedure, superuserProcedure, loginRequestProcedure, orgMemberProcedure in base.ts - Create procedures/me/_base.ts with meRoute = authedProcedure.me - Update all me procedures to use meRoute.X.handler() - Update auth/logout and auth/resend-verification to use authedProcedure - Update all admin procedures to use superuserProcedure - Update all orgs procedures to use authedProcedure This reduces boilerplate and makes middleware usage consistent. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
64 lines
1.7 KiB
TypeScript
64 lines
1.7 KiB
TypeScript
/**
|
|
* Set password procedure - sets or changes user password
|
|
*/
|
|
|
|
import { ORPCError } from "@orpc/server";
|
|
import {
|
|
hashPassword,
|
|
validatePassword,
|
|
verifyPassword,
|
|
} from "../../utils/password.js";
|
|
import { meRoute } from "./_base.js";
|
|
|
|
/**
|
|
* Set password handler
|
|
* - Requires authentication
|
|
* - If user has existing password, currentPassword is required
|
|
* - Validates new password strength using zxcvbn
|
|
*/
|
|
export const setPassword = meRoute.setPassword.handler(
|
|
async ({ input, context }) => {
|
|
const { currentPassword, newPassword } = input;
|
|
|
|
// Fetch current password hash
|
|
const user = await context.db
|
|
.selectFrom("users")
|
|
.select(["password_hash"])
|
|
.where("id", "=", context.user.id)
|
|
.executeTakeFirstOrThrow();
|
|
|
|
// If user has a password, verify current password
|
|
if (user.password_hash) {
|
|
if (!currentPassword) {
|
|
throw new ORPCError("BAD_REQUEST", {
|
|
message: "Current password required",
|
|
});
|
|
}
|
|
const valid = await verifyPassword(currentPassword, user.password_hash);
|
|
if (!valid) {
|
|
throw new ORPCError("BAD_REQUEST", {
|
|
message: "Current password is incorrect",
|
|
});
|
|
}
|
|
}
|
|
|
|
// Validate new password strength
|
|
const validation = validatePassword(newPassword, [context.user.email]);
|
|
if (!validation.valid) {
|
|
throw new ORPCError("BAD_REQUEST", {
|
|
message: validation.feedback[0] ?? "Password is too weak",
|
|
});
|
|
}
|
|
|
|
// Hash and update
|
|
const newHash = await hashPassword(newPassword);
|
|
await context.db
|
|
.updateTable("users")
|
|
.set({ password_hash: newHash, updated_at: new Date() })
|
|
.where("id", "=", context.user.id)
|
|
.execute();
|
|
|
|
return { success: true };
|
|
},
|
|
);
|