Associate users with roles and permissions
This package allows you to manage user permissions and roles in your database.
👇 Setup
Install
go get github.com/Permify/go-role
Run All Tests
Get the database driver for gorm that you will be using
# mysql go get gorm.io/driver/mysql # or postgres go get gorm.io/driver/postgres # or sqlite go get gorm.io/driver/sqlite # or sqlserver go get gorm.io/driver/sqlserver # or clickhouse go get gorm.io/driver/clickhouse
Import permify.
import permify `github.com/Permify/go-role`
Initialize the new Permify.
// initialize the database. (you can use all gorm's supported databases) db, _ := gorm.Open(mysql.Open("user:password@tcp(host:3306)/db?charset=utf8&parseTime=True&loc=Local"), &gorm.Config{}) // New initializer for Permify // If migration is true, it generate all tables in the database if they don't exist. permify, _ := permify.New(permify.Options{ Migrate: true, DB: db, })
🚲 Basic Usage
This package allows users to be associated with permissions and roles. Each role is associated with multiple permissions.
// CreateRole create new role. // Name parameter is converted to guard name. example: senior $#% associate -> senior-associate. // If a role with the same name has been created before, it will not create it again. (FirstOrCreate) // First parameter is role name, second parameter is role description. err := permify.CreateRole("admin", "role description") // CreatePermission create new permission. // Name parameter is converted to guard name. example: create $#% contact -> create-contact. // If a permission with the same name has been created before, it will not create it again. (FirstOrCreate) err := permify.CreatePermission("edit user details", "")
Permissions can be added to a role using AddPermissionsToRole method in different ways:
// first parameter is role id err := permify.AddPermissionsToRole(1, "edit user details") // or err := permify.AddPermissionsToRole("admin", []string{"edit user details", "create contact"}) // or err := permify.AddPermissionsToRole("admin", []uint{1, 3})
With using these methods you can remove and overwrite permissions:
// overwrites the permissions of the role according to the permission names or ids. err := permify.ReplacePermissionsToRole("admin", []string{"edit user details", "create contact"}) // remove permissions from role according to the permission names or ids. err := permify.RemovePermissionsFromRole("admin", []string{"edit user details"})
Basic fetch queries:
// Fetch all the roles. (with pagination option). // If withPermissions is true, it will preload the permissions to the role. // If pagination is nil, it returns without paging. roles, totalCount, err := permify.GetAllRoles(options.RoleOption{ WithPermissions: true, Pagination: &utils.Pagination{ Page: 1, Limit: 1, }, }) // without paging. roles, totalCount, err := permify.GetAllRoles(options.RoleOption{ WithPermissions: false, }) // The data returned is a collection of roles. // Collections provides a fluent convenient wrapper for working with arrays of data. fmt.Println(roles.IDs()) fmt.Println(roles.Names()) fmt.Println(roles.Permissions().Names()) // Fetch all permissions of the user that come with direct and roles. permissions, _ := permify.GetAllPermissionsOfUser(1) // Fetch all direct permissions of the user. (with pagination option) permissions, totalCount, err := permify.GetDirectPermissionsOfUser(1, options.PermissionOption{ Pagination: &utils.Pagination{ Page: 1, Limit: 10, }, })
Controls
// does the role or any of the roles have given permission? can, err := permify.RoleHasPermission("admin", "edit user details") // does the role or roles have any of the given permissions? can, err := permify.RoleHasAnyPermissions([]string{"admin", "manager"}, []string{"edit user details", "create contact"}) // does the role or roles have all the given permissions? can, err := permify.RoleHasAllPermissions("admin", []string{"edit user details", "create contact"}) // does the user have the given permission? (including the permissions of the roles) can, err := permify.UserHasPermission(1, "edit user details") // does the user have the given permission? (not including the permissions of the roles) can, err := permify.UserHasDirectPermission(1, "edit user details") // does the user have any of the given permissions? (including the permissions of the roles) can, err := permify.UserHasAnyPermissions(1, []uint{1, 2}) // does the user have all the given roles? can, err := permify.UserHasAllRoles(1, []string{"admin", "manager"}) // does the user have any of the given roles? can, err := permify.UserHasAnyRoles(1, []string{"admin", "manager"})
🚘 Using permissions via roles
Adding Role
Add roles to user according to the role names or ids:
// add one role to user err := permify.AddRolesToUser(1, "admin") // you can also add multiple roles at once err := permify.AddRolesToUser(1, []string{"admin", "manager"}) // or err := permify.AddRolesToUser(1, []uint{1,2})
Replace the roles of the user according to the role names or ids:
// remove all user roles and add admin role err := permify.ReplaceRolesToUser(1, "admin") // you can also replace multiple roles at once err := permify.ReplaceRolesToUser(1, []string{"admin", "manager"}) // or err := permify.RemoveRolesFromUser(1, []uint{1,2})
Remove the roles of the user according to the role names or ids:
// remove one role to user err := permify.RemoveRolesFromUser(1, "admin") // you can also remove multiple roles at once err := permify.RemoveRolesFromUser(1, []string{"admin", "manager"}) // or err := permify.RemoveRolesFromUser(1, []uint{1,2})
Control Roles
// does the user have the given role? can, err := permify.UserHasRole(1, "admin") // does the user have all the given roles? can, err := permify.UserHasAllRoles(1, []string{"admin", "manager"}) // does the user have any of the given roles? can, err := permify.UserHasAnyRoles(1, []string{"admin", "manager"})
Get User's Roles
roles, totalCount, err := permify.GetRolesOfUser(1, options.RoleOption{ WithPermissions: true, // preload role's permissions Pagination: &utils.Pagination{ Page: 1, Limit: 1, }, }) // the data returned is a collection of roles. // Collections provides a fluent convenient wrapper for working with arrays of data. fmt.Println(roles.IDs()) fmt.Println(roles.Names()) fmt.Println(roles.Len()) fmt.Println(roles.Permissions().Names())
Add Permissions to Roles
// add one permission to role // first parameter can be role name or id, second parameter can be permission name(s) or id(s). err := permify.AddPermissionsToRole("admin", "edit contact details") // you can also add multiple permissions at once err := permify.AddPermissionsToRole("admin", []string{"edit contact details", "delete user"}) // or err := permify.AddPermissionsToRole("admin", []uint{1, 2})
Remove Permissions from Roles
// remove one permission to role err := permify.RemovePermissionsFromRole("admin", "edit contact details") // you can also add multiple permissions at once err := permify.RemovePermissionsFromRole("admin", []string{"edit contact details", "delete user"}) // or err := permify.RemovePermissionsFromRole("admin", []uint{1, 2})
Control Role's Permissions
// does the role or any of the roles have given permission? can, err := permify.RoleHasPermission([]string{"admin", "manager"}, "edit contact details") // does the role or roles have all the given permissions? can, err := permify.RoleHasAllPermissions("admin", []string{"edit contact details", "delete contact"}) // does the role or roles have any of the given permissions? can, err := permify.RoleHasAnyPermissions(1, []string{"edit contact details", "delete contact"})
Get Role's Permissions
permissions, totalCount, err := permify.GetPermissionsOfRoles([]string{"admin", "manager"}, options.PermissionOption{ Pagination: &utils.Pagination{ Page: 1, Limit: 1, }, }) // the data returned is a collection of permissions. // Collections provides a fluent convenient wrapper for working with arrays of data. fmt.Println(permissions.IDs()) fmt.Println(permissions.Names()) fmt.Println(permissions.Len())
🚤 Direct Permissions
Adding Direct Permissions
Add direct permission or permissions to user according to the permission names or ids.
// add one permission to user err := permify.AddPermissionsToUser(1, "edit contact details") // you can also add multiple permissions at once err := permify.AddPermissionsToUser(1, []string{"edit contact details", "create contact"}) // or err := permify.AddPermissionsToUser(1, []uint{1,2})
Remove the roles of the user according to the role names or ids:
// remove one role to user err := permify.RemovePermissionsFromUser(1, "edit contact details") // you can also remove multiple permissions at once err := permify.RemovePermissionsFromUser(1, []string{"edit contact details", "create contact"}) // or err := permify.RemovePermissionsFromUser(1, []uint{1,2})
Control Permissions
// ALL PERMISSIONS // does the user have the given permission? (including the permissions of the roles) can, err := permify.UserHasPermission(1, "edit contact details") // does the user have all the given permissions? (including the permissions of the roles) can, err := permify.UserHasAllPermissions(1, []string{"edit contact details", "delete contact"}) // does the user have any of the given permissions? (including the permissions of the roles). can, err := permify.UserHasAnyPermissions(1, []string{"edit contact details", "delete contact"}) // DIRECT PERMISSIONS // does the user have the given permission? (not including the permissions of the roles) can, err := permify.UserHasDirectPermission(1, "edit contact details") // does the user have all the given permissions? (not including the permissions of the roles) can, err := permify.UserHasAllDirectPermissions(1, []string{"edit contact details", "delete contact"}) // does the user have any of the given permissions? (not including the permissions of the roles) can, err := permify.UserHasAnyDirectPermissions(1, []string{"edit contact details", "delete contact"})
Get User's All Permissions
permissions, err := permify.GetAllPermissionsOfUser(1) // the data returned is a collection of permissions. // Collections provides a fluent convenient wrapper for working with arrays of data. fmt.Println(permissions.IDs()) fmt.Println(permissions.Names()) fmt.Println(permissions.Len())
Get User's Direct Permissions
permissions, totalCount, err := permify.GetDirectPermissionsOfUser(1, options.PermissionOption{ Pagination: &utils.Pagination{ Page: 1, Limit: 10, }, }) // the data returned is a collection of permissions. // Collections provides a fluent convenient wrapper for working with arrays of data. fmt.Println(permissions.IDs()) fmt.Println(permissions.Names()) fmt.Println(permissions.Len())
🚀 Using your user model
You can create the relationships between the user and the role and permissions in this manner. In this way:
- You can manage user preloads
- You can create foreign key between users and pivot tables (user_roles, user_permissions).
import ( "gorm.io/gorm" models `github.com/Permify/go-role/models` ) type User struct { gorm.Model Name string // permify Roles []models.Role `gorm:"many2many:user_roles;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` Permissions []models.Permission `gorm:"many2many:user_permissions;constraint:OnUpdate:CASCADE,OnDelete:CASCADE"` }
⁉️ Error Handling
ErrRecordNotFound
You can use error handling in the same way as gorm. for example:
// check if returns RecordNotFound error permission, err := permify.GetPermission(1) if errors.Is(err, gorm.ErrRecordNotFound) { // record not found }
Errors
Stargazers
Community & Support
Join our Discord channel for issues, feature requests, feedbacks or anything else. We love to talk about authorization and access control ❤️