3
0

Refactor RBAC rule cloning route for role

It moves role permission cloning under /system/roles from /system/permissions, since cloning action copies all rules, and it can not be limited per-component and also shifted all respective service methods to role service and removed Rbac rule cloning methods from access-control template.
This commit is contained in:
Vivek Patel
2022-07-04 19:36:17 +05:30
parent 2ffe8a2df0
commit d26ca37fe0
17 changed files with 216 additions and 225 deletions

View File

@@ -33,7 +33,7 @@
###############################################################################
# Allow insecure (invalid, expired TLS/SSL certificates) connections.
#
#
# [IMPORTANT]
# ====
# We strongly recommend keeping this value set to false except for local development or demos.
@@ -191,7 +191,7 @@
###############################################################################
# Password for the web console endpoint. When running in dev environment, password is not required.
#
#
# Corteza intentionally sets default password to random chars to prevent security incidents.
# Type: string
# Default: <no value>
@@ -278,7 +278,7 @@
# Email sending
#
# Configure your local SMTP server or use one of the available providers.
#
#
# These values are copied to settings when the server starts and can be managed from the administration console.
# We recommend you remove these values after they are copied to settings.
# If server detects difference between these options and settings, it shows a warning in the log on server start.
@@ -348,13 +348,13 @@
###############################################################################
# Enables actionlog for compose record create, update, and delete. which is disabled by default.
#
#
# [IMPORTANT]
# ====
# This is temp fix for now, it will be removed completely in future release.
# Once new env var will be introduced for actionlog policy, which will enable more control over action log policies.
# ====
#
#
# Type: bool
# Default: <no value>
# ACTIONLOG_COMPOSE_RECORD_ENABLED=<no value>
@@ -431,7 +431,7 @@
###############################################################################
# Password security allows you to disable constraints to which passwords must conform to.
#
#
# [CAUTION]
# ====
# Disabling password security can be useful for development environments as it removes the need for complex passwords.
@@ -443,7 +443,7 @@
###############################################################################
# Secret used for signing JWT tokens.
#
#
# [IMPORTANT]
# ====
# If secret is not set, system auto-generates one from DB_DSN and HOSTNAME environment variables.
@@ -461,7 +461,7 @@
###############################################################################
# Lifetime of the refresh token. Should be much longer than lifetime of the access token.
#
#
# Refresh tokens are used to exchange expired access tokens with new ones.
# Type: time.Duration
# Default: 72h
@@ -469,7 +469,7 @@
###############################################################################
# Redirect URL to be sent with OAuth2 authentication request to provider
#
#
# `provider` placeholder is replaced with the actual value when used.
# Type: string
# Default: <no value>
@@ -477,7 +477,7 @@
###############################################################################
# Secret used for securing cookies
#
#
# [IMPORTANT]
# ====
# If secret is not set, system auto-generates one from DB_DSN and HOSTNAME environment variables.
@@ -520,21 +520,21 @@
###############################################################################
# Maximum time user is allowed to stay idle when logged in without "remember-me" option and before session is expired.
#
#
# Recomended value is between an hour and a day.
#
#
# [IMPORTANT]
# ====
# This affects only profile (/auth) pages. Using applications (admin, compose, ...) does not prolong the session.
# ====
#
#
# Type: time.Duration
# Default: 24h
# AUTH_SESSION_LIFETIME=24h
###############################################################################
# Duration of the session in /auth lasts when user logs-in with "remember-me" option.
#
#
# If set to 0, "remember-me" option is removed.
# Type: time.Duration
# Default: 8640h
@@ -561,7 +561,7 @@
###############################################################################
# Secret used for securing CSRF protection
#
#
# [IMPORTANT]
# ====
# If secret is not set, system auto-generates one from DB_DSN and HOSTNAME environment variables.
@@ -591,19 +591,19 @@
###############################################################################
# Handle for OAuth2 client used for automatic redirect from /auth/oauth2/go endpoint.
#
#
# This simplifies configuration for OAuth2 flow for Corteza Web applications as it removes
# the need to suply redirection URL and client ID (oauth2/go endpoint does that internally)
#
#
# Type: string
# Default: corteza-webapp
# AUTH_DEFAULT_CLIENT=corteza-webapp
###############################################################################
# Path to js, css, images and template source files
#
#
# When corteza starts, if path exists it tries to load template files from it.
#
#
# When empty path is set (default value), embedded files are used.
# Type: string
# Default: <no value>
@@ -612,7 +612,7 @@
###############################################################################
# When enabled, corteza reloads template before every execution.
# Enable this for debugging or when developing auth templates.
#
#
# Should be disabled in production where templates do not change between server restarts.
# Type: bool
# Default: <no value>
@@ -790,9 +790,9 @@
###############################################################################
# List of compa delimited languages (language tags) to enable.
# In case when an enabled language can not be loaded, error is logged.
#
#
# When loading language configurations (config.xml) from the configured path(s).
#
#
# Type: string
# Default: en
# LOCALE_LANGUAGES=en
@@ -807,7 +807,7 @@
# Name of the query string parameter used to pass the language tag (it overrides Accept-Language header).
# Set it to empty string to disable detection from the query string.
# This parameter is ignored if only one language is enabled
#
#
# Type: string
# Default: lng
# LOCALE_QUERY_STRING_PARAM=lng
@@ -838,9 +838,9 @@
###############################################################################
# Disables JSON format for logging and enables more human-readable output with colors.
#
#
# Disable for production.
#
#
# Type: bool
# Default: <no value>
# LOG_DEBUG=<no value>
@@ -848,11 +848,11 @@
###############################################################################
# Minimum logging level. If set to "warn",
# Levels warn, error, dpanic panic and fatal will be logged.
#
#
# Recommended value for production: warn
#
#
# Possible values: debug, info, warn, error, dpanic, panic, fatal
#
#
# Type: string
# Default: warn
# LOG_LEVEL=warn
@@ -860,25 +860,25 @@
###############################################################################
# Log filtering rules by level and name (log-level:log-namespace).
# Please note that level (LOG_LEVEL) is applied before filter and it affects the final output!
#
#
# Leave unset for production.
#
#
# Example:
# `warn+:* *:auth,workflow.*`
# Log warnings, errors, panic, fatals. Everything from auth and workflow is logged.
#
#
#
#
# See more examples and documentation here: https://github.com/moul/zapfilter
#
#
# Type: string
# Default: <no value>
# LOG_FILTER=<no value>
###############################################################################
# Set to true to see where the logging was called from.
#
#
# Disable for production.
#
#
# Type: bool
# Default: <no value>
# LOG_INCLUDE_CALLER=<no value>
@@ -886,9 +886,9 @@
###############################################################################
# Include stack-trace when logging at a specified level or below.
# Disable for production.
#
#
# Possible values: debug, info, warn, error, dpanic, panic, fatal
#
#
# Type: string
# Default: dpanic
# LOG_STACKTRACE_LEVEL=dpanic
@@ -1000,11 +1000,11 @@
#
# Provisioning allows you to configure a {PRODUCT_NAME} instance when deployed.
# It occurs automatically after the {PRODUCT_NAME} server starts.
#
#
# [IMPORTANT]
# ====
# We recommend you to keep provisioning enabled as it simplifies version updates by updating the database and updating settings.
#
#
# If you're doing local development or some debugging, you can disable this.
# ====
#
@@ -1041,7 +1041,7 @@
# ====
# These parameters help in the development and testing process.
# When you are deploying to production, these should be disabled to improve performance and reduce storage usage.
#
#
# You should configure external services such as Sentry or ELK to keep track of logs and error reports.
# ====
#
@@ -1141,7 +1141,7 @@
# Delay system startup
#
# You can configure these options to defer API execution until another external (HTTP) service is up and running.
#
#
# [ TIP ]
# ====
# Delaying API execution can come in handy in complex setups where execution order is important.
@@ -1165,7 +1165,7 @@
###############################################################################
# Space delimited list of hosts and/or URLs to probe.
# Host format: `host` or `host:443` (port will default to 80).
#
#
# [NOTE]
# ====
# Services are probed in parallel.

View File

@@ -26,7 +26,6 @@ type (
Evaluate(rbac.Session, string, rbac.Resource) rbac.Evaluated
Grant(context.Context, ...*rbac.Rule) error
FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet)
CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error
}
accessControl struct {
@@ -261,17 +260,6 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) (
return svc.rbac.FindRulesByRoleID(roleID), nil
}
// CloneRulesByRoleID clone all rules of a Role S to a specific Role T
//
// This function is auto-generated
func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error {
if !svc.CanGrant(ctx) {
return AccessControlErrNotAllowedToSetPermissions()
}
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
}
// CanReadWorkflow checks if current user can read workflow
//
// This function is auto-generated

View File

@@ -25,7 +25,6 @@ type (
Evaluate(rbac.Session, string, rbac.Resource) rbac.Evaluated
Grant(context.Context, ...*rbac.Rule) error
FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet)
CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error
}
accessControl struct {
@@ -206,17 +205,6 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) (
return svc.rbac.FindRulesByRoleID(roleID), nil
}
// CloneRulesByRoleID clone all rules of a Role S to a specific Role T
//
// This function is auto-generated
func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error {
if !svc.CanGrant(ctx) {
return AccessControlErrNotAllowedToSetPermissions()
}
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
}
{{- range .operations }}
// {{ .checkFuncName }} checks if current user can {{ lower .description }}
//

View File

@@ -23,11 +23,9 @@ type (
}
rbacService interface {
Can(rbac.Session, string, rbac.Resource) bool
Evaluate(rbac.Session, string, rbac.Resource) rbac.Evaluated
Grant(context.Context, ...*rbac.Rule) error
FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet)
CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error
}
accessControl struct {
@@ -46,14 +44,14 @@ func AccessControl(rms roleMemberSearcher) *accessControl {
}
}
func (svc *accessControl) can(ctx context.Context, op string, res rbac.Resource) bool {
return svc.rbac.Can(rbac.ContextToSession(ctx), op, res)
func (svc accessControl) can(ctx context.Context, op string, res rbac.Resource) bool {
return svc.rbac.Evaluate(rbac.ContextToSession(ctx), op, res).Can
}
// Effective returns a list of effective permissions for all given resource
//
// This function is auto-generated
func (svc *accessControl) Effective(ctx context.Context, rr ...rbac.Resource) (ee rbac.EffectiveSet) {
func (svc accessControl) Effective(ctx context.Context, rr ...rbac.Resource) (ee rbac.EffectiveSet) {
for _, res := range rr {
r := res.RbacResource()
for op := range rbacResourceOperations(r) {
@@ -67,7 +65,7 @@ func (svc *accessControl) Effective(ctx context.Context, rr ...rbac.Resource) (e
// Evaluate returns a list of permissions evaluated for the given user/roles combo
//
// This function is auto-generated
func (svc *accessControl) Evaluate(ctx context.Context, userID uint64, roles []uint64, rr ...string) (ee rbac.EvaluatedSet, err error) {
func (svc accessControl) Evaluate(ctx context.Context, userID uint64, roles []uint64, rr ...string) (ee rbac.EvaluatedSet, err error) {
// Reusing the grant permission since this is who the feature is for
if !svc.CanGrant(ctx) {
// @todo should be altered to check grant permissions PER resource
@@ -123,7 +121,7 @@ func (svc *accessControl) Evaluate(ctx context.Context, userID uint64, roles []u
// Resources returns list of resources
//
// This function is auto-generated
func (svc *accessControl) Resources() []rbac.Resource {
func (svc accessControl) Resources() []rbac.Resource {
return []rbac.Resource{
rbac.NewResource(types.ChartRbacResource(0, 0)),
rbac.NewResource(types.ModuleRbacResource(0, 0)),
@@ -138,7 +136,7 @@ func (svc *accessControl) Resources() []rbac.Resource {
// List returns list of operations on all resources
//
// This function is auto-generated
func (svc *accessControl) List() (out []map[string]string) {
func (svc accessControl) List() (out []map[string]string) {
def := []map[string]string{
{
"type": types.ChartResourceType,
@@ -372,17 +370,6 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) (
return svc.rbac.FindRulesByRoleID(roleID), nil
}
// CloneRulesByRoleID clone all rules of a Role S to a specific Role T
//
// This function is auto-generated
func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error {
if !svc.CanGrant(ctx) {
return AccessControlErrNotAllowedToSetPermissions()
}
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
}
// CanReadChart checks if current user can read
//
// This function is auto-generated

View File

@@ -26,7 +26,6 @@ type (
Evaluate(rbac.Session, string, rbac.Resource) rbac.Evaluated
Grant(context.Context, ...*rbac.Rule) error
FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet)
CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error
}
accessControl struct {
@@ -248,17 +247,6 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) (
return svc.rbac.FindRulesByRoleID(roleID), nil
}
// CloneRulesByRoleID clone all rules of a Role S to a specific Role T
//
// This function is auto-generated
func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error {
if !svc.CanGrant(ctx) {
return AccessControlErrNotAllowedToSetPermissions()
}
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
}
// CanManageNode checks if current user can manage federation node
//
// This function is auto-generated

View File

@@ -396,6 +396,21 @@ endpoints:
type: map[string]interface{}
parser: parseMapStringInterface
title: Arguments to pass to the script
- name: cloneRules
path: "/{roleID}/rules/clone"
method: POST
title: Clone permission settings to a role
parameters:
path:
- name: roleID
type: uint64
required: true
title: Role ID
get:
- name: cloneToRoleID
type: "[]string"
required: true
title: Clone set of rules to roleID
- title: Users
path: "/users"
entrypoint: user
@@ -1272,21 +1287,6 @@ endpoints:
type: rbac.RuleSet
required: true
title: List of permission rules to set
- name: clone
path: "/{roleID}/rules/clone"
method: POST
title: Clone permission settings to a role
parameters:
path:
- name: roleID
type: uint64
required: true
title: Role ID
get:
- name: cloneToRoleID
type: "[]string"
required: true
title: Clone set of rules to roleID
- title: Reminders
entrypoint: reminder
path: "/reminder"

View File

@@ -25,7 +25,6 @@ type (
Read(context.Context, *request.PermissionsRead) (interface{}, error)
Delete(context.Context, *request.PermissionsDelete) (interface{}, error)
Update(context.Context, *request.PermissionsUpdate) (interface{}, error)
Clone(context.Context, *request.PermissionsClone) (interface{}, error)
}
// HTTP API interface
@@ -36,7 +35,6 @@ type (
Read func(http.ResponseWriter, *http.Request)
Delete func(http.ResponseWriter, *http.Request)
Update func(http.ResponseWriter, *http.Request)
Clone func(http.ResponseWriter, *http.Request)
}
)
@@ -136,22 +134,6 @@ func NewPermissions(h PermissionsAPI) *Permissions {
return
}
api.Send(w, r, value)
},
Clone: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewPermissionsClone()
if err := params.Fill(r); err != nil {
api.Send(w, r, err)
return
}
value, err := h.Clone(r.Context(), params)
if err != nil {
api.Send(w, r, err)
return
}
api.Send(w, r, value)
},
}
@@ -166,6 +148,5 @@ func (h Permissions) MountRoutes(r chi.Router, middlewares ...func(http.Handler)
r.Get("/permissions/{roleID}/rules", h.Read)
r.Delete("/permissions/{roleID}/rules", h.Delete)
r.Patch("/permissions/{roleID}/rules", h.Update)
r.Post("/permissions/{roleID}/rules/clone", h.Clone)
})
}

View File

@@ -33,6 +33,7 @@ type (
MemberAdd(context.Context, *request.RoleMemberAdd) (interface{}, error)
MemberRemove(context.Context, *request.RoleMemberRemove) (interface{}, error)
TriggerScript(context.Context, *request.RoleTriggerScript) (interface{}, error)
CloneRules(context.Context, *request.RoleCloneRules) (interface{}, error)
}
// HTTP API interface
@@ -51,6 +52,7 @@ type (
MemberAdd func(http.ResponseWriter, *http.Request)
MemberRemove func(http.ResponseWriter, *http.Request)
TriggerScript func(http.ResponseWriter, *http.Request)
CloneRules func(http.ResponseWriter, *http.Request)
}
)
@@ -278,6 +280,22 @@ func NewRole(h RoleAPI) *Role {
return
}
api.Send(w, r, value)
},
CloneRules: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewRoleCloneRules()
if err := params.Fill(r); err != nil {
api.Send(w, r, err)
return
}
value, err := h.CloneRules(r.Context(), params)
if err != nil {
api.Send(w, r, err)
return
}
api.Send(w, r, value)
},
}
@@ -300,5 +318,6 @@ func (h Role) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http.H
r.Post("/roles/{roleID}/member/{userID}", h.MemberAdd)
r.Delete("/roles/{roleID}/member/{userID}", h.MemberRemove)
r.Post("/roles/{roleID}/trigger", h.TriggerScript)
r.Post("/roles/{roleID}/rules/clone", h.CloneRules)
})
}

View File

@@ -4,7 +4,6 @@ import (
"context"
"github.com/cortezaproject/corteza-server/pkg/api"
"github.com/cortezaproject/corteza-server/pkg/payload"
"github.com/cortezaproject/corteza-server/pkg/rbac"
"github.com/cortezaproject/corteza-server/system/rest/request"
"github.com/cortezaproject/corteza-server/system/service"
@@ -21,7 +20,6 @@ type (
Evaluate(ctx context.Context, user uint64, roles []uint64, rr ...string) (ee rbac.EvaluatedSet, err error)
List() []map[string]string
FindRulesByRoleID(context.Context, uint64) (rbac.RuleSet, error)
CloneRulesByRoleID(ctx context.Context, roleID uint64, toRoleID ...uint64) error
Grant(ctx context.Context, rr ...*rbac.Rule) error
}
)
@@ -69,11 +67,3 @@ func (ctrl Permissions) Update(ctx context.Context, r *request.PermissionsUpdate
return api.OK(), ctrl.ac.Grant(ctx, r.Rules...)
}
// Clone all RBAC rules on ALL components (not just system)
//
// @todo needs to be moved under roles
func (ctrl Permissions) Clone(ctx context.Context, r *request.PermissionsClone) (interface{}, error) {
// Clone rules from role S to role T
return api.OK(), ctrl.ac.CloneRulesByRoleID(ctx, r.RoleID, payload.ParseUint64s(r.CloneToRoleID)...)
}

View File

@@ -86,18 +86,6 @@ type (
// List of permission rules to set
Rules rbac.RuleSet
}
PermissionsClone struct {
// RoleID PATH parameter
//
// Role ID
RoleID uint64 `json:",string"`
// CloneToRoleID GET parameter
//
// Clone set of rules to roleID
CloneToRoleID []string
}
)
// NewPermissionsList request
@@ -366,61 +354,3 @@ func (r *PermissionsUpdate) Fill(req *http.Request) (err error) {
return err
}
// NewPermissionsClone request
func NewPermissionsClone() *PermissionsClone {
return &PermissionsClone{}
}
// Auditable returns all auditable/loggable parameters
func (r PermissionsClone) Auditable() map[string]interface{} {
return map[string]interface{}{
"roleID": r.RoleID,
"cloneToRoleID": r.CloneToRoleID,
}
}
// Auditable returns all auditable/loggable parameters
func (r PermissionsClone) GetRoleID() uint64 {
return r.RoleID
}
// Auditable returns all auditable/loggable parameters
func (r PermissionsClone) GetCloneToRoleID() []string {
return r.CloneToRoleID
}
// Fill processes request and fills internal variables
func (r *PermissionsClone) Fill(req *http.Request) (err error) {
{
// GET params
tmp := req.URL.Query()
if val, ok := tmp["cloneToRoleID[]"]; ok {
r.CloneToRoleID, err = val, nil
if err != nil {
return err
}
} else if val, ok := tmp["cloneToRoleID"]; ok {
r.CloneToRoleID, err = val, nil
if err != nil {
return err
}
}
}
{
var val string
// path params
val = chi.URLParam(req, "roleID")
r.RoleID, err = payload.ParseUint64(val), nil
if err != nil {
return err
}
}
return err
}

View File

@@ -242,6 +242,18 @@ type (
// Arguments to pass to the script
Args map[string]interface{}
}
RoleCloneRules struct {
// RoleID PATH parameter
//
// Role ID
RoleID uint64 `json:",string"`
// CloneToRoleID GET parameter
//
// Clone set of rules to roleID
CloneToRoleID []string
}
)
// NewRoleList request
@@ -1284,3 +1296,61 @@ func (r *RoleTriggerScript) Fill(req *http.Request) (err error) {
return err
}
// NewRoleCloneRules request
func NewRoleCloneRules() *RoleCloneRules {
return &RoleCloneRules{}
}
// Auditable returns all auditable/loggable parameters
func (r RoleCloneRules) Auditable() map[string]interface{} {
return map[string]interface{}{
"roleID": r.RoleID,
"cloneToRoleID": r.CloneToRoleID,
}
}
// Auditable returns all auditable/loggable parameters
func (r RoleCloneRules) GetRoleID() uint64 {
return r.RoleID
}
// Auditable returns all auditable/loggable parameters
func (r RoleCloneRules) GetCloneToRoleID() []string {
return r.CloneToRoleID
}
// Fill processes request and fills internal variables
func (r *RoleCloneRules) Fill(req *http.Request) (err error) {
{
// GET params
tmp := req.URL.Query()
if val, ok := tmp["cloneToRoleID[]"]; ok {
r.CloneToRoleID, err = val, nil
if err != nil {
return err
}
} else if val, ok := tmp["cloneToRoleID"]; ok {
r.CloneToRoleID, err = val, nil
if err != nil {
return err
}
}
}
{
var val string
// path params
val = chi.URLParam(req, "roleID")
r.RoleID, err = payload.ParseUint64(val), nil
if err != nil {
return err
}
}
return err
}

View File

@@ -169,6 +169,11 @@ func (ctrl Role) Unarchive(ctx context.Context, r *request.RoleUnarchive) (inter
return api.OK(), ctrl.role.Unarchive(ctx, r.RoleID)
}
func (ctrl Role) CloneRules(ctx context.Context, r *request.RoleCloneRules) (interface{}, error) {
// Clone rules from role S to role T
return api.OK(), ctrl.role.CloneRules(ctx, r.RoleID, payload.ParseUint64s(r.CloneToRoleID)...)
}
// deprecated
func (ctrl Role) Merge(ctx context.Context, r *request.RoleMerge) (interface{}, error) {
return api.OK(), nil

View File

@@ -26,7 +26,6 @@ type (
Evaluate(rbac.Session, string, rbac.Resource) rbac.Evaluated
Grant(context.Context, ...*rbac.Rule) error
FindRulesByRoleID(roleID uint64) (rr rbac.RuleSet)
CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error
}
accessControl struct {
@@ -578,17 +577,6 @@ func (svc accessControl) FindRulesByRoleID(ctx context.Context, roleID uint64) (
return svc.rbac.FindRulesByRoleID(roleID), nil
}
// CloneRulesByRoleID clone all rules of a Role S to a specific Role T
//
// This function is auto-generated
func (svc accessControl) CloneRulesByRoleID(ctx context.Context, fromRoleID uint64, toRoleID ...uint64) error {
if !svc.CanGrant(ctx) {
return AccessControlErrNotAllowedToSetPermissions()
}
return svc.rbac.CloneRulesByRoleID(ctx, fromRoleID, toRoleID...)
}
// CanReadApplication checks if current user can read application
//
// This function is auto-generated

View File

@@ -28,6 +28,7 @@ type (
ac roleAccessController
eventbus eventDispatcher
rbac rbacRuleService
user UserService
auth roleAuth
@@ -42,6 +43,8 @@ type (
}
roleAccessController interface {
CanGrant(context.Context) bool
CanSearchRoles(context.Context) bool
CanCreateRole(context.Context) bool
CanReadRole(context.Context, *types.Role) bool
@@ -67,6 +70,7 @@ type (
Unarchive(ctx context.Context, ID uint64) error
Delete(ctx context.Context, ID uint64) error
Undelete(ctx context.Context, ID uint64) error
CloneRules(ctx context.Context, ID uint64, cloneToRoleID ...uint64) error
Membership(ctx context.Context, userID uint64) (types.RoleMemberSet, error)
MemberList(ctx context.Context, roleID uint64) (types.RoleMemberSet, error)
@@ -82,15 +86,20 @@ type (
UpdateRoles(rr ...*rbac.Role)
}
rbacRuleService interface {
CloneRulesByRoleID(ctx context.Context, roleID uint64, toRoleID ...uint64) error
}
roleAuth interface {
RemoveAccessTokens(context.Context, *types.User) error
}
)
func Role() *role {
func Role(rbac rbacRuleService) *role {
return &role{
ac: DefaultAccessControl,
eventbus: eventbus.Service(),
rbac: rbac,
actionlog: DefaultActionlog,
@@ -604,6 +613,14 @@ func (svc role) Unarchive(ctx context.Context, roleID uint64) (err error) {
return svc.recordAction(ctx, raProps, RoleActionUnarchive, err)
}
func (svc role) CloneRules(ctx context.Context, roleID uint64, cloneToRoleID ...uint64) (err error) {
if !svc.ac.CanGrant(ctx) {
return RoleErrNotAllowedToCloneRules()
}
return svc.rbac.CloneRulesByRoleID(ctx, roleID, cloneToRoleID...)
}
func (svc role) Membership(ctx context.Context, userID uint64) (types.RoleMemberSet, error) {
mm, _, err := store.SearchRoleMembers(ctx, svc.store, types.RoleMemberFilter{UserID: userID})
return mm, err

View File

@@ -1039,6 +1039,42 @@ func RoleErrNotAllowedToUnarchive(mm ...*roleActionProps) *errors.Error {
return e
}
// RoleErrNotAllowedToCloneRules returns "system:role.notAllowedToCloneRules" as *errors.Error
//
//
// This function is auto-generated.
//
func RoleErrNotAllowedToCloneRules(mm ...*roleActionProps) *errors.Error {
var p = &roleActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to clone rules of this role", nil),
errors.Meta("type", "notAllowedToCloneRules"),
errors.Meta("resource", "system:role"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(roleLogMetaKey{}, "failed to clone rules of {{role.handle}}; insufficient permissions"),
errors.Meta(rolePropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "system"),
errors.Meta(locale.ErrorMetaKey{}, "role.errors.notAllowedToCloneRules"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// RoleErrNotAllowedToManageMembers returns "system:role.notAllowedToManageMembers" as *errors.Error
//
//

View File

@@ -120,6 +120,10 @@ errors:
message: "not allowed to unarchive this role"
log: "failed to unarchive {{role.handle}}; insufficient permissions"
- error: notAllowedToCloneRules
message: "not allowed to clone rules of this role"
log: "failed to clone rules of {{role.handle}}; insufficient permissions"
- error: notAllowedToManageMembers
message: "not allowed to manage role members"
log: "failed to manage {{role.handle}} members; insufficient permissions"

View File

@@ -202,7 +202,7 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, ws websock
DefaultAuthClient = AuthClient(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service(), c.Auth)
DefaultUser = User(UserOptions{LimitUsers: c.Limit.SystemUsers})
DefaultReport = Report(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service())
DefaultRole = Role()
DefaultRole = Role(rbac.Global())
DefaultApplication = Application(DefaultStore, DefaultAccessControl, DefaultActionlog, eventbus.Service())
DefaultReminder = Reminder(ctx, DefaultLogger.Named("reminder"), ws)
DefaultSink = Sink()