Skip to content

Commit 65e5e2a

Browse files
Copilothsluoyz
andcommitted
Add Provider interface to rbac package
Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com>
1 parent bf4f0f9 commit 65e5e2a

2 files changed

Lines changed: 259 additions & 0 deletions

File tree

rbac/provider.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2026 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package rbac
16+
17+
// Provider is the interface for Casbin providers.
18+
// It provides identity info for Casbin, including users, roles, user-role-mappings,
19+
// permissions, and role-permission-mappings.
20+
// It extends the RoleManager interface because RoleManager only handles user-role-mappings,
21+
// but Provider handles all identity and permission information.
22+
// A Provider can be viewed as a way to import other auth permissions into Casbin.
23+
// Provider implementations can be cloud providers (like AWS, Azure, GCP),
24+
// identity vendors (like Okta, Auth0), or auth languages (like XACML).
25+
type Provider interface {
26+
RoleManager
27+
28+
// GetAllUsers gets all users.
29+
GetAllUsers() ([]string, error)
30+
// AddUser adds a user.
31+
AddUser(user string) error
32+
// DeleteUser deletes a user.
33+
DeleteUser(user string) error
34+
35+
// GetAllRoles gets all roles.
36+
GetAllRoles() ([]string, error)
37+
// AddRole adds a role.
38+
AddRole(role string) error
39+
// DeleteRole deletes a role.
40+
DeleteRole(role string) error
41+
42+
// GetPermissions gets the permissions for a subject (user or role).
43+
// Returns a list of permissions, where each permission is represented as a string slice
44+
// (e.g., [][]string{{"alice", "data1", "read"}, {"alice", "data2", "write"}}).
45+
GetPermissions(subject string) ([][]string, error)
46+
// AddPermission adds a permission for a subject (user or role).
47+
// The permission is represented as a string slice (e.g., []string{"alice", "data1", "read"}).
48+
AddPermission(subject string, permission []string) error
49+
// DeletePermission deletes a permission for a subject (user or role).
50+
DeletePermission(subject string, permission []string) error
51+
52+
// GetRolePermissions gets the permissions for a role.
53+
// Returns a list of permissions, where each permission is represented as a string slice.
54+
GetRolePermissions(role string) ([][]string, error)
55+
// AddRolePermission adds a permission for a role.
56+
AddRolePermission(role string, permission []string) error
57+
// DeleteRolePermission deletes a permission for a role.
58+
DeleteRolePermission(role string, permission []string) error
59+
}

rbac/provider_test.go

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
// Copyright 2026 The casbin Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package rbac
16+
17+
import (
18+
"testing"
19+
)
20+
21+
// mockProvider is a mock implementation of Provider for testing purposes.
22+
type mockProvider struct {
23+
RoleManager
24+
users []string
25+
roles []string
26+
permissions map[string][][]string
27+
rolePermissions map[string][][]string
28+
}
29+
30+
func newMockProvider() *mockProvider {
31+
return &mockProvider{
32+
users: []string{},
33+
roles: []string{},
34+
permissions: make(map[string][][]string),
35+
rolePermissions: make(map[string][][]string),
36+
}
37+
}
38+
39+
func (m *mockProvider) GetAllUsers() ([]string, error) {
40+
return m.users, nil
41+
}
42+
43+
func (m *mockProvider) AddUser(user string) error {
44+
m.users = append(m.users, user)
45+
return nil
46+
}
47+
48+
func (m *mockProvider) DeleteUser(user string) error {
49+
for i, u := range m.users {
50+
if u == user {
51+
m.users = append(m.users[:i], m.users[i+1:]...)
52+
break
53+
}
54+
}
55+
return nil
56+
}
57+
58+
func (m *mockProvider) GetAllRoles() ([]string, error) {
59+
return m.roles, nil
60+
}
61+
62+
func (m *mockProvider) AddRole(role string) error {
63+
m.roles = append(m.roles, role)
64+
return nil
65+
}
66+
67+
func (m *mockProvider) DeleteRole(role string) error {
68+
for i, r := range m.roles {
69+
if r == role {
70+
m.roles = append(m.roles[:i], m.roles[i+1:]...)
71+
break
72+
}
73+
}
74+
return nil
75+
}
76+
77+
func (m *mockProvider) GetPermissions(subject string) ([][]string, error) {
78+
return m.permissions[subject], nil
79+
}
80+
81+
func (m *mockProvider) AddPermission(subject string, permission []string) error {
82+
m.permissions[subject] = append(m.permissions[subject], permission)
83+
return nil
84+
}
85+
86+
func (m *mockProvider) DeletePermission(subject string, permission []string) error {
87+
// Simple implementation for testing
88+
return nil
89+
}
90+
91+
func (m *mockProvider) GetRolePermissions(role string) ([][]string, error) {
92+
return m.rolePermissions[role], nil
93+
}
94+
95+
func (m *mockProvider) AddRolePermission(role string, permission []string) error {
96+
m.rolePermissions[role] = append(m.rolePermissions[role], permission)
97+
return nil
98+
}
99+
100+
func (m *mockProvider) DeleteRolePermission(role string, permission []string) error {
101+
// Simple implementation for testing
102+
return nil
103+
}
104+
105+
// TestProviderInterface verifies that the Provider interface can be implemented and used.
106+
func TestProviderInterface(t *testing.T) {
107+
var provider Provider = newMockProvider()
108+
109+
// Test user operations
110+
err := provider.AddUser("alice")
111+
if err != nil {
112+
t.Fatalf("AddUser failed: %v", err)
113+
}
114+
115+
err = provider.AddUser("bob")
116+
if err != nil {
117+
t.Fatalf("AddUser failed: %v", err)
118+
}
119+
120+
users, err := provider.GetAllUsers()
121+
if err != nil {
122+
t.Fatalf("GetAllUsers failed: %v", err)
123+
}
124+
if len(users) != 2 {
125+
t.Fatalf("Expected 2 users, got %d", len(users))
126+
}
127+
128+
err = provider.DeleteUser("alice")
129+
if err != nil {
130+
t.Fatalf("DeleteUser failed: %v", err)
131+
}
132+
133+
users, err = provider.GetAllUsers()
134+
if err != nil {
135+
t.Fatalf("GetAllUsers failed: %v", err)
136+
}
137+
if len(users) != 1 {
138+
t.Fatalf("Expected 1 user after deletion, got %d", len(users))
139+
}
140+
141+
// Test role operations
142+
err = provider.AddRole("admin")
143+
if err != nil {
144+
t.Fatalf("AddRole failed: %v", err)
145+
}
146+
147+
err = provider.AddRole("editor")
148+
if err != nil {
149+
t.Fatalf("AddRole failed: %v", err)
150+
}
151+
152+
roles, err := provider.GetAllRoles()
153+
if err != nil {
154+
t.Fatalf("GetAllRoles failed: %v", err)
155+
}
156+
if len(roles) != 2 {
157+
t.Fatalf("Expected 2 roles, got %d", len(roles))
158+
}
159+
160+
err = provider.DeleteRole("admin")
161+
if err != nil {
162+
t.Fatalf("DeleteRole failed: %v", err)
163+
}
164+
165+
roles, err = provider.GetAllRoles()
166+
if err != nil {
167+
t.Fatalf("GetAllRoles failed: %v", err)
168+
}
169+
if len(roles) != 1 {
170+
t.Fatalf("Expected 1 role after deletion, got %d", len(roles))
171+
}
172+
173+
// Test permission operations
174+
err = provider.AddPermission("bob", []string{"data1", "read"})
175+
if err != nil {
176+
t.Fatalf("AddPermission failed: %v", err)
177+
}
178+
179+
perms, err := provider.GetPermissions("bob")
180+
if err != nil {
181+
t.Fatalf("GetPermissions failed: %v", err)
182+
}
183+
if len(perms) != 1 {
184+
t.Fatalf("Expected 1 permission, got %d", len(perms))
185+
}
186+
187+
// Test role permission operations
188+
err = provider.AddRolePermission("editor", []string{"data2", "write"})
189+
if err != nil {
190+
t.Fatalf("AddRolePermission failed: %v", err)
191+
}
192+
193+
rolePerms, err := provider.GetRolePermissions("editor")
194+
if err != nil {
195+
t.Fatalf("GetRolePermissions failed: %v", err)
196+
}
197+
if len(rolePerms) != 1 {
198+
t.Fatalf("Expected 1 role permission, got %d", len(rolePerms))
199+
}
200+
}

0 commit comments

Comments
 (0)