Allow SITE_ADMIN to login across all tenants
Login now falls back to a cross-tenant lookup for SITE_ADMIN users when the email isn't found in the current tenant. Regular users remain scoped to their own tenant. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { json, error } from '@sveltejs/kit';
|
|||||||
import type { RequestHandler } from './$types.js';
|
import type { RequestHandler } from './$types.js';
|
||||||
import { verifyPassword, createSession, sessionCookieName, sessionCookieOptions } from '$lib/server/auth.js';
|
import { verifyPassword, createSession, sessionCookieName, sessionCookieOptions } from '$lib/server/auth.js';
|
||||||
import { loginSchema } from '$lib/server/validation.js';
|
import { loginSchema } from '$lib/server/validation.js';
|
||||||
import { withTenant } from '$lib/server/rls.js';
|
import { withTenant, withBypassRLS } from '$lib/server/rls.js';
|
||||||
import { loginLimiter } from '$lib/server/ratelimit.js';
|
import { loginLimiter } from '$lib/server/ratelimit.js';
|
||||||
|
|
||||||
export const POST: RequestHandler = async ({ request, locals, cookies, getClientAddress }) => {
|
export const POST: RequestHandler = async ({ request, locals, cookies, getClientAddress }) => {
|
||||||
@@ -22,17 +22,26 @@ export const POST: RequestHandler = async ({ request, locals, cookies, getClient
|
|||||||
|
|
||||||
const { email, password } = result.data;
|
const { email, password } = result.data;
|
||||||
|
|
||||||
const user = await withTenant(tenant.id, async (tx) => {
|
// 1. Try tenant-scoped lookup (normal users)
|
||||||
|
let user = await withTenant(tenant.id, async (tx) => {
|
||||||
return tx.user.findUnique({
|
return tx.user.findUnique({
|
||||||
where: { tenantId_email: { tenantId: tenant.id, email } }
|
where: { tenantId_email: { tenantId: tenant.id, email } }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 2. Fall back to cross-tenant lookup for SITE_ADMIN
|
||||||
|
if (!user) {
|
||||||
|
user = await withBypassRLS(async (tx) => {
|
||||||
|
return tx.user.findFirst({
|
||||||
|
where: { email, globalRole: 'SITE_ADMIN' }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return json({ error: 'Invalid email or password' }, { status: 401 });
|
return json({ error: 'Invalid email or password' }, { status: 401 });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify password outside transaction
|
|
||||||
const valid = await verifyPassword(password, user.passwordHash);
|
const valid = await verifyPassword(password, user.passwordHash);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return json({ error: 'Invalid email or password' }, { status: 401 });
|
return json({ error: 'Invalid email or password' }, { status: 401 });
|
||||||
|
|||||||
Reference in New Issue
Block a user