Class: JSS::Scopable::Scope
- Defined in:
- lib/jss/api_object/scopable/scope.rb,
lib/jss.rb
Overview
Implement simple LDAP queries using the defined LDAPServers to confirm the existance of users or groups used in limitations and exclusions. As things are now if you add invalid user or group names, you’ll get a 409 conflict error when you try to save your changes to the JSS.
This class represents a Scope in the JSS, as can be applied to Scopable objects like Policies, Profiles, etc. Instances of this class are generally used as the value of the @scope attribute of those objects.
Scope data comes from the API as a hash within the overall object data. The main keys of the hash define the included targets of the scope. A sub-hash defines limitations on those inclusions, and another sub-hash defines explicit exclusions.
This class provides methods for adding, removing, or fully replacing the various parts of the scope’s inclusions, limitations, and exclusions.
Constant Summary collapse
- SCOPING_CLASSES =
These are the classes that Scopes can use for defining a scope, keyed by appropriate symbols.
{ computers: JSS::Computer, computer: JSS::Computer, computer_groups: JSS::ComputerGroup, computer_group: JSS::ComputerGroup, mobile_devices: JSS::MobileDevice, mobile_device: JSS::MobileDevice, mobile_device_groups: JSS::MobileDeviceGroup, mobile_device_group: JSS::MobileDeviceGroup, buildings: JSS::Building, building: JSS::Building, departments: JSS::Department, department: JSS::Department, network_segments: JSS::NetworkSegment, network_segment: JSS::NetworkSegment, users: JSS::User, user: JSS::User, user_groups: JSS::UserGroup, user_group: JSS::UserGroup }.freeze
- LDAP_USER_KEYS =
Some things get checked in LDAP as well as the JSS
%i[user users].freeze
- LDAP_GROUP_KEYS =
%i[user_groups user_group].freeze
- CHECK_LDAP_KEYS =
LDAP_USER_KEYS + LDAP_GROUP_KEYS
- TARGETS_AND_GROUPS =
This hash maps the availble Scope Target keys from SCOPING_CLASSES to their corresponding target group keys from SCOPING_CLASSES.
{ computers: :computer_groups, mobile_devices: :mobile_device_groups }.freeze
- INCLUSIONS =
These can be part of the base inclusion list of the scope, along with the appropriate target and target group keys
%i[buildings departments].freeze
- LIMITATIONS =
These can limit the inclusion list
%i[network_segments users user_groups].freeze
- EXCLUSIONS =
any of them can be excluded
INCLUSIONS + LIMITATIONS
- DEFAULT_SCOPE =
Here’s a default scope as it might come from the API.
{ all_computers: true, all_mobile_devices: true, limitations: {}, exclusions: {} }.freeze
Instance Attribute Summary collapse
-
#all_targets ⇒ Boolean
(also: #all_targets?)
readonly
Does this scope cover all targets?.
-
#container ⇒ JSS::APIObject subclass
A reference to the object that contains this Scope.
-
#exclusions ⇒ Hash<Array>
readonly
The items in these arrays are the exclusions applied to targets in the @inclusions .
-
#inclusions ⇒ Hash<Array>
readonly
The items which form the base scope of included targets.
-
#limitations ⇒ Hash<Array>
readonly
The items in these arrays are the limitations applied to targets in the @inclusions .
-
#target_class ⇒ Object
readonly
what type of target is this scope for? Computers or Mobiledevices?.
-
#unable_to_verify_ldap_entries ⇒ Boolean
Should we expect a potential 409 Conflict if we can’t connect to LDAP servers for verification?.
Instance Method Summary collapse
-
#add_exclusion(key, item) ⇒ void
Add a single item for exclusions of this scope.
-
#add_inclusion(key, item) ⇒ void
Add a single item for this inclusion in this scope.
-
#add_limitation(key, item) ⇒ void
Add a single item for limiting this scope.
-
#include_all(clear = false) ⇒ void
Set the scope’s inclusions to all targets.
-
#initialize(target_key, raw_scope = nil) ⇒ Scope
constructor
If raw_scope is empty, a default scope, scoped to all targets, is created, and can be modified as needed.
-
#remove_exclusion(key, item) ⇒ void
Remove a single item for exclusions of this scope.
-
#remove_inclusion(key, item) ⇒ void
Remove a single item for this scope.
-
#remove_limitation(key, item) ⇒ void
Remove a single item for limiting this scope.
-
#scope_xml ⇒ REXML::Element
private
Return a REXML Element containing the current state of the Scope for adding into the XML of the container.
-
#set_exclusion(key, list) ⇒ void
Replace an exclusion list for this scope.
-
#set_inclusion(key, list) ⇒ void
Replace a list of item names for inclusion in this scope.
-
#set_limitation(key, list) ⇒ void
Replace a limitation list for this scope.
Constructor Details
#initialize(target_key, raw_scope = nil) ⇒ Scope
If raw_scope is empty, a default scope, scoped to all targets, is created, and can be modified as needed.
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/jss/api_object/scopable/scope.rb', line 184 def initialize(target_key, raw_scope = nil) raw_scope ||= DEFAULT_SCOPE raise JSS::InvalidDataError, "The target class of a Scope must be one of the symbols :#{TARGETS_AND_GROUPS.keys.join(', :')}" unless TARGETS_AND_GROUPS.keys.include? target_key @target_key = target_key @target_class = SCOPING_CLASSES[@target_key] @group_key = TARGETS_AND_GROUPS[@target_key] @group_class = SCOPING_CLASSES[@group_key] @inclusion_keys = [@target_key, @group_key] + INCLUSIONS @exclusion_keys = [@target_key, @group_key] + EXCLUSIONS @all_key = "all_#{target_key}".to_sym @all_targets = raw_scope[@all_key] # Everything gets mapped from an Array of Hashes to an Array of names (or an empty array) # since names are all that really matter when submitting the scope. @inclusions = {} @inclusion_keys.each { |k| @inclusions[k] = raw_scope[k] ? raw_scope[k].map { |n| n[:name] } : [] } @limitations = {} if raw_scope[:limitations] LIMITATIONS.each { |k| @limitations[k] = raw_scope[:limitations][k] ? raw_scope[:limitations][k].map { |n| n[:name] } : [] } end @exclusions = {} if raw_scope[:exclusions] @exclusion_keys.each { |k| @exclusions[k] = raw_scope[:exclusions][k] ? raw_scope[:exclusions][k].map { |n| n[:name] } : [] } end @container = nil end |
Instance Attribute Details
#all_targets ⇒ Boolean (readonly) Also known as: all_targets?
Does this scope cover all targets?
If this is true, the @inclusions Hash is ignored, and all targets in the JSS form the base scope.
146 147 148 |
# File 'lib/jss/api_object/scopable/scope.rb', line 146 def all_targets @all_targets end |
#container ⇒ JSS::APIObject subclass
A reference to the object that contains this Scope
For telling it when a change is made and an update needed
116 117 118 |
# File 'lib/jss/api_object/scopable/scope.rb', line 116 def container @container end |
#exclusions ⇒ Hash<Array> (readonly)
The items in these arrays are the exclusions applied to targets in the @inclusions .
The arrays of names are:
-
:targets
-
:target_groups
-
:departments
-
:buildings
-
:network_segments
-
:users
-
:user_groups
172 173 174 |
# File 'lib/jss/api_object/scopable/scope.rb', line 172 def exclusions @exclusions end |
#inclusions ⇒ Hash<Array> (readonly)
The items which form the base scope of included targets
This is the group of targets to which the limitations and exclusions apply. they keys are:
-
:targets
-
:target_groups
-
:departments
-
:buildings
and the values are Arrays of names of those things.
137 138 139 |
# File 'lib/jss/api_object/scopable/scope.rb', line 137 def inclusions @inclusions end |
#limitations ⇒ Hash<Array> (readonly)
The items in these arrays are the limitations applied to targets in the @inclusions .
The arrays of names are:
-
:network_segments
-
:users
-
:user_groups
157 158 159 |
# File 'lib/jss/api_object/scopable/scope.rb', line 157 def limitations @limitations end |
#target_class ⇒ Object (readonly)
what type of target is this scope for? Computers or Mobiledevices?
123 124 125 |
# File 'lib/jss/api_object/scopable/scope.rb', line 123 def target_class @target_class end |
#unable_to_verify_ldap_entries ⇒ Boolean
Returns should we expect a potential 409 Conflict if we can’t connect to LDAP servers for verification?.
120 121 122 |
# File 'lib/jss/api_object/scopable/scope.rb', line 120 def unable_to_verify_ldap_entries @unable_to_verify_ldap_entries end |
Instance Method Details
#add_exclusion(key, item) ⇒ void
This method returns an undefined value.
Add a single item for exclusions of this scope.
The item name will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.
475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
# File 'lib/jss/api_object/scopable/scope.rb', line 475 def add_exclusion(key, item) raise JSS::InvalidDataError, "Exclusion key must be one of :#{@exclusion_keys.join(', :')}" unless @exclusion_keys.include? key raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String return nil if @exclusions[key] && @exclusions[key].include?(item) # check the name raise JSS::NoSuchItemError, "No existing #{key} with name '#{item}'" unless check_name key, item raise JSS::AlreadyExistsError, "Can't exclude #{key} scope to '#{item}' because it's already explicitly included." if @inclusions[key] && @inclusions[key].include?(item) raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{item}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(item) @exclusions[key] << item @container.should_update if @container end |
#add_inclusion(key, item) ⇒ void
This method returns an undefined value.
Add a single item for this inclusion in this scope.
The item name will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/jss/api_object/scopable/scope.rb', line 293 def add_inclusion(key, item) raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String return nil if @inclusions[key] && @inclusions[key].include?(item) # check the name raise JSS::NoSuchItemError, "No existing #{key} with name '#{item}'" unless check_name key, item raise JSS::AlreadyExistsError, "Can't set #{key} scope to '#{item}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item) @inclusions[key] << item @all_targets = false @container.should_update if @container end |
#add_limitation(key, item) ⇒ void
handle ldap user/group lookups
This method returns an undefined value.
Add a single item for limiting this scope.
The item name will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.
385 386 387 388 389 390 391 392 393 394 395 396 397 |
# File 'lib/jss/api_object/scopable/scope.rb', line 385 def add_limitation(key, item) raise JSS::InvalidDataError, "Limitation key must be one of :#{LIMITATIONS.join(', :')}" unless LIMITATIONS.include? key raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String return nil if @limitations[key] && @limitations[key].include?(item) # check the name raise JSS::NoSuchItemError, "No existing #{key} with name '#{item}'" unless check_name key, item raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(item) @limitations[key] << item @container.should_update if @container end |
#include_all(clear = false) ⇒ void
This method returns an undefined value.
Set the scope’s inclusions to all targets.
By default, the limitations and exclusions remain. If a non-false parameter is provided, they will be removed also.
226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/jss/api_object/scopable/scope.rb', line 226 def include_all(clear = false) @inclusions = {} @inclusion_keys.each { |k| @inclusions[k] = [] } @all_targets = true if clear @limitations = {} LIMITATIONS.each { |k| @limitations[k] = [] } @exclusions = {} @exclusion_keys.each { |k| @exclusions[k] = [] } end @container.should_update if @container end |
#remove_exclusion(key, item) ⇒ void
This method returns an undefined value.
Remove a single item for exclusions of this scope
501 502 503 504 505 506 507 508 509 |
# File 'lib/jss/api_object/scopable/scope.rb', line 501 def remove_exclusion(key, item) raise JSS::InvalidDataError, "Exclusion key must be one of :#{@exclusion_keys.join(', :')}" unless @exclusion_keys.include? key raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String return nil unless @exclusions[key] && @exclusions[key].include?(item) @exclusions[key] -= [item] @container.should_update if @container end |
#remove_inclusion(key, item) ⇒ void
This method returns an undefined value.
Remove a single item for this scope.
319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/jss/api_object/scopable/scope.rb', line 319 def remove_inclusion(key, item) raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String return nil unless @inclusions[key] && @inclusions[key].include?(item) @inclusions[key] -= [item] # if ALL the @inclusion keys are empty, then set all targets to true. @all_targets = @inclusions.values.reject { |a| a.nil? || a.empty? }.empty? @container.should_update if @container end |
#remove_limitation(key, item) ⇒ void
handle ldap user/group lookups
This method returns an undefined value.
Remove a single item for limiting this scope.
412 413 414 415 416 417 418 419 420 |
# File 'lib/jss/api_object/scopable/scope.rb', line 412 def remove_limitation(key, item) raise JSS::InvalidDataError, "Limitation key must be one of :#{LIMITATIONS.join(', :')}" unless LIMITATIONS.include? key raise JSS::InvalidDataError, "Item must be a #{key} name." unless item.is_a? String return nil unless @limitations[key] && @limitations[key].include?(item) @limitations[key] -= [item] @container.should_update if @container end |
#scope_xml ⇒ REXML::Element
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Return a REXML Element containing the current state of the Scope for adding into the XML of the container.
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 |
# File 'lib/jss/api_object/scopable/scope.rb', line 517 def scope_xml scope = REXML::Element.new 'scope' scope.add_element(@all_key.to_s).text = @all_targets @inclusions.each do |klass, list| list_as_hash = list.map { |i| { name: i } } scope << SCOPING_CLASSES[klass].xml_list(list_as_hash, :name) end limitations = scope.add_element('limitations') @limitations.each do |klass, list| list_as_hash = list.map { |i| { name: i } } limitations << SCOPING_CLASSES[klass].xml_list(list_as_hash, :name) end exclusions = scope.add_element('exclusions') @exclusions.each do |klass, list| list_as_hash = list.map { |i| { name: i } } exclusions << SCOPING_CLASSES[klass].xml_list(list_as_hash, :name) end scope end |
#set_exclusion(key, list) ⇒ void
This method returns an undefined value.
Replace an exclusion list for this scope
The list must be an Array of names of items of the Class being excluded from the scope Each will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
# File 'lib/jss/api_object/scopable/scope.rb', line 436 def set_exclusion(key, list) raise JSS::InvalidDataError, "Exclusion key must be one of :#{@exclusion_keys.join(', :')}" unless @exclusion_keys.include? key raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array return nil if list.sort == @exclusions[key].sort if list.empty? @exclusions[key] = [] @container.should_update if @container return list end # check the names list.each do |name| raise JSS::NoSuchItemError, "No existing #{key} with name '#{name}'" unless check_name key, name case key when *@inclusion_keys raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{name}' because it's already explicitly included." if @inclusions[key] && @inclusions[key].include?(name) when *LIMITATIONS raise JSS::AlreadyExistsError, "Can't exclude #{key} '#{name}' because it's already an explicit limitation." if @limitations[key] && @limitations[key].include?(name) end end # each @exclusions[key] = list @container.should_update if @container end |
#set_inclusion(key, list) ⇒ void
This method returns an undefined value.
Replace a list of item names for inclusion in this scope.
The list must be an Array of names of items of the Class represented by the key. Each will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.
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/jss/api_object/scopable/scope.rb', line 254 def set_inclusion(key, list) raise JSS::InvalidDataError, "Inclusion key must be one of :#{@inclusion_keys.join(', :')}" unless @inclusion_keys.include? key raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array return nil if list.sort == @inclusions[key].sort # emptying the list? if list.empty? @inclusion[key] = list # if ALL the @inclusion keys are empty, then set all targets to true. @all_targets = @inclusions.values.reject { |a| a.nil? || a.empty? }.empty? @container.should_update if @container return list end # check the names list.each do |name| raise JSS::NoSuchItemError, "No existing #{key} with name '#{name}'" unless check_name key, name raise JSS::AlreadyExistsError, "Can't set #{key} scope to '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(name) end # each @inclusions[key] = list @all_targets = false @container.should_update if @container end |
#set_limitation(key, list) ⇒ void
handle ldap user group lookups
This method returns an undefined value.
Replace a limitation list for this scope.
The list must be an Array of names of items of the Class represented by the key. Each will be checked for existence in the JSS, and an exception raised if the item doesn’t exist.
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/jss/api_object/scopable/scope.rb', line 349 def set_limitation(key, list) raise JSS::InvalidDataError, "Limitation key must be one of :#{LIMITATIONS.join(', :')}" unless LIMITATIONS.include? key raise JSS::InvalidDataError, "List must be an Array of #{key} names, it may be empty." unless list.is_a? Array return nil if list.sort == @limitations[key].sort if list.empty? @limitations[key] = [] @container.should_update if @container return list end # check the names list.each do |name| raise JSS::NoSuchItemError, "No existing #{key} with name '#{name}'" unless check_name key, name raise JSS::AlreadyExistsError, "Can't set #{key} limitation for '#{name}' because it's already an explicit exclusion." if @exclusions[key] && @exclusions[key].include?(name) end # each @limitations[key] = list @container.should_update if @container end |