Merge pull request 'develop' (#11) from develop into main

Reviewed-on: #11
This commit is contained in:
Zeni Kim 2024-12-18 08:22:38 -05:00
commit d4d4abb751
11 changed files with 721 additions and 4 deletions

View file

@ -19,6 +19,29 @@ import (
func AdminUsersList(c *core.Context) *core.Response { func AdminUsersList(c *core.Context) *core.Response {
// initiate authority
auth := new(utils.Authority)
var session = new(utils.SessionUser)
// true if session is active
hassession := session.Init(c)
if !hassession {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
session_uid := session.GetUserID()
// check if user has role admin
is_admin, _ := auth.CheckUserRole(c, session_uid, "admin")
if !is_admin {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
// continue if has session and is admin
var users []models.User var users []models.User
db := c.GetGorm() db := c.GetGorm()
db.Find(&users) db.Find(&users)
@ -46,6 +69,10 @@ func AdminUsersList(c *core.Context) *core.Response {
Value: "Email", Value: "Email",
ValueType: "string", ValueType: "string",
}, },
{
Value: "Roles",
ValueType: "string",
},
{ {
Value: "Created", Value: "Created",
}, },
@ -57,13 +84,26 @@ func AdminUsersList(c *core.Context) *core.Response {
}, },
} }
var listroles string
rows := make([][]components.ContentTableTD, len(users)) rows := make([][]components.ContentTableTD, len(users))
for i, u := range users { for i, u := range users {
roles, _ := auth.GetUserRoles(c, u.ID)
listroles = ""
for _, role := range roles {
if listroles != "" {
listroles += ", "
}
listroles += role.Name
}
row := []components.ContentTableTD{ row := []components.ContentTableTD{
{Value: strconv.Itoa(int(u.ID))}, {Value: strconv.Itoa(int(u.ID))},
{Value: u.Name}, {Value: u.Name},
{Value: u.Fullname}, {Value: u.Fullname},
{Value: u.Email}, {Value: u.Email},
{Value: listroles},
{Value: utils.FormatUnix(u.Created)}, {Value: utils.FormatUnix(u.Created)},
{Value: utils.FormatUnix(u.Updated)}, {Value: utils.FormatUnix(u.Updated)},
{Value: components.ContentHref{ {Value: components.ContentHref{
@ -93,10 +133,44 @@ func AdminUsersList(c *core.Context) *core.Response {
func AdminUsersAdd(c *core.Context) *core.Response { func AdminUsersAdd(c *core.Context) *core.Response {
// initiate authority
auth := new(utils.Authority)
var session = new(utils.SessionUser)
// true if session is active
hassession := session.Init(c)
if !hassession {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
session_uid := session.GetUserID()
// check if user has role admin
is_admin, _ := auth.CheckUserRole(c, session_uid, "admin")
if !is_admin {
type emptytemplate struct{}
emptyData := emptytemplate{}
return c.Response.Template("nopermission.html", emptyData)
}
// check if is submit // check if is submit
submit := c.GetRequestParam("submit").(string) submit := c.GetRequestParam("submit").(string)
errormessages := make([]string, 0) errormessages := make([]string, 0)
var listroles []components.FormCheckboxItem
systemroles, _ := auth.GetAllRoles(c)
for _, systemrole := range systemroles {
var userrole components.FormCheckboxItem
userrole.Label = systemrole.Name
userrole.Name = "roles"
userrole.Value = systemrole.Slug
if systemrole.Slug == "authenticated" {
userrole.IsChecked = true
}
listroles = append(listroles, userrole)
}
name := "" name := ""
fullname := "" fullname := ""
@ -109,6 +183,7 @@ func AdminUsersAdd(c *core.Context) *core.Response {
fullname = c.GetRequestParam("fullname").(string) fullname = c.GetRequestParam("fullname").(string)
email = c.GetRequestParam("email").(string) email = c.GetRequestParam("email").(string)
password = c.GetRequestParam("password").(string) password = c.GetRequestParam("password").(string)
roles := c.GetRequesForm("roles").([]string)
// check if email exists // check if email exists
var user models.User var user models.User
@ -161,6 +236,11 @@ func AdminUsersAdd(c *core.Context) *core.Response {
errormessages = append(errormessages, res.Error.Error()) errormessages = append(errormessages, res.Error.Error())
} else { } else {
// assign roles
for _, role := range roles {
auth.AssignRoleToUser(c, user.ID, role)
}
// fire user registered event // fire user registered event
err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_REGISTERED, Payload: map[string]interface{}{ err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_REGISTERED, Payload: map[string]interface{}{
"user": user, "user": user,
@ -180,6 +260,7 @@ func AdminUsersAdd(c *core.Context) *core.Response {
FieldName components.FormInput FieldName components.FormInput
FieldFullname components.FormInput FieldFullname components.FormInput
FieldEmail components.FormInput FieldEmail components.FormInput
FieldRoles components.FormCheckbox
FieldPassword components.FormInput FieldPassword components.FormInput
ErrorMessages []string ErrorMessages []string
SubmitButton components.FormButton SubmitButton components.FormButton
@ -208,6 +289,10 @@ func AdminUsersAdd(c *core.Context) *core.Response {
//Autocomplete: true, //Autocomplete: true,
IsRequired: true, IsRequired: true,
}, },
FieldRoles: components.FormCheckbox{
Label: "Roles",
AllCheckbox: listroles,
},
FieldPassword: components.FormInput{ FieldPassword: components.FormInput{
ID: "password", ID: "password",
Label: "Password", Label: "Password",
@ -236,6 +321,29 @@ func AdminUsersEdit(c *core.Context) *core.Response {
user_id := c.GetPathParam("id") user_id := c.GetPathParam("id")
errormessages := make([]string, 0) errormessages := make([]string, 0)
// initiate authority
auth := new(utils.Authority)
var listroles []components.FormCheckboxItem
systemroles, _ := auth.GetAllRoles(c)
user_id_uint, _ := strconv.ParseUint(user_id.(string), 10, 32)
userroles, _ := auth.GetUserRoles(c, uint(user_id_uint))
for _, systemrole := range systemroles {
var userrole components.FormCheckboxItem
userrole.Label = systemrole.Name
userrole.Name = "roles"
userrole.Value = systemrole.Slug
for _, ur := range userroles {
if ur.Slug == systemrole.Slug {
userrole.IsChecked = true
break
}
}
listroles = append(listroles, userrole)
}
var origin_user models.User var origin_user models.User
@ -259,6 +367,7 @@ func AdminUsersEdit(c *core.Context) *core.Response {
fullname = c.GetRequestParam("fullname").(string) fullname = c.GetRequestParam("fullname").(string)
email = c.GetRequestParam("email").(string) email = c.GetRequestParam("email").(string)
password = c.GetRequestParam("password").(string) password = c.GetRequestParam("password").(string)
roles := c.GetRequesForm("roles").([]string)
key := c.GetRequestParam("key") key := c.GetRequestParam("key")
// check if email exists // check if email exists
@ -316,6 +425,14 @@ func AdminUsersEdit(c *core.Context) *core.Response {
c.GetLogger().Error("Admin user: error updating") c.GetLogger().Error("Admin user: error updating")
errormessages = append(errormessages, fmt.Sprintf("Error updating user %s:", user_id_string)) errormessages = append(errormessages, fmt.Sprintf("Error updating user %s:", user_id_string))
} else { } else {
// delete roles
auth.RevokeAllUserRole(c, origin_user.ID)
// assign roles
for _, role := range roles {
auth.AssignRoleToUser(c, origin_user.ID, role)
}
return c.Response.Redirect("/admin/users") return c.Response.Redirect("/admin/users")
} }
} }
@ -325,6 +442,7 @@ func AdminUsersEdit(c *core.Context) *core.Response {
FieldName components.FormInput FieldName components.FormInput
FieldFullname components.FormInput FieldFullname components.FormInput
FieldEmail components.FormInput FieldEmail components.FormInput
FieldRoles components.FormCheckbox
FieldPassword components.FormInput FieldPassword components.FormInput
FieldKey components.FormInput FieldKey components.FormInput
ErrorMessages []string ErrorMessages []string
@ -355,6 +473,10 @@ func AdminUsersEdit(c *core.Context) *core.Response {
//Autocomplete: true, //Autocomplete: true,
IsRequired: true, IsRequired: true,
}, },
FieldRoles: components.FormCheckbox{
Label: "Roles",
AllCheckbox: listroles,
},
FieldPassword: components.FormInput{ FieldPassword: components.FormInput{
ID: "password", ID: "password",
Label: "Password", Label: "Password",
@ -461,6 +583,9 @@ func AdminUsersDelConfirm(c *core.Context) *core.Response {
// check if is the seed user // check if is the seed user
seed := "1" seed := "1"
if user_id != seed { if user_id != seed {
// initiate authority
auth := new(utils.Authority)
// Delete the user // Delete the user
// fire user delete event // fire user delete event
err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_DELETED, Payload: map[string]interface{}{ err := c.GetEventsManager().Fire(&core.Event{Name: events.USER_DELETED, Payload: map[string]interface{}{
@ -469,6 +594,7 @@ func AdminUsersDelConfirm(c *core.Context) *core.Response {
if err != nil { if err != nil {
c.GetLogger().Error(err.Error()) c.GetLogger().Error(err.Error())
} }
auth.RevokeAllUserRole(c, origin_user.ID)
result_db.Unscoped().Delete(&origin_user) result_db.Unscoped().Delete(&origin_user)
} }
} }

16
models/permission.go Normal file
View file

@ -0,0 +1,16 @@
// Copyright (c) 2025 Zeni Kim <zenik@smarteching.com>
// Use of this source code is governed by MIT-style
// license that can be found in the LICENSE file.
package models
type Permission struct {
BaseModel
Name string
Slug string
}
// TableName sets the table name
func (Permission) TableName() string {
return "permissions"
}

View file

@ -0,0 +1,16 @@
// Copyright (c) 2025 Zeni Kim <zenik@smarteching.com>
// Use of this source code is governed by MIT-style
// license that can be found in the LICENSE file.
package models
type RolePermission struct {
BaseModel
RoleID uint // Role id
PermissionID uint // Permission id
}
// TableName sets the table name
func (RolePermission) TableName() string {
return "role_permissions"
}

16
models/roles.go Normal file
View file

@ -0,0 +1,16 @@
// Copyright (c) 2025 Zeni Kim <zenik@smarteching.com>
// Use of this source code is governed by MIT-style
// license that can be found in the LICENSE file.
package models
type Role struct {
BaseModel
Name string // The name of the role
Slug string // String based unique identifier of the role, (use hyphen seperated role name '-', instead of space)
}
// TableName sets the table name
func (Role) TableName() string {
return "roles"
}

16
models/user-roles.go Normal file
View file

@ -0,0 +1,16 @@
// Copyright (c) 2025 Zeni Kim <zenik@smarteching.com>
// Use of this source code is governed by MIT-style
// license that can be found in the LICENSE file.
package models
type UserRole struct {
BaseModel
UserID uint // The user id
RoleID uint // The role id
}
// TableName sets the table name
func (UserRole) TableName() string {
return "user_roles"
}

View file

@ -6,8 +6,12 @@
package main package main
import ( import (
"errors"
"git.smarteching.com/goffee/core" "git.smarteching.com/goffee/core"
"git.smarteching.com/goffee/cup/models" "git.smarteching.com/goffee/cup/models"
"git.smarteching.com/goffee/cup/utils"
"gorm.io/gorm"
) )
func RunAutoMigrations() { func RunAutoMigrations() {
@ -17,5 +21,18 @@ func RunAutoMigrations() {
//############################## //##############################
// Add auto migrations for your models here... // Add auto migrations for your models here...
db.AutoMigrate(&models.User{}) db.AutoMigrate(&models.UserRole{})
db.AutoMigrate(&models.Role{})
db.AutoMigrate(&models.RolePermission{})
db.AutoMigrate(&models.Permission{})
// End your auto migrations
// Create seed data data, DO NOT TOUCH
if err := db.AutoMigrate(&models.User{}); err == nil && db.Migrator().HasTable(&models.User{}) {
if err := db.First(&models.User{}).Error; errors.Is(err, gorm.ErrRecordNotFound) {
utils.CreateSeedData()
}
}
} }

View file

@ -15,7 +15,8 @@
<form method="POST" id="add_user" action="/admin/users/add"> <form method="POST" id="add_user" action="/admin/users/add">
{{template "form_input" .FieldName}} {{template "form_input" .FieldName}}
{{template "form_input" .FieldFullname}} {{template "form_input" .FieldFullname}}
{{template "form_input" .FieldEmail}} {{template "form_input" .FieldEmail}}
{{template "form_checkbox" .FieldRoles}}
{{template "form_input" .FieldPassword}} {{template "form_input" .FieldPassword}}
<hr> <hr>
{{template "form_button" .SubmitButton}} {{template "form_button" .SubmitButton}}

View file

@ -15,7 +15,8 @@
<form method="POST" id="add_user" action="/admin/users/edit/{{.FieldKey.Value}}"> <form method="POST" id="add_user" action="/admin/users/edit/{{.FieldKey.Value}}">
{{template "form_input" .FieldName}} {{template "form_input" .FieldName}}
{{template "form_input" .FieldFullname}} {{template "form_input" .FieldFullname}}
{{template "form_input" .FieldEmail}} {{template "form_input" .FieldEmail}}
{{template "form_checkbox" .FieldRoles}}
{{template "form_input" .FieldPassword}} {{template "form_input" .FieldPassword}}
{{template "form_input" .FieldKey}} {{template "form_input" .FieldKey}}
{{template "form_button" .SubmitButton}} {{template "form_button" .SubmitButton}}

View file

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
{{template "page_head" "No permission"}}
<body>
<div class="container">
<div class="row">
You do not have permission to visit this page.
</div>
</div>
{{template "page_footer"}}
</body>
</html>

436
utils/authority.go Normal file
View file

@ -0,0 +1,436 @@
// Copyright (c) 2025 Zeni Kim <zenik@smarteching.com>
// Use of this source code is governed by MIT-style
// license that can be found in the LICENSE file.
package utils
import (
"errors"
"fmt"
"git.smarteching.com/goffee/core"
"git.smarteching.com/goffee/cup/models"
"gorm.io/gorm"
)
type Authority struct{}
var auth *Authority
var (
ErrPermissionInUse = errors.New("cannot delete assigned permission")
ErrPermissionNotFound = errors.New("permission not found")
ErrRoleInUse = errors.New("cannot delete assigned role")
ErrRoleNotFound = errors.New("role not found")
)
// Add a new role to the database
func (a *Authority) CreateRole(c *core.Context, r models.Role) error {
roleSlug := r.Slug
var dbRole models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&dbRole)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
// create
createRes := c.GetGorm().Create(&r)
if createRes.Error != nil {
return createRes.Error
}
return nil
}
return res.Error
}
return errors.New(fmt.Sprintf("role '%v' already exists", roleSlug))
}
// Add a new permission to the database
func (a *Authority) CreatePermission(c *core.Context, p models.Permission) error {
permSlug := p.Slug
var dbPerm models.Permission
res := c.GetGorm().Where("slug = ?", permSlug).First(&dbPerm)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
// create
createRes := c.GetGorm().Create(&p)
if createRes.Error != nil {
return createRes.Error
}
return nil
}
return res.Error
}
return errors.New(fmt.Sprintf("permission '%v' already exists", permSlug))
}
// Assigns a group of permissions to a given role
func (a *Authority) AssignPermissionsToRole(c *core.Context, roleSlug string, permSlugs []string) error {
var role models.Role
rRes := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if rRes.Error != nil {
if errors.Is(rRes.Error, gorm.ErrRecordNotFound) {
return ErrRoleNotFound
}
return rRes.Error
}
var perms []models.Permission
for _, permSlug := range permSlugs {
var perm models.Permission
pRes := c.GetGorm().Where("slug = ?", permSlug).First(&perm)
if pRes.Error != nil {
if errors.Is(pRes.Error, gorm.ErrRecordNotFound) {
return ErrPermissionNotFound
}
return pRes.Error
}
perms = append(perms, perm)
}
tx := c.GetGorm().Begin()
for _, perm := range perms {
var rolePerm models.RolePermission
res := c.GetGorm().Where("role_id = ?", role.ID).Where("permission_id =?", perm.ID).First(&rolePerm)
if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) {
cRes := tx.Create(&models.RolePermission{RoleID: role.ID, PermissionID: perm.ID})
if cRes.Error != nil {
tx.Rollback()
return cRes.Error
}
}
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
tx.Rollback()
return res.Error
}
if rolePerm != (models.RolePermission{}) {
tx.Rollback()
return errors.New(fmt.Sprintf("permission '%v' is aleady assigned to the role '%v'", perm.Name, role.Name))
}
rolePerm = models.RolePermission{}
}
return tx.Commit().Error
}
// Assigns a role to a given user
func (a *Authority) AssignRoleToUser(c *core.Context, userID uint, roleSlug string) error {
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return ErrRoleNotFound
}
return res.Error
}
var userRole models.UserRole
res = c.GetGorm().Where("user_id = ?", userID).Where("role_id = ?", role.ID).First(&userRole)
if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) {
c.GetGorm().Create(&models.UserRole{UserID: userID, RoleID: role.ID})
return nil
}
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
return res.Error
}
return errors.New(fmt.Sprintf("this role '%v' is aleady assigned to the user", roleSlug))
}
// Checks if a role is assigned to a user
func (a *Authority) CheckUserRole(c *core.Context, userID uint, roleSlug string) (bool, error) {
// find the role
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, ErrRoleNotFound
}
return false, res.Error
}
// check if the role is a assigned
var userRole models.UserRole
res = c.GetGorm().Where("user_id = ?", userID).Where("role_id = ?", role.ID).First(&userRole)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, nil
}
return false, res.Error
}
return true, nil
}
// Checks if a permission is assigned to a user
func (a *Authority) CheckUserPermission(c *core.Context, userID uint, permSlug string) (bool, error) {
// the user role
var userRoles []models.UserRole
res := c.GetGorm().Where("user_id = ?", userID).Find(&userRoles)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, nil
}
return false, res.Error
}
//prepare an array of role ids
var roleIDs []interface{}
for _, r := range userRoles {
roleIDs = append(roleIDs, r.RoleID)
}
// find the permission
var perm models.Permission
res = c.GetGorm().Where("slug = ?", permSlug).First(&perm)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, ErrPermissionNotFound
}
return false, res.Error
}
// find the role permission
var rolePermission models.RolePermission
res = c.GetGorm().Where("role_id IN (?)", roleIDs).Where("permission_id = ?", perm.ID).First(&rolePermission)
if res.Error != nil && errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, nil
}
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, res.Error
}
return true, nil
}
// Checks if a permission is assigned to a role
func (a *Authority) CheckRolePermission(c *core.Context, roleSlug string, permSlug string) (bool, error) {
// find the role
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, ErrRoleNotFound
}
return false, res.Error
}
// find the permission
var perm models.Permission
res = c.GetGorm().Where("slug = ?", permSlug).First(&perm)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, ErrPermissionNotFound
}
return false, res.Error
}
// find the rolePermission
var rolePermission models.RolePermission
res = c.GetGorm().Where("role_id = ?", role.ID).Where("permission_id = ?", perm.ID).First(&rolePermission)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return false, nil
}
return false, res.Error
}
return true, nil
}
// Revokes a roles's permission
func (a *Authority) RevokeRolePermission(c *core.Context, roleSlug string, permSlug string) error {
// find the role
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return ErrRoleNotFound
}
return res.Error
}
// find the permission
var perm models.Permission
res = c.GetGorm().Where("slug = ?", permSlug).First(&perm)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return ErrPermissionNotFound
}
return res.Error
}
// revoke the permission
rRes := c.GetGorm().Where("role_id = ?", role.ID).Where("permission_id = ?", perm.ID).Delete(models.RolePermission{})
if rRes.Error != nil {
return rRes.Error
}
return nil
}
// Revokes a user's role
func (a *Authority) RevokeUserRole(c *core.Context, userID uint, roleSlug string) error {
// find the role
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if res.Error != nil {
if errors.Is(res.Error, gorm.ErrRecordNotFound) {
return ErrRoleNotFound
}
return res.Error
}
// revoke the role
rRes := c.GetGorm().Where("user_id = ?", userID).Where("role_id = ?", role.ID).Delete(models.UserRole{})
if rRes.Error != nil {
return rRes.Error
}
return nil
}
// Revokes all user's role
func (a *Authority) RevokeAllUserRole(c *core.Context, userID uint) error {
// revoke the role
rRes := c.GetGorm().Where("user_id = ?", userID).Delete(models.UserRole{})
if rRes.Error != nil {
return rRes.Error
}
return nil
}
// Returns all stored roles
func (a *Authority) GetAllRoles(c *core.Context) ([]models.Role, error) {
var roles []models.Role
res := c.GetGorm().Find(&roles)
if res.Error != nil {
return nil, res.Error
}
return roles, nil
}
// Returns all user assigned roles
func (a *Authority) GetUserRoles(c *core.Context, userID uint) ([]models.Role, error) {
var userRoles []models.UserRole
res := c.GetGorm().Where("user_id = ?", userID).Find(&userRoles)
if res.Error != nil {
return nil, res.Error
}
var roleIDs []interface{}
for _, r := range userRoles {
roleIDs = append(roleIDs, r.RoleID)
}
var roles []models.Role
res = c.GetGorm().Where("id IN (?)", roleIDs).Find(&roles)
if res.Error != nil {
return nil, res.Error
}
return roles, nil
}
// Returns all role assigned permissions
func (a *Authority) GetRolePermissions(c *core.Context, roleSlug string) ([]models.Permission, error) {
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).Find(&role)
if res.Error != nil {
return nil, res.Error
}
var rolePerms []models.RolePermission
res = c.GetGorm().Where("role_id = ?", role.ID).Find(&rolePerms)
if res.Error != nil {
return nil, res.Error
}
var permIDs []interface{}
for _, rolePerm := range rolePerms {
permIDs = append(permIDs, rolePerm.PermissionID)
}
var perms []models.Permission
res = c.GetGorm().Where("id IN (?)", permIDs).Find(&perms)
if res.Error != nil {
return nil, res.Error
}
return perms, nil
}
// Returns all stored permissions
func (a *Authority) GetAllPermissions(c *core.Context) ([]models.Permission, error) {
var perms []models.Permission
res := c.GetGorm().Find(&perms)
if res.Error != nil {
return nil, res.Error
}
return perms, nil
}
// Deletes a given role even if it's has assigned permissions
func (a *Authority) DeleteRole(c *core.Context, roleSlug string) error {
// find the role
var role models.Role
res := c.GetGorm().Where("slug = ?", roleSlug).First(&role)
if res.Error != nil {
return res.Error
}
// check if the role is assigned to a user
var ca int64
res = c.GetGorm().Model(models.UserRole{}).Where("role_id = ?", role.ID).Count(&ca)
if res.Error != nil {
return res.Error
}
if ca != 0 {
// role is assigned
return ErrRoleInUse
}
tx := c.GetGorm().Begin()
// revoke the assignment of permissions before deleting the role
dRes := tx.Where("role_id = ?", role.ID).Delete(models.RolePermission{})
if dRes.Error != nil {
tx.Rollback()
return dRes.Error
}
// delete the role
dRes = c.GetGorm().Where("slug = ?", roleSlug).Delete(models.Role{})
if dRes.Error != nil {
tx.Rollback()
return dRes.Error
}
return tx.Commit().Error
}
// Deletes a given permission
func (a *Authority) DeletePermission(c *core.Context, permSlug string) error {
// find the permission
var perm models.Permission
res := c.GetGorm().Where("slug = ?", permSlug).First(&perm)
if res.Error != nil {
return res.Error
}
// check if the permission is assigned to a role
var rolePermission models.RolePermission
res = c.GetGorm().Where("permission_id = ?", perm.ID).First(&rolePermission)
if res.Error != nil && !errors.Is(res.Error, gorm.ErrRecordNotFound) {
return res.Error
}
if res.Error == nil {
return ErrPermissionInUse
}
// delete the permission
dRes := c.GetGorm().Where("slug = ?", permSlug).Delete(models.Permission{})
if dRes.Error != nil {
return dRes.Error
}
return nil
}

View file

@ -8,9 +8,69 @@ package utils
import ( import (
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"log"
"time" "time"
"git.smarteching.com/goffee/core"
"git.smarteching.com/goffee/cup/models"
) )
func CreateSeedData() {
db := core.ResolveGorm()
var hashing = new(core.Hashing)
var role models.Role
// seed user
password := "goffee"
name := "admin"
fullname := "Goffee administrator"
email := "change@me.com"
passwordHashed, _ := hashing.HashPassword(password)
user := models.User{
Name: name,
Fullname: fullname,
Email: email,
Password: passwordHashed,
}
result := db.Create(&user)
if result.Error != nil {
log.Fatal("Can't create seed user in database")
}
// seed roles
roles := []models.Role{
{Name: "Administrator", Slug: "admin"},
{Name: "Authenticated", Slug: "authenticated"},
}
for _, role := range roles {
result = db.Create(&role)
if result.Error != nil {
log.Fatal("Can't create seed role in database")
}
}
// seed permission
permission := models.Permission{Name: "Users administration", Slug: "admin-users"}
result = db.Create(&permission)
if result.Error != nil {
log.Fatal("Can't create seed permission in database")
}
result = db.Where("slug = ?", "admin").First(&role)
if result.Error != nil {
log.Fatal("Can't find user admin in database")
}
result = db.Create(&models.RolePermission{RoleID: role.ID, PermissionID: permission.ID})
if result.Error != nil {
log.Fatal("Can't register permission role in database")
}
result = db.Create(&models.UserRole{UserID: user.ID, RoleID: role.ID})
if result.Error != nil {
log.Fatal("Can't assign role administrator to user in database")
}
}
// generate a hashed string to be used as key for caching auth jwt token // generate a hashed string to be used as key for caching auth jwt token
func CreateAuthTokenHashedCacheKey(userID uint, userAgent string) string { func CreateAuthTokenHashedCacheKey(userID uint, userAgent string) string {
cacheKey := fmt.Sprintf("userid:_%v_useragent:_%v_jwt_token", userID, userAgent) cacheKey := fmt.Sprintf("userid:_%v_useragent:_%v_jwt_token", userID, userAgent)