package session import ( "net/http" "github.com/gin-gonic/gin" ) // Employee permissions var EmployeePermissions = []string{ "grades:read", "grades:write", "attendance:read", "attendance:write", "students:read", "students:write", "reports:generate", "consent:admin", "corrections:read", "corrections:write", "classes:read", "classes:write", "timetable:read", "timetable:write", "substitutions:read", "substitutions:write", "parent_communication:read", "parent_communication:write", } // Customer permissions var CustomerPermissions = []string{ "own_data:read", "own_grades:read", "own_attendance:read", "consent:manage", "meetings:join", "messages:read", "messages:write", "children:read", "children:grades:read", "children:attendance:read", } // Admin permissions var AdminPermissions = []string{ "users:read", "users:write", "users:manage", "rbac:read", "rbac:write", "audit:read", "settings:read", "settings:write", "dsr:read", "dsr:process", } // Employee roles var EmployeeRoles = map[string]bool{ "admin": true, "schul_admin": true, "schulleitung": true, "pruefungsvorsitz": true, "klassenlehrer": true, "fachlehrer": true, "sekretariat": true, "erstkorrektor": true, "zweitkorrektor": true, "drittkorrektor": true, "teacher_assistant": true, "teacher": true, "lehrer": true, "data_protection_officer": true, } // Customer roles var CustomerRoles = map[string]bool{ "parent": true, "student": true, "user": true, "guardian": true, } // RequireEmployee requires the user to be an employee func RequireEmployee() gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if !session.IsEmployee() { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "Employee access required", }) return } c.Next() } } // RequireCustomer requires the user to be a customer func RequireCustomer() gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if !session.IsCustomer() { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "Customer access required", }) return } c.Next() } } // RequireUserType requires a specific user type func RequireUserType(userType UserType) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if session.UserType != userType { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "User type '" + string(userType) + "' required", }) return } c.Next() } } // RequirePermission requires a specific permission func RequirePermission(permission string) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if !session.HasPermission(permission) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "Permission '" + permission + "' required", }) return } c.Next() } } // RequireAnyPermission requires at least one of the permissions func RequireAnyPermission(permissions ...string) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if !session.HasAnyPermission(permissions) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "One of the required permissions is missing", }) return } c.Next() } } // RequireAllPermissions requires all specified permissions func RequireAllPermissions(permissions ...string) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if !session.HasAllPermissions(permissions) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "Missing required permissions", }) return } c.Next() } } // RequireRole requires a specific role func RequireRole(role string) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } if !session.HasRole(role) { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "Role '" + role + "' required", }) return } c.Next() } } // RequireAnyRole requires at least one of the roles func RequireAnyRole(roles ...string) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } for _, role := range roles { if session.HasRole(role) { c.Next() return } } c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "One of the required roles is missing", }) } } // RequireSameTenant ensures user can only access their tenant's data func RequireSameTenant(tenantIDParam string) gin.HandlerFunc { return func(c *gin.Context) { session := GetSession(c) if session == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "error": "unauthorized", "message": "Authentication required", }) return } requestTenantID := c.Param(tenantIDParam) if requestTenantID == "" { requestTenantID = c.Query(tenantIDParam) } if requestTenantID != "" && session.TenantID != nil && *session.TenantID != requestTenantID { // Check if user is super admin if !session.HasRole("super_admin") { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ "error": "forbidden", "message": "Access denied to this tenant", }) return } } c.Next() } } // DetermineUserType determines user type based on roles func DetermineUserType(roles []string) UserType { for _, role := range roles { if EmployeeRoles[role] { return UserTypeEmployee } } for _, role := range roles { if CustomerRoles[role] { return UserTypeCustomer } } return UserTypeCustomer } // GetPermissionsForRoles returns permissions based on roles and user type func GetPermissionsForRoles(roles []string, userType UserType) []string { permSet := make(map[string]bool) // Base permissions by user type if userType == UserTypeEmployee { for _, p := range EmployeePermissions { permSet[p] = true } } else { for _, p := range CustomerPermissions { permSet[p] = true } } // Admin permissions adminRoles := map[string]bool{ "admin": true, "schul_admin": true, "super_admin": true, "data_protection_officer": true, } for _, role := range roles { if adminRoles[role] { for _, p := range AdminPermissions { permSet[p] = true } break } } // Convert to slice permissions := make([]string, 0, len(permSet)) for p := range permSet { permissions = append(permissions, p) } return permissions } // CheckResourceOwnership checks if user owns a resource or is admin func CheckResourceOwnership(session *Session, resourceUserID string, allowAdmin bool) bool { if session == nil { return false } // User owns the resource if session.UserID == resourceUserID { return true } // Admin can access all if allowAdmin && (session.HasRole("admin") || session.HasRole("super_admin")) { return true } return false } // IsSessionEmployee checks if current session belongs to an employee func IsSessionEmployee(c *gin.Context) bool { session := GetSession(c) if session == nil { return false } return session.IsEmployee() } // IsSessionCustomer checks if current session belongs to a customer func IsSessionCustomer(c *gin.Context) bool { session := GetSession(c) if session == nil { return false } return session.IsCustomer() } // HasSessionPermission checks if session has a permission func HasSessionPermission(c *gin.Context, permission string) bool { session := GetSession(c) if session == nil { return false } return session.HasPermission(permission) } // HasSessionRole checks if session has a role func HasSessionRole(c *gin.Context, role string) bool { session := GetSession(c) if session == nil { return false } return session.HasRole(role) }