mirror of
https://github.com/Since-3/Kuma.git
synced 2026-10-12 21:41:17 +00:00
see comments from commit #88
This commit is contained in:
parent
87dd836ddc
commit
a17047895b
4 changed files with 98 additions and 22 deletions
|
|
@ -145,7 +145,12 @@ export const getUserData = cache(async (): Promise<AuthUserData | null> => {
|
|||
|
||||
let permissions: EmployeeData["permissions"];
|
||||
|
||||
if (raw && ("canCreateCourses" in raw || "canCreateEmployees" in raw)) {
|
||||
if (
|
||||
raw &&
|
||||
typeof raw === "object" &&
|
||||
!Array.isArray(raw) &&
|
||||
("canCreateCourses" in raw || "canCreateEmployees" in raw)
|
||||
) {
|
||||
// Backward-Kompatibilität: altes Format migrieren
|
||||
const old = raw as { canCreateCourses?: boolean; canCreateEmployees?: boolean };
|
||||
permissions = {
|
||||
|
|
@ -210,6 +215,14 @@ export const getUserData = cache(async (): Promise<AuthUserData | null> => {
|
|||
)(user.email, user.id);
|
||||
});
|
||||
|
||||
// Returns the effective manager ID for any user type.
|
||||
// For Employees, this is createdBy (the manager who created them).
|
||||
// Returns null if the employee is orphaned (no manager mapping) — callers must handle this.
|
||||
export function getEffectiveManagerId(userData: AuthUserData): string | null {
|
||||
if (isEmployee(userData)) return userData.createdBy;
|
||||
return userData.id;
|
||||
}
|
||||
|
||||
export async function requireAuth() {
|
||||
const user = await getUser();
|
||||
return user!;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"use server";
|
||||
|
||||
import { prisma } from "@/src/lib/prisma";
|
||||
import { getUserData, isManager, isEmployee } from "@/src/lib/auth/getUser";
|
||||
import { getUserData, isManager, isEmployee, getEffectiveManagerId } from "@/src/lib/auth/getUser";
|
||||
import { courseSchema, publishedCourseSchema, type CourseFormData } from "../schemas/course-schema";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
|
@ -63,7 +63,9 @@ export async function createCourse(data: CourseFormData, status: "draft" | "publ
|
|||
const validatedData = validation.data;
|
||||
|
||||
// Schritt 5: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
const creatorId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const creatorId = getEffectiveManagerId(userData);
|
||||
if (!creatorId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 6: Kurs in der Datenbank erstellen
|
||||
const course = await prisma.course.create({
|
||||
|
|
@ -173,7 +175,13 @@ export async function getMyCourses(options?: { dateFrom?: Date; dateTo?: Date })
|
|||
}
|
||||
|
||||
// Step 3: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return {
|
||||
success: false,
|
||||
error: "Mitarbeiter-Account ist keinem Manager zugeordnet",
|
||||
courses: [],
|
||||
};
|
||||
|
||||
// Step 4: Build the where clause with optional date filtering
|
||||
const whereClause: Prisma.CourseWhereInput = {
|
||||
|
|
@ -248,7 +256,9 @@ export async function getCourseById(courseId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 4: Kurs aus der Datenbank abrufen
|
||||
const course = await prisma.course.findUnique({
|
||||
|
|
@ -324,7 +334,9 @@ export async function updateCourse(
|
|||
}
|
||||
|
||||
// Schritt 4: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 5: Kurs aus der Datenbank abrufen
|
||||
const existingCourse = await prisma.course.findUnique({
|
||||
|
|
@ -434,7 +446,9 @@ export async function deleteCourse(courseId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 4: Kurs aus der Datenbank abrufen
|
||||
const course = await prisma.course.findUnique({
|
||||
|
|
@ -492,7 +506,13 @@ export async function getMySportTypes() {
|
|||
return { success: false, error: "Unauthorized", sports: [] };
|
||||
}
|
||||
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return {
|
||||
success: false,
|
||||
error: "Mitarbeiter-Account ist keinem Manager zugeordnet",
|
||||
sports: [],
|
||||
};
|
||||
|
||||
const courses = await prisma.course.findMany({
|
||||
where: { createdBy: managerId },
|
||||
|
|
@ -522,7 +542,13 @@ export async function getMyBusinesses() {
|
|||
return { success: false, error: "Unauthorized", businesses: [] };
|
||||
}
|
||||
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return {
|
||||
success: false,
|
||||
error: "Mitarbeiter-Account ist keinem Manager zugeordnet",
|
||||
businesses: [],
|
||||
};
|
||||
|
||||
const businesses = await prisma.business.findMany({
|
||||
where: { managerId },
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"use server";
|
||||
|
||||
import { prisma } from "@/src/lib/prisma";
|
||||
import { getUserData, isManager, isEmployee } from "@/src/lib/auth/getUser";
|
||||
import { getUserData, isManager, isEmployee, getEffectiveManagerId } from "@/src/lib/auth/getUser";
|
||||
import { createAdminClient } from "@/src/lib/supabase/admin";
|
||||
import { employeeSchema, type EmployeeFormData } from "../schemas/employee-schema";
|
||||
import { revalidatePath, revalidateTag } from "next/cache";
|
||||
|
|
@ -129,7 +129,9 @@ export async function createEmployee(data: EmployeeFormData, status: "draft" | "
|
|||
}
|
||||
|
||||
// Schritt 7: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 8: Berechtigungen auf Caller-Ceiling begrenzen (Privilege-Escalation verhindern)
|
||||
const finalPermissions = isEmployee(userData)
|
||||
|
|
@ -216,7 +218,14 @@ export async function getMyTrainers() {
|
|||
};
|
||||
}
|
||||
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return {
|
||||
success: false,
|
||||
error: "Mitarbeiter-Account ist keinem Manager zugeordnet",
|
||||
employees: [],
|
||||
trainers: [],
|
||||
};
|
||||
|
||||
const employees = await prisma.employee.findMany({
|
||||
where: {
|
||||
|
|
@ -282,8 +291,12 @@ export async function getMyEmployees() {
|
|||
// Manager sieht alle Mitarbeiter unter seiner ID
|
||||
whereClause = { createdBy: userData.id };
|
||||
} else {
|
||||
// Employee: eigene Manager-ID ermitteln, dann alle unter diesem Manager anzeigen (außer sich selbst)
|
||||
// Employee: alle unter demselben Manager anzeigen (außer sich selbst)
|
||||
// createdBy kann null sein (verwaister Account) — in dem Fall nichts zurückgeben
|
||||
const managerId = userData.createdBy;
|
||||
if (!managerId) {
|
||||
return { success: true, employees: [] };
|
||||
}
|
||||
whereClause = { createdBy: managerId, NOT: { email: userData.email } };
|
||||
}
|
||||
const employees = await prisma.employee.findMany({
|
||||
|
|
@ -435,7 +448,9 @@ export async function updateEmployee(
|
|||
}
|
||||
|
||||
// Schritt 6: Überprüfen, ob der Benutzer der Besitzer des Mitarbeiters ist
|
||||
const ownerManagerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const ownerManagerId = getEffectiveManagerId(userData);
|
||||
if (!ownerManagerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
if (existingEmployee.createdBy !== ownerManagerId) {
|
||||
return {
|
||||
success: false,
|
||||
|
|
@ -568,7 +583,13 @@ export async function getMyEmployeeRoles() {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return {
|
||||
success: false,
|
||||
error: "Mitarbeiter-Account ist keinem Manager zugeordnet",
|
||||
roles: [],
|
||||
};
|
||||
|
||||
// Schritt 4: Alle Mitarbeiter des Managers abrufen (nur roles Feld)
|
||||
const employees = await prisma.employee.findMany({
|
||||
|
|
@ -653,7 +674,9 @@ export async function deleteEmployee(employeeId: string) {
|
|||
}
|
||||
|
||||
// Schritt 5: Überprüfen, ob der Benutzer der Besitzer des Mitarbeiters ist
|
||||
const ownerManagerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const ownerManagerId = getEffectiveManagerId(userData);
|
||||
if (!ownerManagerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
if (employee.createdBy !== ownerManagerId) {
|
||||
return {
|
||||
success: false,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"use server";
|
||||
|
||||
import { prisma } from "@/src/lib/prisma";
|
||||
import { getUserData, isManager, isEmployee } from "@/src/lib/auth/getUser";
|
||||
import { getUserData, isManager, isEmployee, getEffectiveManagerId } from "@/src/lib/auth/getUser";
|
||||
import { roomSchema, type RoomFormData } from "../schemas/room-schema";
|
||||
import { revalidatePath } from "next/cache";
|
||||
|
||||
|
|
@ -59,7 +59,9 @@ export async function createRoom(data: RoomFormData) {
|
|||
const validatedData = validation.data;
|
||||
|
||||
// Schritt 5: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
const creatorId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const creatorId = getEffectiveManagerId(userData);
|
||||
if (!creatorId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 6: Raum in der Datenbank erstellen
|
||||
const room = await prisma.room.create({
|
||||
|
|
@ -143,7 +145,13 @@ export async function getMyRooms() {
|
|||
}
|
||||
|
||||
// Schritt 3: Manager-ID ermitteln (Employee erbt createdBy vom eigenen Datensatz)
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return {
|
||||
success: false,
|
||||
error: "Mitarbeiter-Account ist keinem Manager zugeordnet",
|
||||
rooms: [],
|
||||
};
|
||||
|
||||
// Schritt 4: Räume abrufen, die von diesem Manager erstellt wurden
|
||||
const rooms = await prisma.room.findMany({
|
||||
|
|
@ -195,7 +203,9 @@ export async function getRoomById(roomId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 4: Raum aus der Datenbank abrufen
|
||||
const room = await prisma.room.findUnique({
|
||||
|
|
@ -267,7 +277,9 @@ export async function updateRoom(roomId: string, data: RoomFormData) {
|
|||
}
|
||||
|
||||
// Schritt 4: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 5: Raum aus der Datenbank abrufen
|
||||
const existingRoom = await prisma.room.findUnique({
|
||||
|
|
@ -356,7 +368,9 @@ export async function deleteRoom(roomId: string) {
|
|||
}
|
||||
|
||||
// Schritt 3: Effektive Manager-ID ermitteln
|
||||
const managerId = isEmployee(userData) ? (userData.createdBy ?? userData.id) : userData.id;
|
||||
const managerId = getEffectiveManagerId(userData);
|
||||
if (!managerId)
|
||||
return { success: false, error: "Mitarbeiter-Account ist keinem Manager zugeordnet" };
|
||||
|
||||
// Schritt 4: Raum aus der Datenbank abrufen
|
||||
const room = await prisma.room.findUnique({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue