forked from Permify/go-role
/
roleRepository.go
278 lines (230 loc) · 10.5 KB
/
roleRepository.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
package repositories
import (
"gorm.io/gorm"
"github.com/MrWildanMD/go-role/collections"
"github.com/MrWildanMD/go-role/models"
"github.com/MrWildanMD/go-role/models/pivot"
"github.com/MrWildanMD/go-role/repositories/scopes"
"github.com/google/uuid"
)
// IRoleRepository its data access layer abstraction of role.
type IRoleRepository interface {
Migratable
// single fetch options
GetRoleByID(ID uint) (role models.Role, err error)
GetRoleByIDWithPermissions(ID uint) (role models.Role, err error)
GetRoleByGuardName(guardName string) (role models.Role, err error)
GetRoleByGuardNameWithPermissions(guardName string) (role models.Role, err error)
// Multiple fetch options
GetRoles(roleIDs []uint) (roles collections.Role, err error)
GetRolesWithPermissions(roleIDs []uint) (roles collections.Role, err error)
GetRolesByGuardNames(guardNames []string) (roles collections.Role, err error)
GetRolesByGuardNamesWithPermissions(guardNames []string) (roles collections.Role, err error)
// ID fetch options
GetRoleIDs(pagination scopes.GormPager) (roleIDs []uint, totalCount int64, err error)
GetRoleIDsOfUser(userID uuid.UUID, pagination scopes.GormPager) (roleIDs []uint, totalCount int64, err error)
GetRoleIDsOfPermission(permissionID uint, pagination scopes.GormPager) (roleIDs []uint, totalCount int64, err error)
// FirstOrCreate & Updates & Delete
FirstOrCreate(role *models.Role) (err error)
Updates(role *models.Role, updates map[string]interface{}) (err error)
Delete(role *models.Role) (err error)
// Actions
AddPermissions(role *models.Role, permissions collections.Permission) (err error)
ReplacePermissions(role *models.Role, permissions collections.Permission) (err error)
RemovePermissions(role *models.Role, permissions collections.Permission) (err error)
ClearPermissions(role *models.Role) (err error)
// Controls
HasPermission(roles collections.Role, permission models.Permission) (b bool, err error)
HasAllPermissions(roles collections.Role, permissions collections.Permission) (b bool, err error)
HasAnyPermissions(roles collections.Role, permissions collections.Permission) (b bool, err error)
}
// RoleRepository its data access layer of role.
type RoleRepository struct {
Database *gorm.DB
}
// Migrate generate tables from the database.
// @return error
func (repository *RoleRepository) Migrate() (err error) {
err = repository.Database.AutoMigrate(models.Role{})
err = repository.Database.AutoMigrate(pivot.UserRoles{})
return
}
// SINGLE FETCH OPTIONS
// GetRoleByID get role by id.
// @param uint
// @return models.Role, error
func (repository *RoleRepository) GetRoleByID(ID uint) (role models.Role, err error) {
err = repository.Database.First(&role, "roles.id = ?", ID).Error
return
}
// GetRoleByIDWithPermissions get role by id with its permissions.
// @param uint
// @return models.Role, error
func (repository *RoleRepository) GetRoleByIDWithPermissions(ID uint) (role models.Role, err error) {
err = repository.Database.Preload("Permissions").First(&role, "roles.id = ?", ID).Error
return
}
// GetRoleByGuardName get role by guard name.
// @param string
// @return models.Role, error
func (repository *RoleRepository) GetRoleByGuardName(guardName string) (role models.Role, err error) {
err = repository.Database.Where("roles.guard_name = ?", guardName).First(&role).Error
return
}
// GetRoleByGuardNameWithPermissions get role by guard name with its permissions.
// @param string
// @return models.Role, error
func (repository *RoleRepository) GetRoleByGuardNameWithPermissions(guardName string) (role models.Role, err error) {
err = repository.Database.Preload("Permissions").Where("roles.guard_name = ?", guardName).First(&role).Error
return
}
// MULTIPLE FETCH OPTIONS
// GetRoles get roles by ids.
// @param []uint
// @return collections.Role, error
func (repository *RoleRepository) GetRoles(IDs []uint) (roles collections.Role, err error) {
err = repository.Database.Where("roles.id IN (?)", IDs).Find(&roles).Error
return
}
// GetRolesWithPermissions get roles by ids with its permissions.
// @param []uint
// @return collections.Role, error
func (repository *RoleRepository) GetRolesWithPermissions(IDs []uint) (roles collections.Role, err error) {
err = repository.Database.Preload("Permissions").Where("roles.id IN (?)", IDs).Find(&roles).Error
return
}
// GetRolesByGuardNames get roles by guard names.
// @param []string
// @return collections.Role, error
func (repository *RoleRepository) GetRolesByGuardNames(guardNames []string) (roles collections.Role, err error) {
err = repository.Database.Where("roles.guard_name IN (?)", guardNames).Find(&roles).Error
return
}
// GetRolesByGuardNamesWithPermissions get roles by guard names.
// @param []string
// @return collections.Role, error
func (repository *RoleRepository) GetRolesByGuardNamesWithPermissions(guardNames []string) (roles collections.Role, err error) {
err = repository.Database.Preload("Permissions").Where("roles.guard_name IN (?)", guardNames).Find(&roles).Error
return
}
// ID FETCH OPTIONS
// GetRoleIDs get role ids. (with pagination)
// @param repositories_scopes.GormPager
// @return []uint, int64, error
func (repository *RoleRepository) GetRoleIDs(pagination scopes.GormPager) (roleIDs []uint, totalCount int64, err error) {
err = repository.Database.Model(&models.Role{}).Count(&totalCount).Scopes(repository.paginate(pagination)).Pluck("roles.id", &roleIDs).Error
return
}
// GetRoleIDsOfUser get role ids of user. (with pagination)
// @param uint
// @param repositories_scopes.GormPager
// @return []uint, int64, error
func (repository *RoleRepository) GetRoleIDsOfUser(userID uuid.UUID, pagination scopes.GormPager) (roleIDs []uint, totalCount int64, err error) {
err = repository.Database.Table("user_roles").Where("user_roles.user_id = ?", userID).Count(&totalCount).Scopes(repository.paginate(pagination)).Pluck("user_roles.role_id", &roleIDs).Error
return
}
// GetRoleIDsOfPermission get role ids of permission. (with pagination)
// @param uint
// @param repositories_scopes.GormPager
// @return []uint, int64, error
func (repository *RoleRepository) GetRoleIDsOfPermission(permissionID uint, pagination scopes.GormPager) (roleIDs []uint, totalCount int64, err error) {
err = repository.Database.Table("role_permissions").Where("role_permissions.permission_id = ?", permissionID).Count(&totalCount).Scopes(repository.paginate(pagination)).Pluck("role_permissions.role_id", &roleIDs).Error
return
}
// FirstOrCreate & Updates & Delete
// FirstOrCreate create new role if name not exist.
// @param *models.Role
// @return error
func (repository *RoleRepository) FirstOrCreate(role *models.Role) error {
return repository.Database.Where(models.Role{GuardName: role.GuardName}).FirstOrCreate(role).Error
}
// Updates update role.
// @param *models.Role
// @param map[string]interface{}
// @return error
func (repository *RoleRepository) Updates(role *models.Role, updates map[string]interface{}) (err error) {
return repository.Database.Model(role).Updates(updates).Error
}
// Delete delete role.
// @param *models.Role
// @return error
func (repository *RoleRepository) Delete(role *models.Role) (err error) {
return repository.Database.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("user_roles.role_id = ?", role.ID).Delete(&pivot.UserRoles{}).Error; err != nil {
tx.Rollback()
return err
}
if err := tx.Delete(role).Error; err != nil {
tx.Rollback()
return err
}
return nil
})
}
// ACTIONS
// AddPermissions add permissions to role.
// @param *models.Role
// @param collections.Permission
// @return error
func (repository *RoleRepository) AddPermissions(role *models.Role, permissions collections.Permission) error {
return repository.Database.Model(role).Association("Permissions").Append(permissions.Origin())
}
// ReplacePermissions replace permissions of role.
// @param *models.Role
// @param collections.Permission
// @return error
func (repository *RoleRepository) ReplacePermissions(role *models.Role, permissions collections.Permission) error {
return repository.Database.Model(role).Association("Permissions").Replace(permissions.Origin())
}
// RemovePermissions remove permissions of role.
// @param *models.Role
// @param collections.Permission
// @return error
func (repository *RoleRepository) RemovePermissions(role *models.Role, permissions collections.Permission) error {
return repository.Database.Model(role).Association("Permissions").Delete(permissions.Origin())
}
// ClearPermissions remove all permissions of role.
// @param *models.Role
// @return error
func (repository *RoleRepository) ClearPermissions(role *models.Role) (err error) {
return repository.Database.Model(role).Association("Permissions").Clear()
}
// Controls
// HasPermission does the role or any of the roles have given permission?
// @param collections.Role
// @param models.Permission
// @return bool, error
func (repository *RoleRepository) HasPermission(roles collections.Role, permission models.Permission) (b bool, err error) {
var count int64
err = repository.Database.Table("role_permissions").Where("role_permissions.role_id IN (?)", roles.IDs()).Where("role_permissions.permission_id = ?", permission.ID).Count(&count).Error
return count > 0, err
}
// HasAllPermissions does the role or roles have all the given permissions?
// @param collections.Role
// @param collections.Permission
// @return bool, error
func (repository *RoleRepository) HasAllPermissions(roles collections.Role, permissions collections.Permission) (b bool, err error) {
var count int64
err = repository.Database.Table("role_permissions").Where("role_permissions.role_id IN (?)", roles.IDs()).Where("role_permissions.permission_id IN (?)", permissions.IDs()).Count(&count).Error
return roles.Len()*permissions.Len() == count, err
}
// HasAnyPermissions does the role or roles have any of the given permissions?
// @param collections.Role
// @param collections.Permission
// @return bool, error
func (repository *RoleRepository) HasAnyPermissions(roles collections.Role, permissions collections.Permission) (b bool, err error) {
var count int64
err = repository.Database.Table("role_permissions").Where("role_permissions.role_id IN (?)", roles.IDs()).Where("role_permissions.permission_id IN (?)", permissions.IDs()).Count(&count).Error
return count > 0, err
}
// paginate pagging if pagination option is true.
// @param repositories_scopes.GormPager
// @return func(db *gorm.DB) *gorm.DB
func (repository *RoleRepository) paginate(pagination scopes.GormPager) func(db *gorm.DB) *gorm.DB {
return func(db *gorm.DB) *gorm.DB {
if pagination != nil {
db.Scopes(pagination.ToPaginate())
}
return db
}
}