package auth import "github.com/google/uuid" // Матрица прав из docs/auth-and-roles.md. Проверяется в сервисном слое, а не только в middleware. // Permission — право, не зависящее от целевого пользователя. type Permission int // Глобальные права. const ( PermAdminPanel Permission = iota // открыть админку PermListUsers // видеть список пользователей PermManageLibrary // хранилища, сканирование, переиндексация PermViewLibraryStatus // статус библиотеки (просмотр) PermSuggestTracks // предлагать треки, видеть свои предложения PermReviewUploads // очередь, одобрение, правка метаданных, лимиты PermSystemStatus // статус рекомендательной системы, аудит ) var permissions = map[Permission][]Role{ PermAdminPanel: {RoleModerator, RoleAdmin}, PermListUsers: {RoleModerator, RoleAdmin}, PermManageLibrary: {RoleAdmin}, PermViewLibraryStatus: {RoleModerator, RoleAdmin}, PermSuggestTracks: {RoleModerator, RoleAdmin}, PermReviewUploads: {RoleAdmin}, PermSystemStatus: {RoleAdmin}, } // Can сообщает, есть ли у роли глобальное право. func Can(r Role, p Permission) bool { for _, allowed := range permissions[p] { if allowed == r { return true } } return false } // UserAction — действие над учётной записью другого пользователя. type UserAction int // Действия над пользователями. const ( UserCreate UserAction = iota // создать пользователя с ролью target UserEdit // изменить отображаемое имя UserResetPassword // сбросить пароль UserBlock // заблокировать / разблокировать UserChangeRole // сменить роль (target — текущая роль) UserDelete // удалить UserResetRecommendations // сбросить профиль рекомендаций ) // Actor — кто действует (или над кем). ID нужен, чтобы запретить действия над собой. type Actor struct { ID uuid.UUID Role Role } // CanManageUser — может ли actor выполнить action над target. // Модератор управляет только обычными пользователями; роли и удаление — только админ. // Блокировать, удалять себя и менять себе роль нельзя никому: так не потерять доступ случайно. // Правило «последний админ» зависит от данных и проверяется в сервисе. func CanManageUser(actor, target Actor, action UserAction) bool { self := actor.ID != uuid.Nil && actor.ID == target.ID if self && (action == UserBlock || action == UserDelete || action == UserChangeRole) { return false } switch actor.Role { case RoleAdmin: return true case RoleModerator: switch action { case UserCreate, UserEdit, UserResetPassword, UserBlock, UserResetRecommendations: return target.Role == RoleUser default: return false } default: return false } } // CanAssignRole — может ли actor выдать роль newRole (при создании или смене роли). func CanAssignRole(actor Role, newRole Role) bool { switch actor { case RoleAdmin: return newRole.Valid() case RoleModerator: return newRole == RoleUser default: return false } }