Portal-Login: Mitarbeiter kommen ins Admin-Panel, Admin-Label bleibt WOMS-Rolle
Bisher liess /api/auth/login nur Appwrite-User mit dem Label "admin" in die Admin-Ansicht; alle anderen fielen in den Kunden-Login und bekamen "Kein Kundenkonto fuer diesen Login gefunden". Mitarbeiter ohne Admin-Haken (z.B. nico@webklar.com) kamen damit nicht auf /admin.html. Jetzt gilt: Wer in der employees-Collection steht, ist Backoffice-Nutzer. Das Label "admin" ist nur noch die WOMS-Adminrolle (Mitarbeiterverwaltung) und wird als isAdmin-Flag in der Portal-Session bzw. in den Preview-Token-Labels mitgefuehrt - inklusive "Als Kunde ansehen" und zurueck. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,8 @@ import {
|
||||
getCustomerByAppwriteUserId,
|
||||
getCustomerByEmail,
|
||||
getDocument,
|
||||
getEmployeeByEmail,
|
||||
getEmployeeByUserId,
|
||||
getPortalAccessByCustomerId,
|
||||
getUserById,
|
||||
listDocuments,
|
||||
@@ -40,6 +42,32 @@ function sanitizeCustomer(customer) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Backoffice-Login: Jeder Mitarbeiter aus der employees-Collection darf ins
|
||||
* Admin-Panel (/admin.html). Das Appwrite-Label "admin" ist ausschliesslich die
|
||||
* WOMS-Adminrolle (Mitarbeiterverwaltung) und KEINE Voraussetzung fuer den
|
||||
* Portalzugang - es wird nur als Flag in der Session mitgefuehrt.
|
||||
* Gibt null zurueck, wenn der Login kein Mitarbeiter ist (dann greift der
|
||||
* normale Kunden-Login).
|
||||
*/
|
||||
async function resolveStaffAccount(appwriteUserId, email) {
|
||||
const account = await getUserById(appwriteUserId).catch(() => null)
|
||||
const isAdmin = Array.isArray(account?.labels) && account.labels.includes('admin')
|
||||
|
||||
let employee = await getEmployeeByUserId(appwriteUserId).catch(() => null)
|
||||
if (!employee) {
|
||||
employee = await getEmployeeByEmail(account?.email || email).catch(() => null)
|
||||
}
|
||||
|
||||
if (!employee && !isAdmin) return null
|
||||
|
||||
return {
|
||||
isAdmin,
|
||||
name: employee?.displayName || account?.name || 'Mitarbeiter',
|
||||
email: account?.email || employee?.email || email,
|
||||
}
|
||||
}
|
||||
|
||||
async function validatePortalAccess(appwriteUserId, email) {
|
||||
let customer = await getCustomerByAppwriteUserId(appwriteUserId)
|
||||
if (!customer && email) {
|
||||
@@ -149,28 +177,31 @@ router.post('/login', async (req, res) => {
|
||||
try {
|
||||
const user = await loginWithAppwrite(email.trim(), password)
|
||||
|
||||
// Ticketsystem-Admins (Appwrite-Label "admin") bekommen die Admin-Ansicht
|
||||
const account = await getUserById(user.$id).catch(() => null)
|
||||
if (Array.isArray(account?.labels) && account.labels.includes('admin')) {
|
||||
const adminName = account.name || 'Admin'
|
||||
const adminEmail = account.email || email.trim()
|
||||
// Ticketsystem-Mitarbeiter (employees-Collection) bekommen die Admin-Ansicht
|
||||
const staff = await resolveStaffAccount(user.$id, email.trim())
|
||||
if (staff) {
|
||||
setPortalSession(res, {
|
||||
role: 'admin',
|
||||
isAdmin: staff.isAdmin,
|
||||
appwriteUserId: user.$id,
|
||||
name: adminName,
|
||||
email: adminEmail,
|
||||
name: staff.name,
|
||||
email: staff.email,
|
||||
})
|
||||
const adminPreviewToken = await createPreviewSessionToken({
|
||||
const staffPreviewToken = await createPreviewSessionToken({
|
||||
userId: user.$id,
|
||||
customerId: '',
|
||||
email: adminEmail,
|
||||
name: adminName,
|
||||
email: staff.email,
|
||||
name: staff.name,
|
||||
role: 'admin',
|
||||
labels: ['admin'],
|
||||
labels: staff.isAdmin ? ['admin'] : [],
|
||||
authSource: 'kundenbereich-admin',
|
||||
})
|
||||
res.cookie(PREVIEW_COOKIE_NAME, adminPreviewToken, previewSessionCookieOptions())
|
||||
return res.json({ success: true, role: 'admin', admin: { name: adminName, email: adminEmail } })
|
||||
res.cookie(PREVIEW_COOKIE_NAME, staffPreviewToken, previewSessionCookieOptions())
|
||||
return res.json({
|
||||
success: true,
|
||||
role: 'admin',
|
||||
admin: { name: staff.name, email: staff.email, isAdmin: staff.isAdmin },
|
||||
})
|
||||
}
|
||||
|
||||
let { customer, portalAccess } = await validatePortalAccess(user.$id, email.trim())
|
||||
@@ -324,6 +355,9 @@ router.get('/me', async (req, res) => {
|
||||
|
||||
// Admin-Session (Ticketsystem-Mitarbeiter), optional im "Als Kunde ansehen"-Modus
|
||||
if (session.role === 'admin' && session.appwriteUserId) {
|
||||
// Sessions von vor der Mitarbeiter-Freigabe kennen das Flag nicht - die
|
||||
// konnten nur Admins bekommen, also als Admin werten.
|
||||
const isAdmin = session.isAdmin === undefined ? true : Boolean(session.isAdmin)
|
||||
let customer = null
|
||||
if (session.customerId) {
|
||||
const doc = await getDocument(config.collections.customers, session.customerId).catch(() => null)
|
||||
@@ -335,7 +369,7 @@ router.get('/me', async (req, res) => {
|
||||
email: session.adminEmail || session.email || '',
|
||||
name: session.adminName || session.name || 'Admin',
|
||||
role: 'admin',
|
||||
labels: ['admin'],
|
||||
labels: isAdmin ? ['admin'] : [],
|
||||
authSource: 'kundenbereich-admin',
|
||||
})
|
||||
return res.json({
|
||||
@@ -345,6 +379,7 @@ router.get('/me', async (req, res) => {
|
||||
admin: {
|
||||
name: session.adminName || session.name || 'Admin',
|
||||
email: session.adminEmail || session.email || '',
|
||||
isAdmin,
|
||||
},
|
||||
customer,
|
||||
})
|
||||
|
||||
@@ -408,6 +408,7 @@ router.post('/view-as/:customerId', async (req, res) => {
|
||||
setPortalSession(res, {
|
||||
role: 'admin',
|
||||
viewAs: true,
|
||||
isAdmin: session.isAdmin,
|
||||
appwriteUserId: session.appwriteUserId,
|
||||
adminName: session.adminName || session.name || 'Admin',
|
||||
adminEmail: session.adminEmail || session.email || '',
|
||||
@@ -425,6 +426,7 @@ router.post('/exit-view-as', (req, res) => {
|
||||
const session = parsePortalSession(req) || req.session
|
||||
setPortalSession(res, {
|
||||
role: 'admin',
|
||||
isAdmin: session.isAdmin,
|
||||
appwriteUserId: session.appwriteUserId,
|
||||
name: session.adminName || session.name || 'Admin',
|
||||
email: session.adminEmail || session.email || '',
|
||||
|
||||
@@ -162,6 +162,24 @@ export async function getCustomerByEmail(email) {
|
||||
return docs[0] || null
|
||||
}
|
||||
|
||||
export async function getEmployeeByUserId(userId) {
|
||||
if (!userId) return null
|
||||
const docs = await listDocuments(config.collections.employees, [
|
||||
Query.equal('userId', userId),
|
||||
Query.limit(1),
|
||||
])
|
||||
return docs[0] || null
|
||||
}
|
||||
|
||||
export async function getEmployeeByEmail(email) {
|
||||
if (!email) return null
|
||||
const docs = await listDocuments(config.collections.employees, [
|
||||
Query.equal('email', email.trim().toLowerCase()),
|
||||
Query.limit(1),
|
||||
])
|
||||
return docs[0] || null
|
||||
}
|
||||
|
||||
export async function getPortalAccessByCustomerId(customerId) {
|
||||
const docs = await listDocuments(config.collections.customerPortalAccess, [
|
||||
Query.equal('customerId', customerId),
|
||||
|
||||
Reference in New Issue
Block a user