104 lines
2.2 KiB
Go
104 lines
2.2 KiB
Go
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"git.haelnorr.com/h/oslstats/internal/permissions"
|
|
"git.haelnorr.com/h/oslstats/internal/roles"
|
|
"github.com/pkg/errors"
|
|
"github.com/uptrace/bun"
|
|
)
|
|
|
|
type UserRole struct {
|
|
UserID int `bun:",pk"`
|
|
User *User `bun:"rel:belongs-to,join:user_id=id"`
|
|
RoleID int `bun:",pk"`
|
|
Role *Role `bun:"rel:belongs-to,join:role_id=id"`
|
|
}
|
|
|
|
// AssignRole grants a role to a user
|
|
func AssignRole(ctx context.Context, tx bun.Tx, userID, roleID int, audit *AuditMeta) error {
|
|
if userID <= 0 {
|
|
return errors.New("userID must be positive")
|
|
}
|
|
if roleID <= 0 {
|
|
return errors.New("roleID must be positive")
|
|
}
|
|
|
|
userRole := &UserRole{
|
|
UserID: userID,
|
|
RoleID: roleID,
|
|
}
|
|
details := map[string]any{
|
|
"action": "grant",
|
|
"role_id": roleID,
|
|
}
|
|
info := &AuditInfo{
|
|
string(permissions.UsersManageRoles),
|
|
"user",
|
|
userID,
|
|
details,
|
|
}
|
|
err := Insert(tx, userRole).
|
|
ConflictNothing("user_id", "role_id").
|
|
WithAudit(audit, info).
|
|
Exec(ctx)
|
|
if err != nil {
|
|
return errors.Wrap(err, "db.Insert")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// RevokeRole removes a role from a user
|
|
func RevokeRole(ctx context.Context, tx bun.Tx, userID, roleID int, audit *AuditMeta) error {
|
|
if userID <= 0 {
|
|
return errors.New("userID must be positive")
|
|
}
|
|
if roleID <= 0 {
|
|
return errors.New("roleID must be positive")
|
|
}
|
|
|
|
details := map[string]any{
|
|
"action": "revoke",
|
|
"role_id": roleID,
|
|
}
|
|
info := &AuditInfo{
|
|
string(permissions.UsersManageRoles),
|
|
"user",
|
|
userID,
|
|
details,
|
|
}
|
|
err := DeleteItem[UserRole](tx).
|
|
Where("user_id = ?", userID).
|
|
Where("role_id = ?", roleID).
|
|
WithAudit(audit, info).
|
|
Delete(ctx)
|
|
if err != nil {
|
|
return errors.Wrap(err, "DeleteItem")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HasRole checks if a user has a specific role
|
|
func HasRole(ctx context.Context, tx bun.Tx, userID int, roleName roles.Role) (bool, error) {
|
|
if userID <= 0 {
|
|
return false, errors.New("userID must be positive")
|
|
}
|
|
if roleName == "" {
|
|
return false, errors.New("roleName cannot be empty")
|
|
}
|
|
user, err := GetByID[User](tx, userID).
|
|
Relation("Roles").Get(ctx)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "GetByID")
|
|
}
|
|
for _, role := range user.Roles {
|
|
if role.Name == roleName {
|
|
return true, nil
|
|
}
|
|
}
|
|
return false, nil
|
|
}
|