Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(orgs): split creation flows + add new kind of roles based organization #1429

Merged
merged 106 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
e56ac5b
test: e2e test to create dao creation flow
MikaelVallenet Oct 10, 2024
6860ec0
wip: e2e test to create dao creation flow
MikaelVallenet Oct 10, 2024
c04bea2
wip: e2e test handle filling all steps in dao creation form
MikaelVallenet Oct 10, 2024
59680d9
wip: e2e test handle filling all steps in dao creation form
MikaelVallenet Oct 11, 2024
d3f01e3
Merge branch 'main' into e2e-test-dao-creation-gno
MikaelVallenet Oct 11, 2024
83d31c8
wip: e2e test handle filling all steps in dao creation form
MikaelVallenet Oct 14, 2024
f5a55e2
wip: e2e test handle filling all steps in dao creation form
MikaelVallenet Oct 14, 2024
a020752
fix: remove unused std from gno dao realm generation
MikaelVallenet Oct 15, 2024
7c60018
feat: add adena mock deploy pkg function
MikaelVallenet Oct 15, 2024
e4f4b20
fix: finish e2e test organization creation flow on gno
MikaelVallenet Oct 15, 2024
21567e5
chore: refactor project structure by moving all e2e test files into g…
MikaelVallenet Oct 15, 2024
9b8a071
style: run eslint
MikaelVallenet Oct 15, 2024
03f1e7c
revert: useless modification on e2e test
MikaelVallenet Oct 15, 2024
cdc95c3
fix: delete useless pkg comment
MikaelVallenet Oct 15, 2024
c0eb78c
fix: run lint on networks files
MikaelVallenet Oct 15, 2024
2ec5b9e
Merge branch 'main' into e2e-test-dao-creation-gno
MikaelVallenet Oct 15, 2024
c3516ce
fix: delete useless console.log
MikaelVallenet Oct 16, 2024
dcd664e
feat: use enum to handle adena type message value
MikaelVallenet Oct 16, 2024
55176c8
fix: delete mint & burn tori token for common dao
MikaelVallenet Oct 22, 2024
ca2b6f1
Merge branch 'main' into e2e-test-dao-creation-gno
n0izn0iz Oct 29, 2024
b0cf985
fix(dao): remove modboard related code
MikaelVallenet Oct 31, 2024
5093189
Merge branch 'e2e-test-dao-creation-gno' of github.com:TERITORI/terit…
MikaelVallenet Oct 31, 2024
c3899dd
Merge branch 'main' into e2e-test-dao-creation-gno
MikaelVallenet Oct 31, 2024
ff5bca0
fix(gnovm): remove leftover of tori import
MikaelVallenet Oct 31, 2024
5caf06f
feat: add a call to members JSON
MikaelVallenet Oct 31, 2024
ed52b3f
feat: add a call to members JSON
MikaelVallenet Oct 31, 2024
0fa0a0a
fix: remove tori admin handler
MikaelVallenet Oct 31, 2024
4e08f27
chore: run eslint
MikaelVallenet Oct 31, 2024
fce1b40
fix: add a TODO to fix later the groupId
MikaelVallenet Oct 31, 2024
ca673e0
fix: remove groupId
MikaelVallenet Oct 31, 2024
8be6a98
fix: keep only e2e related code
MikaelVallenet Nov 1, 2024
010420e
fix: keep only e2e related code
MikaelVallenet Nov 1, 2024
d9cd564
Merge branch 'main' into e2e-test-dao-creation-gno
MikaelVallenet Nov 1, 2024
c6801b3
fix(gno-daos): create proposal for post with DAO
MikaelVallenet Nov 4, 2024
3d27a0c
feat(dao): fix org on gno to post on social feed
MikaelVallenet Nov 5, 2024
49bce88
feat(dao): fix org on gno to post on social feed
MikaelVallenet Nov 5, 2024
e15b6b6
feat(dao): fix not enough funds by using user wallet instead of contr…
MikaelVallenet Nov 5, 2024
2885aa9
misc(dao): remove console log statements
MikaelVallenet Nov 5, 2024
ce5aac9
fix(dao): vote value
MikaelVallenet Nov 5, 2024
7f0de1c
chore: lint
MikaelVallenet Nov 5, 2024
4954bb8
chore: gno lint
MikaelVallenet Nov 5, 2024
95633d4
chore: gno lint
MikaelVallenet Nov 5, 2024
7eedca8
chore: gno lint
MikaelVallenet Nov 5, 2024
9b2d5ba
fix: replace function by usage of lodash lib
MikaelVallenet Nov 5, 2024
03d2edb
fix: check dao have enough money
MikaelVallenet Nov 6, 2024
ec11c14
fix: look for balance of DAO not of user
MikaelVallenet Nov 6, 2024
2088df2
fix: remove double wait on tx causing infinite waiting time
MikaelVallenet Nov 7, 2024
53793c3
fix: parse user & network
MikaelVallenet Nov 7, 2024
117295a
fix: simplify ternary operation
MikaelVallenet Nov 7, 2024
e6547dd
Merge branch 'main' into dev/mikaelvallenet/fix/organization-posting-…
MikaelVallenet Nov 7, 2024
fec6e90
Merge branch 'main' into dev/mikaelvallenet/feat/register-dao-to-prof…
MikaelVallenet Nov 7, 2024
d368965
feat(gno/dao): regiser dao conf to profile realm
MikaelVallenet Nov 7, 2024
30f69f6
chore: rename poster to author
MikaelVallenet Nov 8, 2024
3dee11a
Merge branch 'main' into dev/mikaelvallenet/fix/organization-posting-…
MikaelVallenet Nov 8, 2024
656b087
Merge branch 'dev/mikaelvallenet/fix/organization-posting-post' into …
MikaelVallenet Nov 8, 2024
cb0c544
fix(gno/dao): display dao members
MikaelVallenet Nov 11, 2024
513d6c3
fix(gno/dao): merge main
MikaelVallenet Nov 11, 2024
ee26a23
Merge branch 'dev/mikaelvallenet/feat/register-dao-to-profile-realm' …
MikaelVallenet Nov 11, 2024
2efbcf5
fix(gno/dao): delete fakeRoles
MikaelVallenet Nov 11, 2024
52e1f49
fix(gno/dao): run linter
MikaelVallenet Nov 11, 2024
ad36970
feat(gno/dao): add dao_roles_group
MikaelVallenet Nov 11, 2024
0055bda
feat(gno/dao): add dao_roles_group
MikaelVallenet Nov 11, 2024
6a15018
feat(gno/dao): implement role manager into daos realms
MikaelVallenet Nov 12, 2024
9852985
tests(gno/dao): add roles module in test dao core
MikaelVallenet Nov 12, 2024
7686f09
tests(gno/dao): add roles modules info
MikaelVallenet Nov 12, 2024
9cc37d6
feat(gno/dao): add dao_roles_group into network objects
MikaelVallenet Nov 12, 2024
e92bc8f
chore(gno/dao): generate networks.json
MikaelVallenet Nov 12, 2024
629a6d1
feat(gno/dao): add dao roles group into generated dao code
MikaelVallenet Nov 12, 2024
ec2e57f
feat(gno/dao): add dao_roles_group into network objects
MikaelVallenet Nov 12, 2024
3efeae5
feat(gno/dao): add example of role creation & assignment in dao_core
MikaelVallenet Nov 12, 2024
901146d
feat(gno/dao): add form section to add new role into dao
MikaelVallenet Nov 12, 2024
8d21e7d
feat(gno/dao): add review collapsable row for roles settings definition
MikaelVallenet Nov 13, 2024
3904387
fix(gno/dao): handle unregister field value when delete role or member
MikaelVallenet Nov 13, 2024
ccbf26c
fix(gno/dao): add field to assign roles to users
MikaelVallenet Nov 14, 2024
e928bbb
fix(gno/dao): add role & assignment to deployment contract
MikaelVallenet Nov 14, 2024
d8c1b8c
feat(gno/dao): retrive roles from members of the DAO
MikaelVallenet Nov 15, 2024
206021a
feat(gno/dao): display roles of DAO members
MikaelVallenet Nov 15, 2024
d957c11
chore: merge w/ main
MikaelVallenet Nov 29, 2024
4131ab2
fix: e2e test
MikaelVallenet Nov 29, 2024
b755fef
feat: merge main
MikaelVallenet Dec 2, 2024
438d0fb
tests: fix gno dao tests
MikaelVallenet Dec 2, 2024
4c81982
chore: run linter on e2e tests
MikaelVallenet Dec 2, 2024
841ef7e
feat: refactor organizations and slit each flow
MikaelVallenet Dec 3, 2024
c5317f1
Update packages/screens/Organizations/components/CreateDAOSection.tsx
MikaelVallenet Dec 3, 2024
a77163b
fix: add flex property create dao animation
MikaelVallenet Dec 3, 2024
5fddbc0
Merge branch 'dev/mikaelvallenet/feat/push-role-manager-into-dao' of …
MikaelVallenet Dec 3, 2024
ca3b5c1
fix: refactor gno e2e tests
MikaelVallenet Dec 3, 2024
607cebe
fix: remove roles e2e test since it's not production ready
MikaelVallenet Dec 3, 2024
b549bbc
chore: run lint
MikaelVallenet Dec 3, 2024
0ccbc60
fix: reset unlocked steps on structure change
MikaelVallenet Dec 3, 2024
c0e7c6a
test: fix e2e tests
MikaelVallenet Dec 3, 2024
4284bef
test: fix e2e tests
MikaelVallenet Dec 3, 2024
ce2571f
chore: regenerate networks.json
MikaelVallenet Dec 3, 2024
21012de
fix(org): remove unused ReviewInformationSection component
MikaelVallenet Dec 3, 2024
7695414
fix(org): remove duplicate register to realm profile
MikaelVallenet Dec 3, 2024
637d03a
style: remove stylesheet.create from evertwhere in the orgs screens &…
MikaelVallenet Dec 3, 2024
7eeb6ba
fix(org): fix split bug & add split member in two kind for roles & me…
MikaelVallenet Dec 3, 2024
4acc804
fix(org): fix deploy roles based dao without any roles
MikaelVallenet Dec 3, 2024
3d5061b
fix(org/upp): remove roles text if user card does not have any roles
MikaelVallenet Dec 3, 2024
b3de18d
Merge branch 'main' into dev/mikaelvallenet/feat/push-role-manager-in…
n0izn0iz Dec 3, 2024
5480428
feat: add token based dao
MikaelVallenet Dec 4, 2024
0add3e8
fix: import
MikaelVallenet Dec 4, 2024
9ea0010
chore: lint
MikaelVallenet Dec 4, 2024
928814e
chore: lint
MikaelVallenet Dec 4, 2024
1f77d9a
Merge branch 'main' into dev/mikaelvallenet/feat/push-role-manager-in…
MikaelVallenet Dec 4, 2024
9f9df32
fix: e2e test
MikaelVallenet Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { connectWallet, resetChain } from "./lib";
import { connectWallet, resetChain } from "../lib";

describe("Create an organization flow", () => {
it("works", () => {
Expand Down Expand Up @@ -26,7 +26,7 @@ describe("Create an organization flow", () => {
cy.get('[data-testid="organization-description"]').type(description);

cy.contains("Next: Configure voting").click();
cy.contains("Next: Set tokens or members").click();
cy.contains("Next: Set members").click();
cy.get('[data-testid="member-settings-next"]').click();
cy.contains("Confirm & Launch the Organization").click();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
changeSelectedMilestoneStatus,
changeTestUser,
connectWallet,
} from "./lib";
} from "../lib";

describe("Contractor proposer full flow", () => {
it("works", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
changeSelectedMilestoneStatus,
changeTestUser,
connectWallet,
} from "./lib";
} from "../lib";

describe("Funder proposer full flow", () => {
it("works", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { changeTestUser, connectWallet, resetChain } from "./lib";
import { changeTestUser, connectWallet, resetChain } from "../lib";

const showUppForm = () => {
cy.contains("Edit profile").click();
Expand Down
44 changes: 44 additions & 0 deletions gno/p/dao_core/dao_core.gno
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"strconv"
"strings"

"gno.land/p/demo/json"
dao_interfaces "gno.land/p/teritori/dao_interfaces"
"gno.land/p/teritori/jsonutil"
)

// TODO: add wrapper message handler to handle multiple proposal modules messages
Expand All @@ -14,6 +16,7 @@ type daoCore struct {
dao_interfaces.IDAOCore

votingModule dao_interfaces.IVotingModule
rolesModule dao_interfaces.IRolesModule
proposalModules []dao_interfaces.ActivableProposalModule
activeProposalModuleCount int
realm std.Realm
Expand All @@ -22,13 +25,18 @@ type daoCore struct {

func NewDAOCore(
votingModuleFactory dao_interfaces.VotingModuleFactory,
rolesModuleFactory dao_interfaces.RolesModuleFactory,
proposalModulesFactories []dao_interfaces.ProposalModuleFactory,
messageHandlersFactories []dao_interfaces.MessageHandlerFactory,
) dao_interfaces.IDAOCore {
if votingModuleFactory == nil {
panic("Missing voting module factory")
}

if rolesModuleFactory == nil {
panic("Missing roles module factory")
}

if len(proposalModulesFactories) == 0 {
panic("No proposal modules factories")
}
Expand All @@ -45,6 +53,11 @@ func NewDAOCore(
panic("voting module factory returned nil")
}

core.rolesModule = rolesModuleFactory(core)
if core.rolesModule == nil {
panic("roles module factory returned nil")
}

for i, modFactory := range proposalModulesFactories {
mod := modFactory(core)
if mod == nil {
Expand Down Expand Up @@ -117,6 +130,32 @@ func (d *daoCore) VotingModule() dao_interfaces.IVotingModule {
return d.votingModule
}

func (d *daoCore) RolesModule() dao_interfaces.IRolesModule {
return d.rolesModule
}

func (d *daoCore) GetMembersJSON(start, end string, limit uint64, height int64) string {
vMembers := d.votingModule.GetMembersJSON(start, end, limit, height)
nodes, err := json.Unmarshal([]byte(vMembers))
if err != nil {
panic("failed to unmarshal voting module members")
}
vals := nodes.MustArray()
for i, val := range vals {
obj := val.MustObject()
addr := jsonutil.MustAddress(obj["address"])
roles := d.rolesModule.GetMemberRoles(addr)
rolesJSON := make([]*json.Node, len(roles))
for j, role := range roles {
rolesJSON[j] = json.StringNode("", role)
}
obj["roles"] = json.ArrayNode("", rolesJSON)
vals[i] = json.ObjectNode("", obj)

}
return json.ArrayNode("", vals).String()
}

func (d *daoCore) VotingPowerAtHeight(address std.Address, height int64) uint64 {
return d.VotingModule().VotingPowerAtHeight(address, height)
}
Expand All @@ -133,6 +172,11 @@ func (d *daoCore) Render(path string) string {
sb.WriteString(votingInfo.String())
sb.WriteRune('\n')
sb.WriteString(d.votingModule.Render(""))
rolesInfo := d.rolesModule.Info()
sb.WriteString("# Roles Module: ")
sb.WriteString(rolesInfo.String())
sb.WriteRune('\n')
sb.WriteString(d.rolesModule.Render(""))
sb.WriteString("## Supported Messages:\n")
sb.WriteString(d.registry.Render())

Expand Down
58 changes: 57 additions & 1 deletion gno/p/dao_core/dao_core_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,53 @@ func (vm *votingModule) TotalPowerAtHeight(height int64) uint64 {
return 0
}

type rolesModule struct {
core dao_interfaces.IDAOCore
}

func rolesModuleFactory(core dao_interfaces.IDAOCore) dao_interfaces.IRolesModule {
return &rolesModule{core: core}
}

func (rm *rolesModule) Info() dao_interfaces.ModuleInfo {
return dao_interfaces.ModuleInfo{
Kind: "TestRoles",
Version: "42.21",
}
}

func (rm *rolesModule) ConfigJSON() string {
return "{}"
}

func (rm *rolesModule) Render(path string) string {
return "# Test Roles Module"
}

func (rm *rolesModule) HasRole(address std.Address, role string) bool {
return false
}

func (rm *rolesModule) NewRole(roleName string) {
panic("not implemented")
}

func (rm *rolesModule) DeleteRole(roleName string) {
panic("not implemented")
}

func (rm *rolesModule) GrantRole(address std.Address, role string) {
panic("not implemented")
}

func (rm *rolesModule) RevokeRole(address std.Address, role string) {
panic("not implemented")
}

func (rm *rolesModule) GetMemberRoles(address std.Address) []string {
return []string{}
}

type proposalModule struct {
core dao_interfaces.IDAOCore
}
Expand Down Expand Up @@ -100,7 +147,7 @@ func TestDAOCore(t *testing.T) {
return handler
}

core := NewDAOCore(votingModuleFactory, []dao_interfaces.ProposalModuleFactory{proposalModuleFactory}, []dao_interfaces.MessageHandlerFactory{handlerFactory})
core := NewDAOCore(votingModuleFactory, rolesModuleFactory, []dao_interfaces.ProposalModuleFactory{proposalModuleFactory}, []dao_interfaces.MessageHandlerFactory{handlerFactory})
if core == nil {
t.Fatal("core is nil")
}
Expand All @@ -118,6 +165,15 @@ func TestDAOCore(t *testing.T) {
t.Fatal("voting module has wrong kind")
}

rolesMod := core.RolesModule()
if rolesMod == nil {
t.Fatal("roles module is nil")
}

if rolesMod.Info().Kind != "TestRoles" {
t.Fatal("roles module has wrong kind")
}

propMods := core.ProposalModules()
if len(propMods) != 1 {
t.Fatal("expected 1 proposal module")
Expand Down
1 change: 1 addition & 0 deletions gno/p/dao_core/gno.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ module gno.land/p/teritori/dao_core
require (
gno.land/p/demo/json v0.0.0-latest
gno.land/p/teritori/dao_interfaces v0.0.0-latest
gno.land/p/teritori/jsonutil v0.0.0-latest
)
3 changes: 3 additions & 0 deletions gno/p/dao_interfaces/core.gno
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ type IDAOCore interface {
Render(path string) string

VotingModule() IVotingModule
RolesModule() IRolesModule
ProposalModules() []ActivableProposalModule
ActiveProposalModuleCount() int
Registry() *MessagesRegistry

UpdateVotingModule(newVotingModule IVotingModule)
UpdateProposalModules(toAdd []IProposalModule, toDisable []int)

GetMembersJSON(start, end string, limit uint64, height int64) string
}
8 changes: 8 additions & 0 deletions gno/p/dao_interfaces/core_testing.gno
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ func (d *dummyCore) VotingModule() IVotingModule {
panic("not implemented")
}

func (d *dummyCore) RolesModule() IRolesModule {
panic("not implemented")
}

func (d *dummyCore) ProposalModules() []ActivableProposalModule {
panic("not implemented")
}
Expand All @@ -33,3 +37,7 @@ func (d *dummyCore) UpdateVotingModule(newVotingModule IVotingModule) {
func (d *dummyCore) UpdateProposalModules(toAdd []IProposalModule, toDisable []int) {
panic("not implemented")
}

func (d *dummyCore) GetMembersJSON(start, end string, limit uint64, height int64) string {
panic("not implemented")
}
14 changes: 14 additions & 0 deletions gno/p/dao_interfaces/modules.gno
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,17 @@ type IProposalModule interface {
}

type ProposalModuleFactory func(core IDAOCore) IProposalModule

type IRolesModule interface {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO, it could be nice and more practice if we handle AddressOrName instead of only Address

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, if we do we have to add a way to resolve users by passing a resolver in the role module, increasing gas cost, dependencies and complexity
then if at some point usernames can change, we get a lot of headache
IMO it's better to always operate on addresses where possible

Info() ModuleInfo
ConfigJSON() string
Render(path string) string
GetMemberRoles(address std.Address) []string
HasRole(address std.Address, role string) bool
NewRole(roleName string)
DeleteRole(roleName string)
GrantRole(address std.Address, role string)
RevokeRole(address std.Address, role string)
}

type RolesModuleFactory func(core IDAOCore) IRolesModule
8 changes: 8 additions & 0 deletions gno/p/dao_roles_group/gno.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module gno.land/p/teritori/dao_roles_group

require (
gno.land/p/demo/json v0.0.0-latest
gno.land/p/teritori/dao_interfaces v0.0.0-latest
gno.land/p/teritori/jsonutil v0.0.0-latest
gno.land/p/teritori/role_manager v0.0.0-latest
)
63 changes: 63 additions & 0 deletions gno/p/dao_roles_group/roles_group.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package dao_roles_group

import (
"std"

"gno.land/p/demo/json"
dao_interfaces "gno.land/p/teritori/dao_interfaces"
"gno.land/p/teritori/jsonutil"
"gno.land/p/teritori/role_manager"
)

type RolesGroup struct {
dao_interfaces.IRolesModule

rm *role_manager.RoleManager
}

func NewRolesGroup() *RolesGroup {
return &RolesGroup{
rm: role_manager.NewWithAddress(std.PrevRealm().Addr()),
}
}

func (r *RolesGroup) Info() dao_interfaces.ModuleInfo {
return dao_interfaces.ModuleInfo{
Kind: "gno/p/teritori/dao_roles_group",
Version: "0.1.0",
}
}

func (r *RolesGroup) ConfigJSON() string {
return json.ObjectNode("", map[string]*json.Node{
"totalRoles": jsonutil.IntNode(r.rm.CountRoles()),
}).String()
}

func (r *RolesGroup) Render(path string) string {
return "Not implemented yet"
}

func (r *RolesGroup) HasRole(address std.Address, role string) bool {
return r.rm.HasRole(address, role)
}

func (r *RolesGroup) NewRole(roleName string) {
r.rm.CreateNewRole(roleName, []string{})
}

func (r *RolesGroup) DeleteRole(roleName string) {
r.rm.DeleteRole(roleName)
}

func (r *RolesGroup) GrantRole(address std.Address, role string) {
r.rm.AddRoleToUser(address, role)
}

func (r *RolesGroup) RevokeRole(address std.Address, role string) {
r.rm.RemoveRoleFromUser(address, role)
}

func (r *RolesGroup) GetMemberRoles(address std.Address) []string {
return r.rm.GetUserRoles(address)
}
24 changes: 24 additions & 0 deletions gno/p/role_manager/role_manager.gno
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,30 @@ func (rm *RoleManager) HasRole(user std.Address, roleName string) bool {
return userRoles.Has(roleName)
}

func (rm *RoleManager) IsRoleExist(roleName string) bool {
return rm.roles.Has(roleName)
}

func (rm *RoleManager) CountRoles() int {
return rm.roles.Size()
}

func (rm *RoleManager) GetUserRoles(user std.Address) []string {
userRoles, ok := rm.users.Get(user.String())
if !ok {
return []string{}
}
i := 0
roles := userRoles.(*avl.Tree)
res := make([]string, roles.Size())
roles.Iterate("", "", func(key string, value interface{}) bool {
res[i] = key
i++
return false
})
return res
}

func (rm *RoleManager) mustGetRole(roleName string) *Role {
role, ok := rm.roles.Get(roleName)
if !ok {
Expand Down
Loading
Loading