diff --git a/prisma/migrations/20260304200000_make_all_users_admin/migration.sql b/prisma/migrations/20260304200000_make_all_users_admin/migration.sql new file mode 100644 index 0000000..1e85814 --- /dev/null +++ b/prisma/migrations/20260304200000_make_all_users_admin/migration.sql @@ -0,0 +1,5 @@ +-- Promote all existing users to ADMIN (self-hosted: every user is an admin) +UPDATE "User" SET "role" = 'ADMIN' WHERE "role" = 'USER'; + +-- Change the default role for new users to ADMIN +ALTER TABLE "User" ALTER COLUMN "role" SET DEFAULT 'ADMIN'; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 383f5f1..b78ea48 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -22,7 +22,7 @@ model User { emailVerified DateTime? image String? hashedPassword String? - role Role @default(USER) + role Role @default(ADMIN) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt diff --git a/src/app/(auth)/register/actions.ts b/src/app/(auth)/register/actions.ts index 68463eb..e17fd53 100644 --- a/src/app/(auth)/register/actions.ts +++ b/src/app/(auth)/register/actions.ts @@ -21,27 +21,22 @@ export async function registerUser(input: unknown): Promise { - const userCount = await tx.user.count(); - const role = userCount === 0 ? "ADMIN" : "USER"; - - return tx.user.create({ - data: { - name: parsed.data.name, - email: parsed.data.email, - hashedPassword, - role, - settings: { - create: { - lowStockThreshold: 10, - currency: "USD", - theme: "dark", - units: "metric", - }, + // Self-hosted: all users are admins + const user = await prisma.user.create({ + data: { + name: parsed.data.name, + email: parsed.data.email, + hashedPassword, + role: "ADMIN", + settings: { + create: { + lowStockThreshold: 10, + currency: "USD", + theme: "dark", + units: "metric", }, }, - }); + }, }); return { success: true, data: { id: user.id } }; diff --git a/src/lib/auth.ts b/src/lib/auth.ts index ee26737..d0aa2a5 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -18,12 +18,12 @@ export const { auth, handlers, signIn, signOut } = NextAuth({ async jwt({ token, user }) { if (user) { token.id = user.id!; - // Fetch the role from the database to pick up first-user ADMIN promotion + // Fetch the role from the database to ensure token reflects current role const dbUser = await prisma.user.findUnique({ where: { id: user.id! }, select: { role: true }, }); - token.role = dbUser?.role ?? user.role ?? "USER"; + token.role = dbUser?.role ?? user.role ?? "ADMIN"; } return token; }, @@ -38,17 +38,11 @@ export const { auth, handlers, signIn, signOut } = NextAuth({ events: { async createUser({ user }) { if (user.id) { - // First user to register becomes ADMIN (self-hosted owner) - const adminExists = await prisma.user.findFirst({ - where: { role: "ADMIN" }, - select: { id: true }, + // Self-hosted: all users are admins + await prisma.user.update({ + where: { id: user.id }, + data: { role: "ADMIN" }, }); - if (!adminExists) { - await prisma.user.update({ - where: { id: user.id }, - data: { role: "ADMIN" }, - }); - } await prisma.userSettings.upsert({ where: { userId: user.id },