Как сохранить инстанс goRBACH
goRBAC предоставляет довольно облегченную реализацию управления доступом (RBAC) по ролям в Голанге. Вся информация о привилегиях (роли, родители и разрешения), как правило, сохраняется в постоянном хранилище, к примеру в базе данных, файлах или облачном хранилище. В этом посте мы с вами кратко обсудим, как загрузить экземпляр goRBAC из постоянного хранилища и как сохранить экземпляр обратно. Чтобы нам было проще, в качестве постоянного хранилища будем использовать файл JSON.
Подготавливаемся / Определяем роли
Представим, что у нас есть 3 роли: Editor, Photographer and Chief Editor.. Каждая роль имеет следующих родителей и разрешения:
Role |
Parents |
Permissions |
editor |
NULL |
add-text, edit-text, insert-photo |
photographer |
NULL |
add-photo, edit-photo |
chief-editor |
editor, photographer |
del-text, del-photo |
Преобразуем таблицы в два формата JSON. Первый сохраняет данные о ролях (`role.json`), а второй информацию о наследовании (` attribute.json`):
{"editor":["add-text","edit-text","insert-photo"],"photographer":["add-photo","edit-photo"],"chief-editor":["del-text","del-photo"]}
{"chief-editor":["editor","photographer"]}
Мне кажется, здесь все достаточно очевидно и ясно, поэтому я сейчас не стану тратить время на объяснения. Однако, если у вас есть какие-либо вопросы об этой конвертации, прощу вас под кат в комментарии.
Загрузка из файла JSON
Загрузка информации и создание экземпляра goRBAC довольно просто сделать.
Прежде всего, откройте файл JSON и загрузите все данные в map экземпляр.
// map[RoleId]PermissionIds var jsonRoles map[string][]string // map[RoleId]ParentIds var jsonInher map[string][]string // Load roles information if err := LoadJson("roles.json", &jsonRoles); err != nil { log.Fatal(err) } // Load inheritance information if err := LoadJson("inher.json", &jsonInher); err != nil { log.Fatal(err) }
А теперь мы можем начать создавать экземпляр goRBAC. Чтобы это сделать, потребуется проделать всего 3 шага.
Прежде всего, инициализируйте экземпляр:
rbac := gorbac.New() permissions := make(gorbac.Permissions)
И затем мы можем сделать роли `Role (s)` и добавить их в экземпляр goRBAC.
// Build roles and add them to goRBAC instance for rid, pids := range jsonRoles { role := gorbac.NewStdRole(rid) for _, pid := range pids { _, ok := permissions[pid] if !ok { permissions[pid] = gorbac.NewStdPermission(pid) } role.Assign(permissions[pid]) } rbac.Add(role) }
После этого мы можем назначить отношения наследования между ролями.
// Assign the inheritance relationship for rid, parents := range jsonInher { if err := rbac.SetParents(rid, parents); err != nil { log.Fatal(err) } }
Общие use-кейсы
После загрузки всей информации и экземпляром goRBAC под рукой , мы можем начать проверять привилегии.
Вы можете узнать, как это делать здесь.
Сохранение обратно в файл JSON
Если мы добавим несколько новых ролей и разрешений или изменим отношения между ролями, то запись изменений обратно в постоянное хранилище будет довольно существенной.
Самый простой способ - использовать вспомогательную функцию `Walk`
// Persist the change // map[RoleId]PermissionIds jsonOutputRoles := make(map[string][]string) // map[RoleId]ParentIds jsonOutputInher := make(map[string][]string) SaveJsonHandler := func(r gorbac.Role, parents []string) error { // WARNING: Don't use gorbac.RBAC instance in the handler, // otherwise it causes deadlock. permissions := make([]string, 0) for _, p := range r.(*gorbac.StdRole).Permissions() { permissions = append(permissions, p.ID()) } jsonOutputRoles[r.ID()] = permissions jsonOutputInher[r.ID()] = parents return nil } if err := gorbac.Walk(rbac, SaveJsonHandler); err != nil { log.Fatalln(err) } // Save roles information if err := SaveJson("new-roles.json", &jsonOutputRoles); err != nil { log.Fatal(err) } // Save inheritance information if err := SaveJson("new-inher.json", &jsonOutputInher); err != nil { log.Fatal(err) }
Стоит упомянуть кое-что: хоть это closure, НЕ используйте экземпляр goRBAC в обработчике(handler). Это загонит вас в тупик. Ведь основная концепция `WalkHandler` в получении информации из экземпляра goRBAC, который является readonly процессом для него. У вас нет доступа к экземпляру goRBAC без каких либо изменений.
Заключение
goRBAC следует основной идее Go - «меньше», значит экспоненциально «больше» (прим. переводчика — less is exponentially more) и вдохновлен «Чистой архитектурой». Поэтому такие сложные функции, как интерфейс СУБД, интерфейс NoSQL или аутентификация, не появляются в ядре. Хотя `Helper` является важной частью, облегчающей использование goRBAC.