nitropage
Version:
A free and open source, extensible visual page builder based on SolidStart.
143 lines (123 loc) • 2.98 kB
text/typescript
import { createId } from "@paralleldrive/cuid2";
import { NitroUser } from "@prisma/client";
import { redirect } from "@solidjs/router";
import { useRequestRef } from "../cache";
import { createServer } from "./core/server";
import { useServerConfig } from "../server/config";
import { hashPassword, validatePassword } from "../server/crypto";
import { useDatabase } from "../server/prisma";
export const { handler, Auth, getSession, assertCsrf, signin } = createServer(
"np",
{
config: () => useServerConfig().auth,
signin: async function ({
username,
password,
}: {
username: string;
password: string;
}) {
const db = useDatabase();
const user = await db.nitroUser.findFirst({
where: {
[username.includes("@") ? "email" : "username"]: username,
},
});
if (!user) {
return;
}
const passwordCorrect = await validatePassword(password, user.password);
if (!passwordCorrect) {
return;
}
return {
id: user.id,
user: user.username,
};
},
},
);
export const getUser = async ({
assert,
}: {
assert?: {
csrf?: string | true;
};
} = {}) => {
if (assert?.csrf !== undefined) {
await assertCsrf(assert.csrf);
}
const session = await getSession();
if (!session?.data?.id) {
if (assert) {
throw new Error("Access denied!");
}
return;
}
const usersRef = useRequestRef<Record<string, Partial<NitroUser>>>(
"npUsers",
() => ({}),
);
const db = useDatabase();
const user =
usersRef.current[session.data.id] ||
(await db.nitroUser.findFirst({
select: {
id: true,
email: true,
createdAt: true,
updatedAt: true,
username: true,
},
where: {
id: session.data.id,
},
}));
if (!user) {
if (assert) {
throw new Error("Access denied!");
}
return;
}
usersRef.current[session.data.id] = user;
return {
...user,
csrf: session.csrf,
};
};
export const signup = async function (args: {
username: string;
password: string;
email: string;
}) {
// TODO: allow signup of more users by logged in admins
// TODO: add a check to avoid creating duplicate users
const db = useDatabase();
const users = await db.nitroUser.count();
if (users > 0) {
return false;
}
const passwordHashed = await hashPassword(args.password);
const user = await db.nitroUser.create({
data: {
admin: true,
username: args.username,
email: args.email,
password: passwordHashed,
},
});
await signin({
username: user.username,
password: args.password,
});
if (await db.nitroProject.count()) {
return;
}
const firstProject = await db.nitroProject.create({
data: {
publicId: createId(),
title: "My first project",
},
});
throw redirect(`/admin/project/${firstProject.id}`);
};