Updated to using managed types instead of
hard coded ones.
This commit is contained in:
@@ -1,7 +1,20 @@
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { safeQuery } from "@/lib/database"
|
||||
import { hashPassword } from "@/lib/auth"
|
||||
import { type UserRole, DEPARTMENTS, TEAMS, FIELDS } from "@/types/user"
|
||||
import { type UserRole } from "@/types/user"
|
||||
|
||||
const hasManagedType = async (type: "field" | "department" | "team", name: string) => {
|
||||
const rows = (await safeQuery("SELECT 1 FROM managed_types WHERE type = ? AND name = ? LIMIT 1", [
|
||||
type,
|
||||
name,
|
||||
])) as any[]
|
||||
if (rows.length > 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
const legacyRows = (await safeQuery(`SELECT 1 FROM users WHERE ${type} = ? LIMIT 1`, [name])) as any[]
|
||||
return legacyRows.length > 0
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
@@ -12,17 +25,41 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: "נתונים חסרים" }, { status: 400 })
|
||||
}
|
||||
|
||||
// Validate department, team, and field
|
||||
if (!FIELDS.includes(field as any)) {
|
||||
return NextResponse.json({ error: "תחום לא תקין" }, { status: 400 })
|
||||
// Validate department, team, and field against managed types
|
||||
if (!(await hasManagedType("field", field))) {
|
||||
return NextResponse.json({ error: "Invalid field." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!DEPARTMENTS.includes(department as any)) {
|
||||
return NextResponse.json({ error: "מסגרת לא תקינה" }, { status: 400 })
|
||||
if (!(await hasManagedType("department", department))) {
|
||||
return NextResponse.json({ error: "Invalid department." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (!TEAMS.includes(team as any)) {
|
||||
return NextResponse.json({ error: "צוות לא תקין" }, { status: 400 })
|
||||
if (!(await hasManagedType("team", team))) {
|
||||
return NextResponse.json({ error: "Invalid team." }, { status: 400 })
|
||||
}
|
||||
|
||||
const fieldRows = (await safeQuery("SELECT id FROM managed_types WHERE type = 'field' AND name = ?", [
|
||||
field,
|
||||
])) as Array<{ id: number }>
|
||||
const departmentRows = (await safeQuery(
|
||||
"SELECT id, parent_id AS parentId FROM managed_types WHERE type = 'department' AND name = ?",
|
||||
[department],
|
||||
)) as Array<{ id: number; parentId: number | null }>
|
||||
const teamRows = (await safeQuery(
|
||||
"SELECT id, parent_id AS parentId FROM managed_types WHERE type = 'team' AND name = ?",
|
||||
[team],
|
||||
)) as Array<{ id: number; parentId: number | null }>
|
||||
|
||||
if (fieldRows.length === 0 || departmentRows.length === 0 || teamRows.length === 0) {
|
||||
return NextResponse.json({ error: "Invalid field, department, or team." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (departmentRows[0].parentId !== fieldRows[0].id) {
|
||||
return NextResponse.json({ error: "Department does not belong to field." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (teamRows[0].parentId !== departmentRows[0].id) {
|
||||
return NextResponse.json({ error: "Team does not belong to department." }, { status: 400 })
|
||||
}
|
||||
|
||||
const validRoles: UserRole[] = ["user", "team_admin", "department_admin", "field_admin", "global_admin"]
|
||||
|
||||
151
app/api/admin/managed-types/[id]/route.ts
Normal file
151
app/api/admin/managed-types/[id]/route.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { safeQuery } from "@/lib/database"
|
||||
|
||||
type ManagedTypeKind = "field" | "department" | "team"
|
||||
|
||||
type AdminScope = {
|
||||
role: string
|
||||
field?: string | null
|
||||
department?: string | null
|
||||
team?: string | null
|
||||
}
|
||||
|
||||
const getAdminScope = async (adminId?: string) => {
|
||||
if (!adminId) {
|
||||
return { ok: false, response: NextResponse.json({ error: "Missing admin id." }, { status: 400 }) }
|
||||
}
|
||||
|
||||
const adminRows = (await safeQuery("SELECT role, field, department, team FROM users WHERE national_id = ?", [
|
||||
adminId,
|
||||
])) as AdminScope[]
|
||||
if (adminRows.length === 0) {
|
||||
return { ok: false, response: NextResponse.json({ error: "Admin not found." }, { status: 404 }) }
|
||||
}
|
||||
|
||||
return { ok: true as const, admin: adminRows[0] }
|
||||
}
|
||||
|
||||
const canManageType = async (admin: AdminScope, managedType: { type: ManagedTypeKind; name: string; parentId: number | null }) => {
|
||||
if (admin.role === "global_admin") return true
|
||||
if (admin.role === "field_admin") {
|
||||
if (managedType.type === "field") return managedType.name === admin.field
|
||||
if (managedType.type === "department") {
|
||||
const fieldRows = (await safeQuery("SELECT id FROM managed_types WHERE type = 'field' AND name = ?", [
|
||||
admin.field,
|
||||
])) as Array<{ id: number }>
|
||||
return fieldRows.length > 0 && managedType.parentId === fieldRows[0].id
|
||||
}
|
||||
if (managedType.type === "team") {
|
||||
const departmentRows = (await safeQuery(
|
||||
"SELECT parent_id AS parentId FROM managed_types WHERE id = ? AND type = 'department'",
|
||||
[managedType.parentId],
|
||||
)) as Array<{ parentId: number | null }>
|
||||
if (departmentRows.length === 0) return false
|
||||
const fieldRows = (await safeQuery("SELECT id FROM managed_types WHERE type = 'field' AND name = ?", [
|
||||
admin.field,
|
||||
])) as Array<{ id: number }>
|
||||
return fieldRows.length > 0 && departmentRows[0].parentId === fieldRows[0].id
|
||||
}
|
||||
}
|
||||
if (admin.role === "department_admin") {
|
||||
if (managedType.type === "department") return managedType.name === admin.department
|
||||
if (managedType.type === "team") {
|
||||
const departmentRows = (await safeQuery(
|
||||
"SELECT id FROM managed_types WHERE type = 'department' AND name = ?",
|
||||
[admin.department],
|
||||
)) as Array<{ id: number }>
|
||||
return departmentRows.length > 0 && managedType.parentId === departmentRows[0].id
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export async function DELETE(request: NextRequest, { params }: { params: { id: string } }) {
|
||||
try {
|
||||
const { adminId } = await request.json()
|
||||
|
||||
const adminCheck = await getAdminScope(adminId)
|
||||
if (!adminCheck.ok) {
|
||||
return adminCheck.response
|
||||
}
|
||||
|
||||
const typeRows = (await safeQuery("SELECT id, type, name, parent_id AS parentId FROM managed_types WHERE id = ?", [
|
||||
params.id,
|
||||
])) as Array<{ id: number; type: ManagedTypeKind; name: string; parentId: number | null }>
|
||||
|
||||
if (typeRows.length === 0) {
|
||||
return NextResponse.json({ error: "Managed type not found." }, { status: 404 })
|
||||
}
|
||||
|
||||
const managedType = typeRows[0]
|
||||
const column = managedType.type
|
||||
|
||||
if (!(await canManageType(adminCheck.admin, managedType))) {
|
||||
return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
|
||||
}
|
||||
|
||||
const childRows = (await safeQuery("SELECT COUNT(*) as count FROM managed_types WHERE parent_id = ?", [
|
||||
managedType.id,
|
||||
])) as Array<{ count: number }>
|
||||
if ((childRows[0]?.count || 0) > 0) {
|
||||
return NextResponse.json({ error: "Remove child items first." }, { status: 409 })
|
||||
}
|
||||
|
||||
const usageRows = (await safeQuery(`SELECT COUNT(*) as count FROM users WHERE ${column} = ?`, [
|
||||
managedType.name,
|
||||
])) as Array<{ count: number }>
|
||||
|
||||
if ((usageRows[0]?.count || 0) > 0) {
|
||||
return NextResponse.json({ error: "Value is still assigned to users." }, { status: 409 })
|
||||
}
|
||||
|
||||
await safeQuery("DELETE FROM managed_types WHERE id = ?", [managedType.id])
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
} catch (error) {
|
||||
console.error("Managed types delete error:", error)
|
||||
return NextResponse.json({ error: "Failed to delete managed type." }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function PATCH(request: NextRequest, { params }: { params: { id: string } }) {
|
||||
try {
|
||||
const { adminId, name } = await request.json()
|
||||
|
||||
const adminCheck = await getAdminScope(adminId)
|
||||
if (!adminCheck.ok) {
|
||||
return adminCheck.response
|
||||
}
|
||||
|
||||
const trimmedName = typeof name === "string" ? name.trim() : ""
|
||||
if (!trimmedName) {
|
||||
return NextResponse.json({ error: "Name is required." }, { status: 400 })
|
||||
}
|
||||
|
||||
const typeRows = (await safeQuery("SELECT id, type, name, parent_id AS parentId FROM managed_types WHERE id = ?", [
|
||||
params.id,
|
||||
])) as Array<{ id: number; type: ManagedTypeKind; name: string; parentId: number | null }>
|
||||
|
||||
if (typeRows.length === 0) {
|
||||
return NextResponse.json({ error: "Managed type not found." }, { status: 404 })
|
||||
}
|
||||
|
||||
const managedType = typeRows[0]
|
||||
if (!(await canManageType(adminCheck.admin, managedType))) {
|
||||
return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
|
||||
}
|
||||
|
||||
await safeQuery("UPDATE managed_types SET name = ? WHERE id = ?", [trimmedName, managedType.id])
|
||||
|
||||
const column = managedType.type
|
||||
await safeQuery(`UPDATE users SET ${column} = ? WHERE ${column} = ?`, [trimmedName, managedType.name])
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
} catch (error: any) {
|
||||
if (error?.code === "ER_DUP_ENTRY") {
|
||||
return NextResponse.json({ error: "Value already exists." }, { status: 409 })
|
||||
}
|
||||
console.error("Managed types rename error:", error)
|
||||
return NextResponse.json({ error: "Failed to rename managed type." }, { status: 500 })
|
||||
}
|
||||
}
|
||||
203
app/api/admin/managed-types/route.ts
Normal file
203
app/api/admin/managed-types/route.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { safeQuery } from "@/lib/database"
|
||||
|
||||
type ManagedTypeKind = "field" | "department" | "team"
|
||||
|
||||
const managedTypeKinds: ManagedTypeKind[] = ["field", "department", "team"]
|
||||
|
||||
type AdminScope = {
|
||||
role: string
|
||||
field?: string | null
|
||||
department?: string | null
|
||||
team?: string | null
|
||||
}
|
||||
|
||||
const getAdminScope = async (adminId?: string) => {
|
||||
if (!adminId) {
|
||||
return { ok: false, response: NextResponse.json({ error: "Missing admin id." }, { status: 400 }) }
|
||||
}
|
||||
|
||||
const adminRows = (await safeQuery("SELECT role, field, department, team FROM users WHERE national_id = ?", [
|
||||
adminId,
|
||||
])) as AdminScope[]
|
||||
|
||||
if (adminRows.length === 0) {
|
||||
return { ok: false, response: NextResponse.json({ error: "Admin not found." }, { status: 404 }) }
|
||||
}
|
||||
|
||||
return { ok: true as const, admin: adminRows[0] }
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const adminId = request.nextUrl.searchParams.get("adminId") || undefined
|
||||
const adminCheck = await getAdminScope(adminId)
|
||||
if (!adminCheck.ok) {
|
||||
return adminCheck.response
|
||||
}
|
||||
|
||||
const admin = adminCheck.admin
|
||||
|
||||
const managedRows = (await safeQuery(
|
||||
"SELECT id, type, name, parent_id AS parentId FROM managed_types ORDER BY type, name",
|
||||
)) as Array<{ id: number; type: ManagedTypeKind; name: string; parentId: number | null }>
|
||||
|
||||
const [fieldsFromUsers, departmentsFromUsers, teamsFromUsers] = await Promise.all([
|
||||
safeQuery("SELECT DISTINCT field AS name FROM users WHERE field IS NOT NULL AND field <> '' ORDER BY field"),
|
||||
safeQuery(
|
||||
"SELECT DISTINCT department AS name FROM users WHERE department IS NOT NULL AND department <> '' ORDER BY department",
|
||||
),
|
||||
safeQuery("SELECT DISTINCT team AS name FROM users WHERE team IS NOT NULL AND team <> '' ORDER BY team"),
|
||||
])
|
||||
|
||||
const byType = {
|
||||
field: managedRows.filter((row) => row.type === "field"),
|
||||
department: managedRows.filter((row) => row.type === "department"),
|
||||
team: managedRows.filter((row) => row.type === "team"),
|
||||
}
|
||||
|
||||
const merge = (
|
||||
managed: Array<{ id: number; name: string; parentId: number | null }>,
|
||||
fromUsers: Array<{ name: string }>,
|
||||
) => {
|
||||
const map = new Map<
|
||||
string,
|
||||
{ id?: number; name: string; managed: boolean; parentId?: number | null }
|
||||
>()
|
||||
|
||||
managed.forEach((row) => {
|
||||
map.set(row.name, { id: row.id, name: row.name, managed: true, parentId: row.parentId })
|
||||
})
|
||||
|
||||
fromUsers.forEach((row) => {
|
||||
if (!map.has(row.name)) {
|
||||
map.set(row.name, { name: row.name, managed: false, parentId: null })
|
||||
}
|
||||
})
|
||||
|
||||
return Array.from(map.values()).sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
|
||||
let fields = merge(byType.field, fieldsFromUsers as any[])
|
||||
let departments = merge(byType.department, departmentsFromUsers as any[])
|
||||
let teams = merge(byType.team, teamsFromUsers as any[])
|
||||
|
||||
if (admin.role === "field_admin") {
|
||||
fields = fields.filter((field) => field.name === admin.field)
|
||||
const fieldId = fields[0]?.id
|
||||
departments = fieldId ? departments.filter((dept) => dept.parentId === fieldId) : []
|
||||
const departmentIds = new Set(departments.map((dept) => dept.id))
|
||||
teams = teams.filter((team) => team.parentId && departmentIds.has(team.parentId))
|
||||
} else if (admin.role === "department_admin") {
|
||||
fields = fields.filter((field) => field.name === admin.field)
|
||||
departments = departments.filter((dept) => dept.name === admin.department)
|
||||
const departmentId = departments[0]?.id
|
||||
teams = departmentId ? teams.filter((team) => team.parentId === departmentId) : []
|
||||
} else if (admin.role === "team_admin") {
|
||||
fields = fields.filter((field) => field.name === admin.field)
|
||||
departments = departments.filter((dept) => dept.name === admin.department)
|
||||
teams = teams.filter((team) => team.name === admin.team)
|
||||
}
|
||||
|
||||
return NextResponse.json({ fields, departments, teams })
|
||||
} catch (error) {
|
||||
console.error("Managed types fetch error:", error)
|
||||
return NextResponse.json({ error: "Failed to load managed types." }, { status: 500 })
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { adminId, type, name, parentId } = await request.json()
|
||||
|
||||
const adminCheck = await getAdminScope(adminId)
|
||||
if (!adminCheck.ok) {
|
||||
return adminCheck.response
|
||||
}
|
||||
|
||||
const admin = adminCheck.admin
|
||||
|
||||
if (!managedTypeKinds.includes(type)) {
|
||||
return NextResponse.json({ error: "Invalid type." }, { status: 400 })
|
||||
}
|
||||
|
||||
const trimmedName = typeof name === "string" ? name.trim() : ""
|
||||
if (!trimmedName) {
|
||||
return NextResponse.json({ error: "Name is required." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (type === "field") {
|
||||
if (admin.role !== "global_admin" && admin.role !== "field_admin") {
|
||||
return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
|
||||
}
|
||||
if (admin.role === "field_admin" && admin.field && admin.field !== trimmedName) {
|
||||
return NextResponse.json({ error: "Field admins can only manage their field." }, { status: 403 })
|
||||
}
|
||||
await safeQuery("INSERT INTO managed_types (type, name, parent_id) VALUES (?, ?, NULL)", [type, trimmedName])
|
||||
} else if (type === "department") {
|
||||
if (!parentId) {
|
||||
return NextResponse.json({ error: "Parent field is required." }, { status: 400 })
|
||||
}
|
||||
if (admin.role === "department_admin" || admin.role === "team_admin") {
|
||||
return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
|
||||
}
|
||||
if (admin.role === "field_admin") {
|
||||
const fieldRows = (await safeQuery("SELECT id, name FROM managed_types WHERE id = ? AND type = 'field'", [
|
||||
parentId,
|
||||
])) as Array<{ id: number; name: string }>
|
||||
if (fieldRows.length === 0 || fieldRows[0].name !== admin.field) {
|
||||
return NextResponse.json({ error: "Field admins can only manage their field." }, { status: 403 })
|
||||
}
|
||||
}
|
||||
await safeQuery("INSERT INTO managed_types (type, name, parent_id) VALUES (?, ?, ?)", [
|
||||
type,
|
||||
trimmedName,
|
||||
parentId,
|
||||
])
|
||||
} else {
|
||||
if (!parentId) {
|
||||
return NextResponse.json({ error: "Parent department is required." }, { status: 400 })
|
||||
}
|
||||
if (admin.role === "team_admin") {
|
||||
return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
|
||||
}
|
||||
if (admin.role === "department_admin") {
|
||||
const departmentRows = (await safeQuery(
|
||||
"SELECT id, name FROM managed_types WHERE id = ? AND type = 'department'",
|
||||
[parentId],
|
||||
)) as Array<{ id: number; name: string }>
|
||||
if (departmentRows.length === 0 || departmentRows[0].name !== admin.department) {
|
||||
return NextResponse.json({ error: "Department admins can only manage their department." }, { status: 403 })
|
||||
}
|
||||
}
|
||||
if (admin.role === "field_admin") {
|
||||
const departmentRows = (await safeQuery(
|
||||
"SELECT id, parent_id AS parentId FROM managed_types WHERE id = ? AND type = 'department'",
|
||||
[parentId],
|
||||
)) as Array<{ id: number; parentId: number | null }>
|
||||
if (departmentRows.length === 0) {
|
||||
return NextResponse.json({ error: "Department not found." }, { status: 404 })
|
||||
}
|
||||
const fieldRows = (await safeQuery("SELECT id, name FROM managed_types WHERE id = ?", [
|
||||
departmentRows[0].parentId,
|
||||
])) as Array<{ id: number; name: string }>
|
||||
if (fieldRows.length === 0 || fieldRows[0].name !== admin.field) {
|
||||
return NextResponse.json({ error: "Field admins can only manage their field." }, { status: 403 })
|
||||
}
|
||||
}
|
||||
await safeQuery("INSERT INTO managed_types (type, name, parent_id) VALUES (?, ?, ?)", [
|
||||
type,
|
||||
trimmedName,
|
||||
parentId,
|
||||
])
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
} catch (error: any) {
|
||||
if (error?.code === "ER_DUP_ENTRY") {
|
||||
return NextResponse.json({ error: "Value already exists." }, { status: 409 })
|
||||
}
|
||||
console.error("Managed types create error:", error)
|
||||
return NextResponse.json({ error: "Failed to create managed type." }, { status: 500 })
|
||||
}
|
||||
}
|
||||
122
app/api/admin/update-user-scope/route.ts
Normal file
122
app/api/admin/update-user-scope/route.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { type NextRequest, NextResponse } from "next/server"
|
||||
import { safeQuery } from "@/lib/database"
|
||||
|
||||
const hasManagedType = async (type: "field" | "department" | "team", name: string) => {
|
||||
const rows = (await safeQuery("SELECT 1 FROM managed_types WHERE type = ? AND name = ? LIMIT 1", [
|
||||
type,
|
||||
name,
|
||||
])) as any[]
|
||||
if (rows.length > 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
const legacyRows = (await safeQuery(`SELECT 1 FROM users WHERE ${type} = ? LIMIT 1`, [name])) as any[]
|
||||
return legacyRows.length > 0
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { adminId, targetUserId, field, department, team } = await request.json()
|
||||
|
||||
if (!adminId || !targetUserId || !field || !department || !team) {
|
||||
return NextResponse.json({ error: "Missing required fields." }, { status: 400 })
|
||||
}
|
||||
|
||||
const adminRows = (await safeQuery("SELECT role, field, department, team FROM users WHERE national_id = ?", [
|
||||
adminId,
|
||||
])) as any[]
|
||||
if (adminRows.length === 0) {
|
||||
return NextResponse.json({ error: "Admin not found." }, { status: 404 })
|
||||
}
|
||||
|
||||
const admin = adminRows[0]
|
||||
|
||||
const userRows = (await safeQuery("SELECT national_id, field, department, team FROM users WHERE national_id = ?", [
|
||||
targetUserId,
|
||||
])) as any[]
|
||||
if (userRows.length === 0) {
|
||||
return NextResponse.json({ error: "User not found." }, { status: 404 })
|
||||
}
|
||||
const targetUser = userRows[0]
|
||||
|
||||
const [fieldOk, departmentOk, teamOk] = await Promise.all([
|
||||
hasManagedType("field", field),
|
||||
hasManagedType("department", department),
|
||||
hasManagedType("team", team),
|
||||
])
|
||||
|
||||
if (!fieldOk || !departmentOk || !teamOk) {
|
||||
return NextResponse.json({ error: "Invalid field, department, or team." }, { status: 400 })
|
||||
}
|
||||
|
||||
const fieldRows = (await safeQuery("SELECT id FROM managed_types WHERE type = 'field' AND name = ?", [
|
||||
field,
|
||||
])) as Array<{ id: number }>
|
||||
const departmentRows = (await safeQuery(
|
||||
"SELECT id, parent_id AS parentId FROM managed_types WHERE type = 'department' AND name = ?",
|
||||
[department],
|
||||
)) as Array<{ id: number; parentId: number | null }>
|
||||
const teamRows = (await safeQuery(
|
||||
"SELECT id, parent_id AS parentId FROM managed_types WHERE type = 'team' AND name = ?",
|
||||
[team],
|
||||
)) as Array<{ id: number; parentId: number | null }>
|
||||
|
||||
if (fieldRows.length === 0 || departmentRows.length === 0 || teamRows.length === 0) {
|
||||
return NextResponse.json({ error: "Invalid field, department, or team." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (departmentRows[0].parentId !== fieldRows[0].id) {
|
||||
return NextResponse.json({ error: "Department does not belong to field." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (teamRows[0].parentId !== departmentRows[0].id) {
|
||||
return NextResponse.json({ error: "Team does not belong to department." }, { status: 400 })
|
||||
}
|
||||
|
||||
if (admin.role === "field_admin") {
|
||||
if (targetUser.field !== admin.field) {
|
||||
return NextResponse.json({ error: "Target user is outside your field." }, { status: 403 })
|
||||
}
|
||||
if (field !== admin.field) {
|
||||
return NextResponse.json({ error: "Field admins can only assign within their field." }, { status: 403 })
|
||||
}
|
||||
} else if (admin.role === "department_admin") {
|
||||
if (targetUser.department !== admin.department) {
|
||||
return NextResponse.json({ error: "Target user is outside your department." }, { status: 403 })
|
||||
}
|
||||
if (department !== admin.department) {
|
||||
return NextResponse.json({ error: "Department admins can only assign within their department." }, { status: 403 })
|
||||
}
|
||||
if (admin.field && field !== admin.field) {
|
||||
return NextResponse.json({ error: "Department admins can only assign within their field." }, { status: 403 })
|
||||
}
|
||||
} else if (admin.role === "team_admin") {
|
||||
if (targetUser.team !== admin.team) {
|
||||
return NextResponse.json({ error: "Target user is outside your team." }, { status: 403 })
|
||||
}
|
||||
if (team !== admin.team) {
|
||||
return NextResponse.json({ error: "Team admins can only assign within their team." }, { status: 403 })
|
||||
}
|
||||
if (admin.department && department !== admin.department) {
|
||||
return NextResponse.json({ error: "Team admins can only assign within their department." }, { status: 403 })
|
||||
}
|
||||
if (admin.field && field !== admin.field) {
|
||||
return NextResponse.json({ error: "Team admins can only assign within their field." }, { status: 403 })
|
||||
}
|
||||
} else if (admin.role !== "global_admin") {
|
||||
return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
|
||||
}
|
||||
|
||||
await safeQuery("UPDATE users SET field = ?, department = ?, team = ? WHERE national_id = ?", [
|
||||
field,
|
||||
department,
|
||||
team,
|
||||
targetUserId,
|
||||
])
|
||||
|
||||
return NextResponse.json({ success: true, message: "User assignment updated." })
|
||||
} catch (error) {
|
||||
console.error("Update user scope error:", error)
|
||||
return NextResponse.json({ error: "Failed to update user." }, { status: 500 })
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user