Class: Parse::Role
- Inherits:
-
Object
- Object
- Object
- Parse::Role
- Defined in:
- lib/parse/model/classes/role.rb,
lib/parse/stack/generators/templates/model_role.rb
Overview
This class represents the data and columns contained in the standard Parse _Role collection.
Roles allow the an application to group a set of User records with the same set of
permissions, so that specific records in the database can have ACLs related to a role
than trying to add all the users in a group.
The default schema for Role is as follows:
class Parse::Role < Parse::Object
# See Parse::Object for inherited properties...
property :name
# A role may have child roles.
has_many :roles, through: :relation
# The set of users who belong to this role.
has_many :users, through: :relation
end
Constant Summary collapse
- MONGO_AVAILABILITY_ERROR_NAMES =
Names of Mongo driver errors that mean "the server is momentarily unreachable", for which falling back to the Parse Server walk is right.
Names rather than classes, resolved on first use rather than at load time, because the driver is required lazily (
Parse::MongoDB.require_gem!) andMongo::Errordoes not exist when this file loads.The previous check tested
Mongo::Error::ConnectionFailure, which does NOT exist in the locked 2.25.0 driver, sodefined?was always false and the fallback never fired on a real error. The tests manufactured the constant themselves, which is how a guard can be green and dead at the same time. Real availability errors propagated instead of degrading.ConnectionFailureis kept for older drivers that do define it. Deliberately narrow otherwise:ExecutionTimeout,DeniedOperator, andCLPScope::Deniedare attack signals or policy denials and must keep propagating rather than silently downgrading to the slow path. %w[ ConnectionFailure ConnectionUnavailable ConnectionPerished ConnectionCheckOutTimeout SocketError SocketTimeoutError NoServerAvailable ].freeze
Instance Attribute Summary collapse
-
#name ⇒ String
The name of this role.
Class Method Summary collapse
-
.all_for_user(user, max_depth: 10, master: false, as: nil, client: nil, strict: false) ⇒ Set<String>
Return the transitive upward closure of role names a user inherits permissions from.
-
.all_names ⇒ Array<String>
Get all role names in the system.
-
.exists?(role_name) ⇒ Boolean
Check if a role with the given name exists.
- .expand_inheritance_upward(starting_roles, max_depth: 10, client: nil, strict: false) ⇒ Object
-
.find_by_name(role_name) ⇒ Parse::Role?
Find a role by its name.
-
.find_or_create(role_name, acl: nil) ⇒ Parse::Role
Find or create a role by name.
-
.mongo_availability_error?(error) ⇒ Boolean
Whether
errormeans the server was unreachable. -
.mongo_availability_errors ⇒ Array<Class>
The subset of MONGO_AVAILABILITY_ERROR_NAMES this driver actually defines.
- .role_query_all(constraints, client: nil) ⇒ Object
Instance Method Summary collapse
-
#access_decision(object, operation, client: nil, authenticated: nil, max_role_depth: 10) ⇒ Parse::Access::Decision
Inspect one effective object permission for a hypothetical authenticated member of this role.
-
#access_decisions(object, client: nil, authenticated: nil, max_role_depth: 10) ⇒ Hash<Symbol, Parse::Access::Decision>
Inspect read, write, and delete while sharing one parent-role lookup.
-
#add_child_role(role) ⇒ self
Add a child role to this role's hierarchy.
-
#add_child_roles(*role_list) ⇒ self
Add multiple child roles to this role's hierarchy.
-
#add_user(user) ⇒ self
Add a single user to this role.
-
#add_users(*user_list) ⇒ self
Add multiple users to this role.
-
#all_child_roles(max_depth: 10, visited: Set.new) ⇒ Array<Parse::Role>
Get all child roles recursively.
-
#all_parent_role_names(max_depth: 10, client: nil, strict: false) ⇒ Set<String>
Get the set of role names whose presence in a
_rpermarray grants access to this role's members. -
#all_users(max_depth: 10, visited: Set.new, master: false, as: nil, client: nil) ⇒ Array<Parse::User>
Get all users belonging to this role, including users from child roles recursively.
-
#can_delete?(object, **options) ⇒ Boolean
Return whether the role-derived policy definitively grants delete access.
-
#can_read?(object, **options) ⇒ Boolean
Return whether the role-derived policy definitively grants read access.
-
#can_write?(object, **options) ⇒ Boolean
Return whether the role-derived policy definitively grants update access.
-
#child_roles_count ⇒ Integer
Get the count of direct child roles.
-
#grant_capabilities_to(grantee) ⇒ self
Grant this role's capabilities to the given role's users.
-
#grant_capabilities_to!(grantee) ⇒ self
Auto-saving variant of #grant_capabilities_to.
-
#has_child_role?(role) ⇒ Boolean
Check if a role is a direct child of this role.
-
#has_user?(user) ⇒ Boolean
Check if a user belongs to this role (direct membership only).
-
#inherits_capabilities_from(source) ⇒ Parse::Role
Inverse spelling of #grant_capabilities_to: "this role's users inherit
source's capabilities". -
#inherits_capabilities_from!(source) ⇒ self
Auto-saving variant of #inherits_capabilities_from.
-
#remove_child_role(role) ⇒ self
Remove a child role from this role's hierarchy.
-
#remove_child_roles(*role_list) ⇒ self
Remove multiple child roles from this role's hierarchy.
-
#remove_user(user) ⇒ self
Remove a single user from this role.
-
#remove_users(*user_list) ⇒ self
Remove multiple users from this role.
-
#roles ⇒ RelationCollectionProxy<Role>
This attribute is mapped as a
has_manyParse relation association with the Role class, as roles can be associated with multiple child roles to support role inheritance. -
#total_users_count ⇒ Integer
Get the total count of users including child roles.
-
#users ⇒ RelationCollectionProxy<User>
This attribute is mapped as a
has_manyParse relation association with the User class. -
#users_count ⇒ Integer
Get the count of direct users in this role.
Instance Attribute Details
#name ⇒ String
Returns the name of this role.
54 |
# File 'lib/parse/model/classes/role.rb', line 54 property :name |
Class Method Details
.all_for_user(user, max_depth: 10, master: false, as: nil, client: nil, strict: false) ⇒ Set<String>
When neither master: nor as: is supplied, the
mongo-direct fast path is skipped; the method falls
through to the Parse-Server walk
(Parse::Role.all(users: user_pointer)) which goes through
the default Parse::Client. This preserves backward
compatibility for the many SDK-internal call sites that
compose ACL scopes (acl_scope, atlas_search session,
query/constraints) — none of those have a caller scope to
forward. The fast path is opt-in for performance-conscious
callers that can supply explicit authorization.
Return the transitive upward closure of role names a user inherits permissions from.
Parse Server _Role inheritance: when role X holds role Y
in its roles relation, users of Y inherit X's
permissions. So given a user U, the permission set is built
by:
1. Querying for every role `D` where `U` is a direct member
(`_Role.users` contains `U`).
2. For each direct role `D`, walking upward to every role
`P` that lists `D` in its `roles` relation. Repeat until
no new parents are found.
This is the correct primitive for building _rperm predicates
(e.g., ACLReadableByConstraint, ACLWritableByConstraint,
and the Atlas Search ACL $match injection). The legacy walk
via #all_child_roles on the user's direct roles traverses
the wrong direction and over-grants — it returns roles whose
users include the input user through inheritance, not the
roles the input user inherits permissions from.
Cycle-safe: a visited-id set guards against pathological
_Role.roles cycles (e.g. A→B→A).
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/parse/model/classes/role.rb', line 213 def all_for_user(user, max_depth: 10, master: false, as: nil, client: nil, strict: false) names = Set.new return names if user.nil? || max_depth <= 0 user_pointer = role_lookup_pointer_for(user) return names if user_pointer.nil? # The fast path is opt-in. When neither `master:` nor `as:` is # supplied, skip it entirely — the underlying mongo helper # would raise ArgumentError, and we don't want to surprise # the many backward-compat call sites (acl_scope.resolve_for_user, # atlas_search Session.role_names_for, query/constraints' ACL # constraint building, agent default-scope composition) that # have no scope to forward. if master == true || !as.nil? fast_path_result = all_for_user_mongo_fast_path( user_pointer.id, max_depth, master: master, as: as, client: client, ) if fast_path_result.is_a?(Set) ActiveSupport::Notifications.instrument( "parse.role.expand", direction: :forward, target_id: user_pointer.id, depth: max_depth, source: :mongo_direct, result_count: fast_path_result.size, ) return fast_path_result end end if as # FAIL CLOSED. The slow path below reads `_Role` through the REST # client, which in a master-keyed process answers with every role # regardless of what `as:` may see. Silently falling back would turn # a scoped traversal into a master-keyed one and hand the caller a # closure they were never entitled to. A caller who wants the master # answer has to ask for it. raise Parse::MongoDB::NotEnabled, "Parse::Role.all_for_user: `as:` requires the mongo-direct role graph, " \ "which is unavailable. Refusing to fall back to the Parse Server walk, " \ "which would run under the client's own credentials rather than the " \ "requested scope. Configure Parse::MongoDB, or pass `master: true` to " \ "take the unscoped answer deliberately." end begin direct_roles = role_query_all({ users: user_pointer }, client: client) rescue StandardError raise if strict return names end result = ( direct_roles, max_depth: max_depth, client: client, strict: strict, ) ActiveSupport::Notifications.instrument( "parse.role.expand", direction: :forward, target_id: user_pointer.id, depth: max_depth, source: :parse_server, result_count: result.size, ) result end |
.all_names ⇒ Array<String>
Get all role names in the system.
144 145 146 |
# File 'lib/parse/model/classes/role.rb', line 144 def all_names query.results.map(&:name) end |
.exists?(role_name) ⇒ Boolean
Check if a role with the given name exists.
151 152 153 |
# File 'lib/parse/model/classes/role.rb', line 151 def exists?(role_name) query(name: role_name).count > 0 end |
.expand_inheritance_upward(starting_roles, max_depth: 10, client: nil, strict: false) ⇒ Object
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 |
# File 'lib/parse/model/classes/role.rb', line 368 def (starting_roles, max_depth: 10, client: nil, strict: false) names = Set.new visited_ids = Set.new frontier = [] Array(starting_roles).each do |role| next if role.nil? || role.id.nil? next if visited_ids.include?(role.id) visited_ids << role.id names << role.name if role.respond_to?(:name) && role.name.present? frontier << role end depth = 0 while frontier.any? && depth < max_depth next_frontier = [] frontier.each do |role| next if role.nil? || role.id.nil? begin parents = role_query_all({ roles: role }, client: client) rescue StandardError raise if strict next end parents.each do |parent| next if parent.nil? || parent.id.nil? next if visited_ids.include?(parent.id) visited_ids << parent.id names << parent.name if parent.respond_to?(:name) && parent.name.present? next_frontier << parent end end frontier = next_frontier depth += 1 end names end |
.find_by_name(role_name) ⇒ Parse::Role?
Find a role by its name.
122 123 124 |
# File 'lib/parse/model/classes/role.rb', line 122 def find_by_name(role_name) query(name: role_name).first end |
.find_or_create(role_name, acl: nil) ⇒ Parse::Role
Find or create a role by name.
132 133 134 135 136 137 138 139 140 |
# File 'lib/parse/model/classes/role.rb', line 132 def find_or_create(role_name, acl: nil) role = find_by_name(role_name) return role if role role = new(name: role_name) role.acl = acl if acl role.save role end |
.mongo_availability_error?(error) ⇒ Boolean
Returns whether error means the server was unreachable.
102 103 104 |
# File 'lib/parse/model/classes/role.rb', line 102 def self.mongo_availability_error?(error) mongo_availability_errors.any? { |klass| error.is_a?(klass) } end |
.mongo_availability_errors ⇒ Array<Class>
Returns the subset of MONGO_AVAILABILITY_ERROR_NAMES this driver actually defines.
94 95 96 97 98 99 |
# File 'lib/parse/model/classes/role.rb', line 94 def self.mongo_availability_errors return [] unless defined?(::Mongo::Error) @mongo_availability_errors ||= MONGO_AVAILABILITY_ERROR_NAMES.filter_map do |name| ::Mongo::Error.const_get(name) if ::Mongo::Error.const_defined?(name) end.freeze end |
.role_query_all(constraints, client: nil) ⇒ Object
353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/parse/model/classes/role.rb', line 353 def role_query_all(constraints, client: nil) # No explicit client means the historical path, unchanged. This is not # only for compatibility: `Parse::Role.all` is what callers and tests # observe and stub, and routing around it when nothing asked us to # would change behavior for every existing caller to fix a problem # none of them have. # Double-splat, not a positional Hash: `Parse::Role.all` takes # keywords, and Ruby 3 does not convert one to the other. return Parse::Role.all(**constraints) if client.nil? query = Parse::Role.query(constraints) query.client = client query.results end |
Instance Method Details
#access_decision(object, operation, client: nil, authenticated: nil, max_role_depth: 10) ⇒ Parse::Access::Decision
Inspect one effective object permission for a hypothetical authenticated
member of this role. User-specific, pointer-specific, and _User self
rules remain unknown because a role does not identify a concrete member.
809 810 811 812 813 814 815 816 817 818 819 820 |
# File 'lib/parse/model/classes/role.rb', line 809 def access_decision(object, operation, client: nil, authenticated: nil, max_role_depth: 10) require_relative "../../access" unless defined?(Parse::Access) Parse::Access.check( principal: self, object: object, operation: operation, client: client, authenticated: authenticated, max_role_depth: max_role_depth, ) end |
#access_decisions(object, client: nil, authenticated: nil, max_role_depth: 10) ⇒ Hash<Symbol, Parse::Access::Decision>
Inspect read, write, and delete while sharing one parent-role lookup.
824 825 826 827 828 829 830 831 832 833 |
# File 'lib/parse/model/classes/role.rb', line 824 def access_decisions(object, client: nil, authenticated: nil, max_role_depth: 10) require_relative "../../access" unless defined?(Parse::Access) Parse::Access.check_all( principal: self, object: object, client: client, authenticated: authenticated, max_role_depth: max_role_depth, ) end |
#add_child_role(role) ⇒ self
Add a child role to this role's hierarchy.
The method name is misleading — prefer #grant_capabilities_to!
or #inherits_capabilities_from!. add_child_role mutates the
receiver's roles relation; per Parse Server semantics, putting
role Y in role X's roles relation grants X's capabilities to
users-of-Y. The "child" terminology has the inheritance direction
exactly inverted from intuitive org-chart reading. Retained for
backward compatibility and as the low-level structural primitive;
new callers should use the direction-explicit semantic methods.
IMPORTANT — Parse Server _Role inheritance semantics: when role X
holds role Y in its roles relation, users of Y inherit X's
permissions (not the other way around). So calling
admin.add_child_role(moderator) does NOT grant Moderator's
capabilities to Admin; it grants Admin's capabilities to every
Moderator user — privilege escalation.
If you want Admins to have everything Moderators can do, you need to add ADMIN to MODERATOR's roles relation:
moderator.add_child_role(admin) # Admins now have Moderator capabilities
Direction-explicit replacements:
admin.inherits_capabilities_from!(moderator) # admin perspective
moderator.grant_capabilities_to!(admin) # moderator perspective
Both bang variants auto-save and return self.
502 503 504 505 506 |
# File 'lib/parse/model/classes/role.rb', line 502 def add_child_role(role) assert_not_self_reference!(role, :add_child_role) roles.add(role) self end |
#add_child_roles(*role_list) ⇒ self
Add multiple child roles to this role's hierarchy. See #add_child_role for the inheritance-direction caveat.
513 514 515 516 517 518 |
# File 'lib/parse/model/classes/role.rb', line 513 def add_child_roles(*role_list) flat = role_list.flatten flat.each { |r| assert_not_self_reference!(r, :add_child_roles) } roles.add(flat) self end |
#add_user(user) ⇒ self
Add a single user to this role.
438 439 440 441 |
# File 'lib/parse/model/classes/role.rb', line 438 def add_user(user) users.add(user) self end |
#add_users(*user_list) ⇒ self
Add multiple users to this role.
448 449 450 451 |
# File 'lib/parse/model/classes/role.rb', line 448 def add_users(*user_list) users.add(user_list.flatten) self end |
#all_child_roles(max_depth: 10, visited: Set.new) ⇒ Array<Parse::Role>
Get all child roles recursively. Cycle-safe; see #all_users.
898 899 900 901 902 903 904 905 906 907 908 909 |
# File 'lib/parse/model/classes/role.rb', line 898 def all_child_roles(max_depth: 10, visited: Set.new) return [] if max_depth <= 0 return [] if id.nil? || visited.include?(id) visited << id direct_children = roles.all nested_children = direct_children.flat_map do |child| child.all_child_roles(max_depth: max_depth - 1, visited: visited) end (direct_children + nested_children).uniq { |r| r.id } end |
#all_parent_role_names(max_depth: 10, client: nil, strict: false) ⇒ Set<String>
Get the set of role names whose presence in a _rperm array
grants access to this role's members. That's the role itself
plus every role P that lists this role in its roles relation,
transitively upward — because users of this role inherit P's
permissions under Parse Server's role-inheritance semantics
(see #add_child_role).
The instance-side analogue to all_for_user; the
two share an internal BFS via
expand_inheritance_upward. Use this method when
compiling an ACL predicate around a role argument, e.g.
:ACL.readable_by => admin_role: the role itself contributes
"role:Admin", and any role whose .roles relation contains
admin_role also grants Admins access through inheritance.
The legacy #all_child_roles walk is NOT a substitute. Child
roles inherit FROM this role (their members get this role's
capabilities), so child-role names in _rperm would not grant
this role's members anything — the walk traverses the wrong
direction for ACL composition.
888 889 890 891 892 |
# File 'lib/parse/model/classes/role.rb', line 888 def all_parent_role_names(max_depth: 10, client: nil, strict: false) Parse::Role.( [self], max_depth: max_depth, client: client, strict: strict, ) end |
#all_users(max_depth: 10, visited: Set.new, master: false, as: nil, client: nil) ⇒ Array<Parse::User>
When neither master: nor as: is supplied, the
mongo-direct fast path is skipped; the method falls through
to the Parse-Server walk through the per-relation query
interface, which goes through the default Parse::Client.
Get all users belonging to this role, including users from child roles recursively.
Cycle-safe: a visited set guards against pathological
_Role.roles cycles (e.g. A→B→A) that would otherwise cause
exponential per-node query fan-out.
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 |
# File 'lib/parse/model/classes/role.rb', line 662 def all_users(max_depth: 10, visited: Set.new, master: false, as: nil, client: nil) return [] if max_depth <= 0 return [] if id.nil? || visited.include?(id) # The fast path is opt-in (same rationale as {.all_for_user}). if master == true || !as.nil? fast_path = all_users_mongo_fast_path(max_depth, master: master, as: as, client: client) if fast_path.is_a?(Array) ActiveSupport::Notifications.instrument( "parse.role.expand", direction: :reverse, target_id: id, depth: max_depth, source: :mongo_direct, result_count: fast_path.size, ) return fast_path end end if as # Same fail-closed rule as {.all_for_user}: the relation reads below # run under the client's own credentials, so a master-keyed process # would answer a scoped request with every user in the subtree. raise Parse::MongoDB::NotEnabled, "Parse::Role#all_users: `as:` requires the mongo-direct role graph, " \ "which is unavailable. Refusing to fall back to the Parse Server walk, " \ "which would run under the client's own credentials rather than the " \ "requested scope. Configure Parse::MongoDB, or pass `master: true` to " \ "take the unscoped answer deliberately." end visited << id # The posture travels with the recursion. Dropping `client:` here meant # a traversal that started on client B finished on the default, and # dropping `master:` meant an explicit master call could silently # downgrade under client mode or an ambient session token partway down # the tree. direct_users = relation_all(users, client: client) child_roles = relation_all(roles, client: client) child_users = child_roles.flat_map do |child_role| child_role.all_users( max_depth: max_depth - 1, visited: visited, master: master, as: as, client: client, ) end result = (direct_users + child_users).uniq { |u| u.id } ActiveSupport::Notifications.instrument( "parse.role.expand", direction: :reverse, target_id: id, depth: max_depth, source: :parse_server, result_count: result.size, ) result end |
#can_delete?(object, **options) ⇒ Boolean
Return whether the role-derived policy definitively grants delete access.
850 851 852 |
# File 'lib/parse/model/classes/role.rb', line 850 def can_delete?(object, **) access_decision(object, :delete, **).allowed? end |
#can_read?(object, **options) ⇒ Boolean
Return whether the role-derived policy definitively grants read access. Unknown states fail closed.
838 839 840 |
# File 'lib/parse/model/classes/role.rb', line 838 def can_read?(object, **) access_decision(object, :read, **).allowed? end |
#can_write?(object, **options) ⇒ Boolean
Return whether the role-derived policy definitively grants update access.
844 845 846 |
# File 'lib/parse/model/classes/role.rb', line 844 def can_write?(object, **) access_decision(object, :write, **).allowed? end |
#child_roles_count ⇒ Integer
Get the count of direct child roles.
919 920 921 |
# File 'lib/parse/model/classes/role.rb', line 919 def child_roles_count roles.query.count end |
#grant_capabilities_to(grantee) ⇒ self
Grant this role's capabilities to the given role's users. Reads as:
"users with grantee now have self's capabilities."
Equivalent to self.add_child_role(grantee) but unambiguous about
the direction of inheritance.
Non-saving — the caller must call self.save to persist. See
#grant_capabilities_to! for the auto-saving variant.
549 550 551 552 553 |
# File 'lib/parse/model/classes/role.rb', line 549 def grant_capabilities_to(grantee) assert_not_self_reference!(grantee, :grant_capabilities_to) roles.add(grantee) self end |
#grant_capabilities_to!(grantee) ⇒ self
Auto-saving variant of #grant_capabilities_to. Performs the
relation mutation AND persists self in one call. Returns self
consistently so the caller can chain or store the result without
tracking which object was mutated. Prefer this in tests and
one-shot scripts where batching multiple mutations isn't needed.
567 568 569 570 571 |
# File 'lib/parse/model/classes/role.rb', line 567 def grant_capabilities_to!(grantee) grant_capabilities_to(grantee) save! self end |
#has_child_role?(role) ⇒ Boolean
Check if a role is a direct child of this role.
629 630 631 632 |
# File 'lib/parse/model/classes/role.rb', line 629 def has_child_role?(role) return false unless role.is_a?(Parse::Role) && role.id.present? roles.query.where(objectId: role.id).count > 0 end |
#has_user?(user) ⇒ Boolean
Check if a user belongs to this role (direct membership only).
621 622 623 624 |
# File 'lib/parse/model/classes/role.rb', line 621 def has_user?(user) return false unless user.is_a?(Parse::User) && user.id.present? users.query.where(objectId: user.id).count > 0 end |
#inherits_capabilities_from(source) ⇒ Parse::Role
Inverse spelling of #grant_capabilities_to: "this role's users
inherit source's capabilities". Performs the relation mutation
on source, not on self.
Save target. The mutation lives on source.roles. To persist,
the caller must save source, NOT self. This asymmetry exists
because Parse Server stores the relation on the role that holds
the roles list, and that role is source. The non-bang form is
retained for callers that need to batch multiple mutations on
source before a single save; prefer #inherits_capabilities_from!
for the one-shot case where the auto-save matches intent.
594 595 596 597 598 |
# File 'lib/parse/model/classes/role.rb', line 594 def inherits_capabilities_from(source) assert_not_self_reference!(source, :inherits_capabilities_from) source.roles.add(self) source end |
#inherits_capabilities_from!(source) ⇒ self
Auto-saving variant of #inherits_capabilities_from. Performs the
mutation on source.roles AND saves source for you, then
returns self so the caller can keep working with the role they
called the method on. Resolves the most common stumbling block
with #inherits_capabilities_from: the "save target" asymmetry.
612 613 614 615 616 |
# File 'lib/parse/model/classes/role.rb', line 612 def inherits_capabilities_from!(source) inherits_capabilities_from(source) source.save! self end |
#remove_child_role(role) ⇒ self
Remove a child role from this role's hierarchy.
523 524 525 526 |
# File 'lib/parse/model/classes/role.rb', line 523 def remove_child_role(role) roles.remove(role) self end |
#remove_child_roles(*role_list) ⇒ self
Remove multiple child roles from this role's hierarchy.
531 532 533 534 |
# File 'lib/parse/model/classes/role.rb', line 531 def remove_child_roles(*role_list) roles.remove(role_list.flatten) self end |
#remove_user(user) ⇒ self
Remove a single user from this role.
456 457 458 459 |
# File 'lib/parse/model/classes/role.rb', line 456 def remove_user(user) users.remove(user) self end |
#remove_users(*user_list) ⇒ self
Remove multiple users from this role.
464 465 466 467 |
# File 'lib/parse/model/classes/role.rb', line 464 def remove_users(*user_list) users.remove(user_list.flatten) self end |
#roles ⇒ RelationCollectionProxy<Role>
This attribute is mapped as a has_many Parse relation association with the Parse::Role class,
as roles can be associated with multiple child roles to support role inheritance.
The roles Parse relation provides a mechanism to create a hierarchical inheritable types of permissions
by assigning child roles.
60 |
# File 'lib/parse/model/classes/role.rb', line 60 has_many :roles, through: :relation |
#total_users_count ⇒ Integer
Get the total count of users including child roles.
925 926 927 |
# File 'lib/parse/model/classes/role.rb', line 925 def total_users_count all_users.count end |
#users ⇒ RelationCollectionProxy<User>
This attribute is mapped as a has_many Parse relation association with the User class.
63 |
# File 'lib/parse/model/classes/role.rb', line 63 has_many :users, through: :relation |
#users_count ⇒ Integer
Get the count of direct users in this role.
913 914 915 |
# File 'lib/parse/model/classes/role.rb', line 913 def users_count users.query.count end |