/*
TODO: For MySQL set the id and email address column collation to be case-sensitive (utf8mb4_unicode_bin).
model User {
id String @id
emailAddress String @unique
passwordHash Bytes
passwordSalt Bytes
passwordHashAlgorithmId String
disabled Boolean @default(false)
emailAddressCounter Int @default(0)
passwordHashCounter Int @default(0)
disabledCounter Int @default(0)
sessionsCounter Int @default(0)
}
*/
import * as faroe_user_server from "@faroe/user-server";
import { Prisma } from "@prisma/client";
const actions: faroe_user_server.Actions = {
async createUserAction(_actionInvocationId, emailAddress, passwordHash, passwordHashAlgorithmId, passwordSalt) {
const id = generateId(); // TODO
try {
await prisma.user.create({
data: {
id,
emailAddress,
passwordHash,
passwordSalt,
passwordHashAlgorithmId,
emailAddressCounter: 0,
passwordHashCounter: 0,
sessionsCounter: 0,
},
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
throw new faroe_user_server.ActionError("email_address_already_used");
}
throw new faroe_user_server.ActionError("unexpected_error");
}
const user: faroe_user_server.User = {
id: id,
emailAddress,
passwordHash,
passwordHashAlgorithmId,
passwordSalt,
disabled: false,
displayName: emailAddress,
emailAddressCounter: 0,
passwordHashCounter: 0,
disabledCounter: 0,
sessionsCounter: 0,
};
return user;
},
async getUserAction(_actionInvocationId, userId) {
try {
const storedUser = await prisma.user.findUnique({
where: { id: userId },
});
if (storedUser === null) {
throw new faroe_user_server.ActionError("user_not_found");
}
const user: faroe_user_server.User = {
id: storedUser.id,
emailAddress: storedUser.emailAddress,
passwordHash: storedUser.passwordHash,
passwordHashAlgorithmId: storedUser.passwordHasAlgorithm,
passwordSalt: storedUser.passwordSalt,
disabled: false,
displayName: storedUser.emailAddress,
emailAddressCounter: storedUser.emailAddressCounter,
passwordHashCounter: storedUser.passwordHashCounter,
disabledCounter: 0,
sessionsCounter: storedUser.sessionsCounter,
};
return user;
} catch {
throw new faroe_user_server.ActionError("unexpected_error");
}
},
async getUserByEmailAddressAction(_actionInvocationId, emailAddress) {
try {
const storedUser = await prisma.user.findUnique({
where: { emailAddress },
});
if (storedUser === null) {
throw new faroe_user_server.ActionError("user_not_found");
}
const user: faroe_user_server.User = {
id: storedUser.id,
emailAddress: storedUser.emailAddress,
passwordHash: storedUser.passwordHash,
passwordHashAlgorithmId: storedUser.passwordHasAlgorithm,
passwordSalt: storedUser.passwordSalt,
disabled: false,
displayName: storedUser.emailAddress,
emailAddressCounter: storedUser.emailAddressCounter,
passwordHashCounter: storedUser.passwordHashCounter,
disabledCounter: 0,
sessionsCounter: storedUser.sessionsCounter,
};
return user;
} catch {
throw new faroe_user_server.ActionError("unexpected_error");
}
},
async updateUserEmailAddressAction(_actionInvocationId, userId, emailAddress, userEmailAddressCounter) {
try {
await prisma.user.update({
where: {
id: userId,
emailAddressCounter: userEmailAddressCounter,
},
data: {
emailAddress,
emailAddressCounter: { increment: 1 },
},
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2025") {
throw new faroe_user_server.ActionError("user_not_found");
}
throw new faroe_user_server.ActionError("unexpected_error");
}
},
async updateUserPasswordHashAction(_actionInvocationId, userId, passwordHash, passwordHashAlgorithmId, passwordSalt, userPasswordHashCounter) {
try {
await prisma.user.update({
where: {
id: userId,
passwordHashCounter: userPasswordHashCounter,
},
data: {
passwordHash,
passwordHashAlgorithmId,
passwordSalt,
passwordHashCounter: { increment: 1 },
},
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2025") {
throw new faroe_user_server.ActionError("user_not_found");
}
throw new faroe_user_server.ActionError("unexpected_error");
}
},
async incrementUserSessionsCounterAction(_actionInvocationId, userId, userSessionsCounter) {
try {
await prisma.user.update({
where: {
id: userId,
sessionsCounter: userSessionsCounter,
},
data: {
sessionsCounter: { increment: 1 },
},
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2025") {
throw new faroe_user_server.ActionError("user_not_found");
}
throw new faroe_user_server.ActionError("unexpected_error");
}
},
async deleteUserAction(_actionInvocationId, userId) {
try {
await prisma.user.delete({
where: { id: userId },
});
} catch (error) {
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2025") {
throw new faroe_user_server.ActionError("user_not_found");
}
throw new faroe_user_server.ActionError("unexpected_error");
}
},
};