feat: setup and roles
This commit is contained in:
+47
@@ -1,9 +1,29 @@
|
||||
import { drizzleAdapter } from "@better-auth/drizzle-adapter/relations-v2";
|
||||
import { db } from "../server/lib/db";
|
||||
import { APIError, createAuthMiddleware, getSessionFromCtx } from 'better-auth/api';
|
||||
import { betterAuth } from 'better-auth/minimal';
|
||||
import { createAccessControl } from 'better-auth/plugins/access';
|
||||
import { admin } from 'better-auth/plugins/admin';
|
||||
import { defaultStatements } from 'better-auth/plugins/admin/access';
|
||||
import { twoFactor } from 'better-auth/plugins/two-factor';
|
||||
import * as schema from '../drizzle/schema';
|
||||
|
||||
const accessControl = createAccessControl(defaultStatements);
|
||||
|
||||
// Admins manage accounts, not content. Signing in as someone else and setting
|
||||
// another user's password or email are left out on purpose: the first would
|
||||
// show their chats, the others would lock them out of their encrypted API keys.
|
||||
const roles = {
|
||||
admin: accessControl.newRole({
|
||||
user: ['create', 'list', 'set-role', 'ban', 'delete', 'get', 'update'],
|
||||
session: ['list', 'revoke', 'delete'],
|
||||
}),
|
||||
user: accessControl.newRole({
|
||||
user: [],
|
||||
session: [],
|
||||
}),
|
||||
};
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: drizzleAdapter(db, {
|
||||
provider: "pg",
|
||||
@@ -23,10 +43,37 @@ export const auth = betterAuth({
|
||||
baseURL: process.env.NUXT_PUBLIC_URL ?? 'http://localhost:3000',
|
||||
trustedOrigins: [process.env.NUXT_PUBLIC_URL ?? 'http://localhost:3000'],
|
||||
|
||||
hooks: {
|
||||
// The admin endpoints already stop admins from removing or disabling
|
||||
// themselves. Giving up their own admin role is the one way left to
|
||||
// end up with an instance nobody can manage, so that is refused too.
|
||||
before: createAuthMiddleware(async (ctx) => {
|
||||
if (ctx.path !== '/admin/set-role' && ctx.path !== '/admin/update-user') return;
|
||||
|
||||
const role = ctx.path === '/admin/set-role' ? ctx.body?.role : ctx.body?.data?.role;
|
||||
if (role === undefined) return;
|
||||
|
||||
const roleList = (Array.isArray(role) ? role : String(role).split(',')).map((r) => String(r).trim());
|
||||
if (roleList.includes('admin')) return;
|
||||
|
||||
const session = await getSessionFromCtx(ctx);
|
||||
if (session && String(ctx.body?.userId) === session.user.id) {
|
||||
throw new APIError('BAD_REQUEST', {
|
||||
message: 'You cannot remove your own admin role',
|
||||
code: 'YOU_CANNOT_DEMOTE_YOURSELF',
|
||||
});
|
||||
}
|
||||
}),
|
||||
},
|
||||
|
||||
plugins: [
|
||||
twoFactor({
|
||||
issuer: 'Veridian',
|
||||
}),
|
||||
admin({
|
||||
ac: accessControl,
|
||||
roles,
|
||||
}),
|
||||
],
|
||||
|
||||
emailAndPassword: {
|
||||
|
||||
Reference in New Issue
Block a user