wip
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
func (u *User) EffectivePermissions(ctx context.Context, scope string) (Permission, error) {
|
||||
if u.ActiveRole == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Load the role and its associated policies using the helper function.
|
||||
role, err := LoadRoleWithPolicies(ctx, u.ActiveRole.ID)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var perm Permission
|
||||
for _, policy := range role.Policies {
|
||||
for pat, p := range policy.Scopes {
|
||||
if MatchScope(pat, scope) {
|
||||
perm |= p
|
||||
}
|
||||
}
|
||||
}
|
||||
return perm, nil
|
||||
}
|
||||
|
||||
func (u *User) HasPermission(ctx context.Context, scope string, requiredPerm Permission) (bool, error) {
|
||||
effective, err := u.EffectivePermissions(ctx, scope)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return (effective & requiredPerm) == requiredPerm, nil
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
"github.com/timetracker/backend/internal/db"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// LoadRoleWithPolicies loads a role with its associated policies from the database.
|
||||
func LoadRoleWithPolicies(ctx context.Context, roleID ulid.ULID) (*Role, error) {
|
||||
var role Role
|
||||
err := db.GetEngine(ctx).Preload("Policies").First(&role, "id = ?", roleID).Error
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("role with ID %s not found", roleID)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to load role: %w", err)
|
||||
}
|
||||
return &role, nil
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package permissions
|
||||
|
||||
import "strings"
|
||||
|
||||
func MatchScope(pattern, scope string) bool {
|
||||
if strings.HasSuffix(pattern, "/*") {
|
||||
prefix := strings.TrimSuffix(pattern, "/*")
|
||||
return strings.HasPrefix(scope, prefix)
|
||||
}
|
||||
return pattern == scope
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package permissions
|
||||
|
||||
type Permission uint64
|
||||
|
||||
const (
|
||||
PermRead Permission = 1 << iota // 1
|
||||
PermWrite // 2
|
||||
PermCreate // 4
|
||||
PermList // 8
|
||||
PermDelete // 16
|
||||
PermModerate // 32
|
||||
PermSuperadmin // 64
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
type Policy struct {
|
||||
ID ulid.ULID `gorm:"primaryKey;type:bytea"`
|
||||
Name string `gorm:"not null"`
|
||||
RoleID ulid.ULID `gorm:"type:bytea"` //Fremdschlüssel
|
||||
Scopes Scopes `gorm:"type:jsonb;not null"` // JSONB-Spalte
|
||||
}
|
||||
|
||||
// Scopes type to handle JSON marshalling
|
||||
type Scopes map[string]Permission
|
||||
|
||||
// Scan scan value into Jsonb, implements sql.Scanner interface
|
||||
func (j *Scopes) Scan(value interface{}) error {
|
||||
bytes, ok := value.([]byte)
|
||||
if !ok {
|
||||
return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
|
||||
}
|
||||
|
||||
var scopes map[string]Permission
|
||||
if err := json.Unmarshal(bytes, &scopes); err != nil {
|
||||
return err
|
||||
}
|
||||
*j = scopes
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value return json value, implement driver.Valuer interface
|
||||
func (j Scopes) Value() (driver.Value, error) {
|
||||
return json.Marshal(j)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
type Role struct {
|
||||
ID ulid.ULID `gorm:"primaryKey;type:bytea"`
|
||||
Name string `gorm:"unique;not null"`
|
||||
Policies []Policy `gorm:"foreignKey:RoleID"`
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package permissions
|
||||
|
||||
import (
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ActiveRole *Role `gorm:"foreignKey:UserID"` // Beziehung zur aktiven Rolle
|
||||
UserID ulid.ULID `gorm:"type:bytea"` //Fremdschlüssel
|
||||
}
|
||||
Reference in New Issue
Block a user