shellphone.app/app/auth/mutations/login.ts

56 lines
1.6 KiB
TypeScript
Raw Normal View History

import { resolver, SecurePassword, AuthenticationError } from "blitz";
2021-07-31 14:33:18 +00:00
2021-08-26 19:17:46 +00:00
import db from "../../../db";
import { Login } from "../validations";
2021-07-31 14:33:18 +00:00
export const authenticateUser = async (rawEmail: string, rawPassword: string) => {
const email = rawEmail.toLowerCase().trim();
const password = rawPassword.trim();
2021-08-26 19:17:46 +00:00
const user = await db.user.findFirst({
where: { email },
include: {
memberships: {
include: {
organization: {
include: { phoneNumbers: true },
},
},
},
},
});
if (!user) throw new AuthenticationError();
2021-07-31 14:33:18 +00:00
const result = await SecurePassword.verify(user.hashedPassword, password);
2021-07-31 14:33:18 +00:00
if (result === SecurePassword.VALID_NEEDS_REHASH) {
// Upgrade hashed password with a more secure hash
const improvedHash = await SecurePassword.hash(password);
2021-08-26 19:17:46 +00:00
await db.user.update({
where: { id: user.id },
data: { hashedPassword: improvedHash },
});
2021-07-31 14:33:18 +00:00
}
const { hashedPassword, ...rest } = user;
return rest;
};
2021-07-31 14:33:18 +00:00
export default resolver.pipe(resolver.zod(Login), async ({ email, password }, ctx) => {
// This throws an error if credentials are invalid
const user = await authenticateUser(email, password);
2021-07-31 14:33:18 +00:00
2021-08-26 19:17:46 +00:00
const organization = user.memberships[0]!.organization;
const hasCompletedOnboarding =
Boolean(organization.twilioAccountSid) &&
Boolean(organization.twilioAuthToken) &&
Boolean(organization.phoneNumbers.length > 1);
2021-08-05 17:07:15 +00:00
await ctx.session.$create({
userId: user.id,
2021-08-26 19:17:46 +00:00
roles: [user.role, user.memberships[0]!.role],
hasCompletedOnboarding: hasCompletedOnboarding || undefined,
orgId: organization.id,
2021-08-05 17:07:15 +00:00
});
2021-07-31 14:33:18 +00:00
return user;
});