From 8333f09ce5a72dedb62d56daf476924a9dfdb32d Mon Sep 17 00:00:00 2001 From: Stephen Hosom Date: Fri, 11 Sep 2026 15:33:34 -0400 Subject: [PATCH] Remove contracts from calculation hot paths Avoid repeatedly validating cached rules, parsed data, and member collections during recursive entitlement calculation while preserving explicit input validation and contracts outside the calculation path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 5b8ed060-ed02-4402-b5e1-af407bcb2f61 --- lib/entitlements/data/groups/calculated.rb | 22 +++------------- .../data/groups/calculated/base.rb | 25 ------------------- .../data/groups/calculated/filters/base.rb | 5 ---- .../groups/calculated/modifiers/expiration.rb | 1 - .../data/groups/calculated/ruby.rb | 1 - .../data/groups/calculated/rules/base.rb | 5 ---- .../data/groups/calculated/rules/group.rb | 6 ----- .../data/groups/calculated/rules/username.rb | 5 ---- .../data/groups/calculated/text.rb | 11 -------- .../data/groups/calculated/yaml.rb | 9 ------- lib/entitlements/data/people/yaml.rb | 1 - .../extras/ldap_group/rules/ldap_group.rb | 5 ---- lib/entitlements/extras/orgchart/logic.rb | 5 ---- .../extras/orgchart/rules/direct_report.rb | 5 ---- .../extras/orgchart/rules/management.rb | 5 ---- 15 files changed, 4 insertions(+), 107 deletions(-) diff --git a/lib/entitlements/data/groups/calculated.rb b/lib/entitlements/data/groups/calculated.rb index 55eb39a..2f12fc4 100644 --- a/lib/entitlements/data/groups/calculated.rb +++ b/lib/entitlements/data/groups/calculated.rb @@ -8,6 +8,10 @@ # Calculate groups that should exist and the contents of each based on a set of rules # defined within a directory. The calculation of members is global across the entire # entitlements system, so this is a singleton class. +# +# Calculation methods intentionally use explicit validation instead of runtime contracts. +# These methods recurse over large collections, and collection contracts revalidate every +# member on each cached return. module Entitlements class Data @@ -46,7 +50,6 @@ def self.reset! # Takes no arguments. # # Returns a Entitlements::Models::Group object. - Contract String => Entitlements::Models::Group def self.read(dn) return @groups_cache[dn] if @groups_cache[dn] raise "read(#{dn.inspect}) does not support calculation at this time. Please use read_all() first to build cache." @@ -59,9 +62,6 @@ def self.read(dn) # cfg_obj - Hash with the configuration for that key from the configuration file. # # Returns a Set of Strings (DNs) of the groups in this OU. - Contract String, C::HashOf[String => C::Any], C::KeywordArgs[ - skip_broken_references: C::Optional[C::Bool] - ] => C::SetOf[String] def self.read_all(ou_key, cfg_obj, skip_broken_references: false) return read_mirror(ou_key, cfg_obj) if cfg_obj["mirror"] @@ -118,7 +118,6 @@ def self.read_all(ou_key, cfg_obj, skip_broken_references: false) # # Returns a hash { dn => Entitlements::Models::Group } # :nocov: - Contract C::None => C::HashOf[String => Entitlements::Models::Group] def self.to_h @groups_cache end @@ -129,7 +128,6 @@ def self.to_h # Takes no arguments. # # Returns a Hash of OU to the configuration and group objects it contains. - Contract C::None => C::HashOf[String => { config: C::HashOf[String => C::Any], groups: C::HashOf[String => Entitlements::Models::Group]}] def self.all_groups @groups_in_ou_cache.map do |ou_key, dn_in_ou| if @config_cache.key?(ou_key) @@ -154,7 +152,6 @@ def self.all_groups # cfg_obj - Hash with the configuration for that key from the configuration file. # # Returns a Set of Strings (DNs) of the groups in this OU. - Contract String, C::HashOf[String => C::Any] => C::SetOf[String] def self.read_mirror(ou_key, cfg_obj) @groups_in_ou_cache[ou_key] ||= begin Entitlements.logger.debug "Mirroring #{ou_key} from #{cfg_obj['mirror']}" @@ -184,15 +181,6 @@ def self.read_mirror(ou_key, cfg_obj) # filename - A String with the filename. # # Returns an Entitlements::Data::Groups::Calculated::* object. - Contract C::KeywordArgs[ - filename: String, - config: C::HashOf[String => C::Any], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::Or[ - Entitlements::Data::Groups::Calculated::Ruby, - Entitlements::Data::Groups::Calculated::Text, - Entitlements::Data::Groups::Calculated::YAML, - ] def self.ruleset(filename:, config:, options: {}) unless filename =~ /\.(\w+)\z/ raise ArgumentError, "Unable to determine the extension on #{filename.inspect}!" @@ -242,7 +230,6 @@ def self.file_object_key(filename) # Takes no arguments. # # Returns a Hash. - Contract C::None => C::HashOf[String => Class] def self.rules_index @rules_index end @@ -252,7 +239,6 @@ def self.rules_index # Takes no arguments. # # Returns a Hash. - Contract C::None => C::HashOf[String => Object] def self.filters_index @filters_index end diff --git a/lib/entitlements/data/groups/calculated/base.rb b/lib/entitlements/data/groups/calculated/base.rb index 0865f94..05a061a 100644 --- a/lib/entitlements/data/groups/calculated/base.rb +++ b/lib/entitlements/data/groups/calculated/base.rb @@ -39,7 +39,6 @@ class Base # Takes no arguments. # # Returns Set[Entitlements::Models::Person] of all matching members. - Contract C::None => C::SetOf[Entitlements::Models::Person] def members # :nocov: raise "Must be implemented in child class" @@ -51,7 +50,6 @@ def members # Takes no arguments. # # Returns a String. - Contract C::None => String def description # :nocov: raise "Must be implemented in child class" @@ -64,7 +62,6 @@ def description # # Returns Hash[key => value] # :nocov: - Contract C::None => C::HashOf[String => C::Any] def modifiers {} end @@ -78,11 +75,6 @@ def modifiers # # filename - Filename with the ruleset. # options - An optional hash of additional options. - Contract C::KeywordArgs[ - filename: String, - config: C::Maybe[C::HashOf[String => C::Any]], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::Any def initialize(filename:, config: nil, options: {}) @filename = filename @config = config @@ -96,7 +88,6 @@ def initialize(filename:, config: nil, options: {}) # message - String with the message to log and raise. # # Returns nothing. - Contract String => C::None def fatal_message(message) Entitlements.logger.fatal(message) raise RuntimeError, message @@ -107,7 +98,6 @@ def fatal_message(message) # members_in - Optionally a set of Entitlements::Models::Person with the currently calculated member set. # # Returns Set[Entitlements::Models::Person] of all matching members. - Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]] def filtered_members return :calculating if members == :calculating @@ -132,7 +122,6 @@ def filtered_members # Takes no arguments. # # Returns Set[Entitlements::Models::Person] of all matching members. - Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]] def modified_members return :calculating if members == :calculating @modified_members ||= apply_modifiers(members) @@ -143,7 +132,6 @@ def modified_members # members_in - Optionally a set of Entitlements::Models::Person with the currently calculated member set. # # Returns Set[Entitlements::Models::Person] of all matching members. - Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]] def modified_filtered_members return :calculating if filtered_members == :calculating @modified_filtered_members ||= apply_modifiers(filtered_members) @@ -170,7 +158,6 @@ def filter_applies?(filter_config) # member_set - Set of Entitlements::Models::Person # # Returns a set of Entitlements::Models::Person - Contract C::SetOf[Entitlements::Models::Person] => C::SetOf[Entitlements::Models::Person] def apply_modifiers(member_set) result = member_set.dup @@ -205,7 +192,6 @@ def apply_modifiers(member_set) # context - A String (usually a filename) to provide context if there's an error. # # Returns true if expired, false if not expired. - Contract C::Or[nil, String], String => C::Or[nil, C::Bool] def expired?(expiration, context) return false if Entitlements.config.fetch("ignore_expirations", false) return false if expiration.nil? || expiration.strip.empty? @@ -222,7 +208,6 @@ def expired?(expiration, context) # rule - A Hash of rules (see "rules" stub below). # # Returns Set[Entitlements::Models::Person]. - Contract C::HashOf[String => C::Any] => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]] def members_from_rules(rule) Entitlements.cache[:calculated] ||= {} Entitlements.cache[:calculated][rou] ||= {} @@ -258,7 +243,6 @@ def members_from_rules(rule) # rule - A Hash of rules (see "rules" stub below). # # Returns Set[Entitlements::Models::Person]. - Contract C::HashOf[String => C::Any] => C::SetOf[Entitlements::Models::Person] def _members_from_rules(rule) # Empty rule => error. if rule.keys.empty? @@ -302,7 +286,6 @@ def _members_from_rules(rule) # Takes no arguments. # # Returns a Hash. - Contract C::None => C::HashOf[String => C::Any] def rules # :nocov: raise "Must be implemented in child class" @@ -371,7 +354,6 @@ def handle_not(rule) # type - The type. # # Returns nothing, but raises an error if the type doesn't match. - Contract String, C::Any, C::Any => nil def ensure_type!(function, obj, type) return if obj.is_a?(type) raise "Invalid type: in #{filename}, expected #{function.inspect} to be a #{type} but got #{obj.inspect}!" @@ -382,7 +364,6 @@ def ensure_type!(function, obj, type) # str - The string that needs to be converted to CamelCase. # # Returns a String in CamelCase. - Contract String => String def camelize(str) Entitlements::Util::Util.camelize(str) end @@ -392,7 +373,6 @@ def camelize(str) # Takes no arguments. # # Returns a String with the name of the ou. - Contract C::None => String def ou File.basename(File.dirname(filename)) end @@ -402,7 +382,6 @@ def ou # Takes no arguments. # # Returns a String with the name of the ou. - Contract C::None => String def rou File.expand_path(File.dirname(filename)).gsub("#{Entitlements.config_path}/", "").gsub(/^\//, "").gsub(/\//, "/") end @@ -412,7 +391,6 @@ def rou # Takes no arguments. # # Returns a String with the name of the cn. - Contract C::None => String def cn File.basename(filename).sub(/\.[^\.]+\z/, "") end @@ -424,7 +402,6 @@ def cn # Takes no arguments. # # Returns a Set with the permitted methods. - Contract C::None => C::SetOf[String] def allowed_methods @allowed_methods ||= begin if config.is_a?(Hash) && config["allowed_methods"] @@ -445,7 +422,6 @@ def allowed_methods # function_in - String with the function name from the definition. # # Returns the underlying function name if aliased, or else what was entered. - Contract String => String def function_for(function_in) ALIAS_METHODS[function_in] || function_in end @@ -456,7 +432,6 @@ def function_for(function_in) # Takes no arguments. # # Returns an Set of Strings with allowed methods. - Contract C::None => C::SetOf[String] def whitelisted_methods Set.new(Entitlements::Data::Groups::Calculated.rules_index.keys) end diff --git a/lib/entitlements/data/groups/calculated/filters/base.rb b/lib/entitlements/data/groups/calculated/filters/base.rb index b9db9e7..2e01ab6 100644 --- a/lib/entitlements/data/groups/calculated/filters/base.rb +++ b/lib/entitlements/data/groups/calculated/filters/base.rb @@ -18,7 +18,6 @@ class Base # member - Entitlements::Models::Person object # # Return true if the member is to be filtered out, false if the member does not match the filter. - Contract Entitlements::Models::Person => C::Bool def filtered?(_member) # :nocov: raise "Must be implemented in child class" @@ -29,10 +28,6 @@ def filtered?(_member) # # filter - Either :none, :all, or an array of string conditions passed through to the filter # config - Configuration data (Hash, optional) - Contract C::KeywordArgs[ - filter: C::Or[:none, C::ArrayOf[String]], - config: C::Maybe[Hash] - ] => C::Any def initialize(filter:, config: {}) @filter = filter @config = config diff --git a/lib/entitlements/data/groups/calculated/modifiers/expiration.rb b/lib/entitlements/data/groups/calculated/modifiers/expiration.rb index 4b57c7b..81f8990 100644 --- a/lib/entitlements/data/groups/calculated/modifiers/expiration.rb +++ b/lib/entitlements/data/groups/calculated/modifiers/expiration.rb @@ -20,7 +20,6 @@ class Expiration < Base # result - Set of Entitlements::Models::Person (mutated). # # Return true if we made any changes, false otherwise. - Contract C::SetOf[Entitlements::Models::Person] => C::Bool def modify(result) return false if Entitlements.config.fetch("ignore_expirations", false) # If group is already empty, we have nothing to consider modifying, regardless diff --git a/lib/entitlements/data/groups/calculated/ruby.rb b/lib/entitlements/data/groups/calculated/ruby.rb index e39a60c..c07d5cd 100644 --- a/lib/entitlements/data/groups/calculated/ruby.rb +++ b/lib/entitlements/data/groups/calculated/ruby.rb @@ -14,7 +14,6 @@ class Ruby < Entitlements::Data::Groups::Calculated::Base # Takes no arguments. # # Returns a Set[Entitlements::Models::Person] with DN's of the people in the group. - Contract C::None => C::SetOf[Entitlements::Models::Person] def members @members ||= begin Entitlements.logger.debug "Calculating members from #{filename}" diff --git a/lib/entitlements/data/groups/calculated/rules/base.rb b/lib/entitlements/data/groups/calculated/rules/base.rb index ae9de31..a810d07 100644 --- a/lib/entitlements/data/groups/calculated/rules/base.rb +++ b/lib/entitlements/data/groups/calculated/rules/base.rb @@ -17,11 +17,6 @@ class Base # options - Optional hash of additional method-specific options # # Returns a Set[Entitlements::Models::Person]. - Contract C::KeywordArgs[ - value: String, - filename: C::Maybe[String], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::SetOf[Entitlements::Models::Person] def self.matches(value:, filename: nil, options: {}) # :nocov: raise "matches() must be defined in the child class #{self.class}!" diff --git a/lib/entitlements/data/groups/calculated/rules/group.rb b/lib/entitlements/data/groups/calculated/rules/group.rb index 1dd48e3..934c93f 100644 --- a/lib/entitlements/data/groups/calculated/rules/group.rb +++ b/lib/entitlements/data/groups/calculated/rules/group.rb @@ -21,11 +21,6 @@ class Group < Entitlements::Data::Groups::Calculated::Rules::Base # options - Optional hash of additional method-specific options # # Returns a Set[Entitlements::Models::Person]. - Contract C::KeywordArgs[ - value: String, - filename: C::Maybe[String], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::SetOf[Entitlements::Models::Person] def self.matches(value:, filename: nil, options: {}) # We've asked for a managed group, so we need to calculate that group and return its members. # First parse the value into the ou and cn. @@ -98,7 +93,6 @@ def self.matches(value:, filename: nil, options: {}) # path - A String with the directory structure relative to Entitlements.config_path # # Returns a Set of Hashes with { "file_without_extension" => "extension" } - Contract String, C::KeywordArgs[options: C::HashOf[Symbol => C::Any]] => C::HashOf[String => String] def self.files_for(path, options:) @files_for_cache ||= {} @files_for_cache[path] ||= begin diff --git a/lib/entitlements/data/groups/calculated/rules/username.rb b/lib/entitlements/data/groups/calculated/rules/username.rb index 029b4e3..230d976 100644 --- a/lib/entitlements/data/groups/calculated/rules/username.rb +++ b/lib/entitlements/data/groups/calculated/rules/username.rb @@ -17,11 +17,6 @@ class Username < Entitlements::Data::Groups::Calculated::Rules::Base # options - Optional hash of additional method-specific options # # Returns a Set[Entitlements::Models::Person]. - Contract C::KeywordArgs[ - value: String, - filename: C::Maybe[String], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::SetOf[Entitlements::Models::Person] def self.matches(value:, filename: nil, options: {}) # Username is easy - the value is the uid. begin diff --git a/lib/entitlements/data/groups/calculated/text.rb b/lib/entitlements/data/groups/calculated/text.rb index b78828a..e0b663d 100644 --- a/lib/entitlements/data/groups/calculated/text.rb +++ b/lib/entitlements/data/groups/calculated/text.rb @@ -19,7 +19,6 @@ class Text < Entitlements::Data::Groups::Calculated::Base # Takes no arguments. # # Returns a Set[String] with DN's of the people in the group. - Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]] def members @members ||= begin Entitlements.logger.debug "Calculating members from #{filename}" @@ -32,7 +31,6 @@ def members # Takes no arguments. # # Returns a String with the group description, or "" if undefined. - Contract C::None => String def description return "" unless parsed_data.key?("description") @@ -53,7 +51,6 @@ def description # Takes no arguments. # # Returns Hash[key => value] - Contract C::None => C::HashOf[String => C::Any] def modifiers parse_with_prefix("modifier_") end @@ -65,7 +62,6 @@ def modifiers # Takes no arguments. # # Returns a Hash[String => :all/:none/List of strings]. - Contract C::None => C::HashOf[String => C::Or[:all, :none, C::ArrayOf[String]]] def initialize_filters result = Entitlements::Data::Groups::Calculated.filters_default @@ -108,7 +104,6 @@ def initialize_filters # Takes no arguments. # # Returns Hash[key => value] - Contract C::None => C::HashOf[String => C::Any] def initialize_metadata parse_with_prefix("metadata_") end @@ -119,7 +114,6 @@ def initialize_metadata # prefix - String with the prefix expected for the key. # # Returns Hash[key => value] - Contract String => C::HashOf[String => C::Any] def parse_with_prefix(prefix) result = {} parsed_data.each do |raw_key, val| @@ -153,7 +147,6 @@ def parse_with_prefix(prefix) # Takes no arguments. # # Returns a Hash. - Contract C::None => C::HashOf[String => C::Any] def rules @rules ||= begin ignored_keys = %w[description] @@ -215,7 +208,6 @@ def rules # negative - An array of Hashes with rules. # # Returns appropriate and / or hash. - Contract C::ArrayOf[Hash], C::ArrayOf[Hash] => C::HashOf[String => C::Any] def affirmative_negative_rules(affirmative, negative) if negative.empty? # This is a simplified file. Just OR all the conditions together. (For @@ -242,7 +234,6 @@ def affirmative_negative_rules(affirmative, negative) # filename - Filename where rule is defined (used for error printing). # # Updates and returns array_to_update. - Contract C::ArrayOf[C::HashOf[String => String]], String, C::ArrayOf[C::HashOf[Symbol => String]], String => C::ArrayOf[C::HashOf[String => String]] def add_relevant_entries!(array_to_update, key, rule_items, filename) new_items = rule_items.reject { |item| expired?(item[:expiration], filename) }.map { |item| { key => item[:key] } } array_to_update.concat new_items @@ -253,7 +244,6 @@ def add_relevant_entries!(array_to_update, key, rule_items, filename) # Takes no arguments. # # Returns a Hash. - Contract C::None => C::HashOf[String => C::HashOf[String, C::ArrayOf[C::HashOf[Symbol, String]]]] def parsed_data @parsed_data ||= begin result = {} @@ -310,7 +300,6 @@ def parsed_data # val - The predicate string # # Returns a Hash. - Contract String => C::HashOf[Symbol, String] def parsed_predicate(val) v = val.sub(/\s*#.*\z/, "") return { key: v } unless v.include?(";") diff --git a/lib/entitlements/data/groups/calculated/yaml.rb b/lib/entitlements/data/groups/calculated/yaml.rb index 0a45a78..c89f484 100644 --- a/lib/entitlements/data/groups/calculated/yaml.rb +++ b/lib/entitlements/data/groups/calculated/yaml.rb @@ -16,7 +16,6 @@ class YAML < Entitlements::Data::Groups::Calculated::Base # Takes no arguments. # # Returns a Set[String] with DN's of the people in the group. - Contract C::None => C::Or[:calculating, C::SetOf[Entitlements::Models::Person]] def members @members ||= begin Entitlements.logger.debug "Calculating members from #{filename}" @@ -29,7 +28,6 @@ def members # Takes no arguments. # # Returns a String with the group description, or "" if undefined. - Contract C::None => String def description parsed_data.fetch("description", "") end @@ -41,7 +39,6 @@ def description # Format: namespace/major.minor.patch # # Returns a String with the schema version (k8s-style), or "entitlements/v1" if undefined. - Contract C::None => String def schema_version schema_version = parsed_data.fetch("schema_version", "entitlements/v1").to_s @@ -62,7 +59,6 @@ def schema_version # Takes no arguments. # # Returns Hash[key => value] - Contract C::None => C::HashOf[String => C::Any] def modifiers parsed_data.select { |k, _v| MODIFIERS.include?(k) } end @@ -74,7 +70,6 @@ def modifiers # Takes no arguments. # # Returns a Hash[String => :all/:none/List of strings]. - Contract C::None => C::HashOf[String => C::Or[:all, :none, C::ArrayOf[String]]] def initialize_filters result = Entitlements::Data::Groups::Calculated.filters_default return result unless parsed_data.key?("filters") @@ -123,7 +118,6 @@ def initialize_filters # Takes no arguments. # # Returns Hash[key => value] - Contract C::None => C::HashOf[String => C::Any] def initialize_metadata return {} unless parsed_data.key?("metadata") result = parsed_data["metadata"] @@ -146,7 +140,6 @@ def initialize_metadata # Takes no arguments. # # Returns a Hash. - Contract C::None => C::HashOf[String => C::Any] def rules @rules ||= begin rules_hash = parsed_data["rules"] @@ -162,7 +155,6 @@ def rules # rules_hash - Hash of rules. # # Returns the updated hash that has no expired rules in it. - Contract C::HashOf[String => C::Any] => C::HashOf[String => C::Any] def remove_expired_rules(rules_hash) if rules_hash.keys.size == 1 if rules_hash.values.first.is_a?(Array) @@ -183,7 +175,6 @@ def remove_expired_rules(rules_hash) # # Returns a Hash. # :nocov: - Contract C::None => C::HashOf[String => C::Any] def parsed_data @parsed_data ||= if RubyVersionCheck.ruby_version2? ::YAML.load(File.read(filename)).to_h diff --git a/lib/entitlements/data/people/yaml.rb b/lib/entitlements/data/people/yaml.rb index 526cbd8..a856315 100644 --- a/lib/entitlements/data/people/yaml.rb +++ b/lib/entitlements/data/people/yaml.rb @@ -73,7 +73,6 @@ def initialize(filename:, people: nil) # uid - Optionally a uid to return. If not specified, returns the entire hash. # # Returns Hash of { uid => Entitlements::Models::Person } or one Entitlements::Models::Person. - Contract C::Maybe[String] => C::Or[Entitlements::Models::Person, C::HashOf[String => Entitlements::Models::Person]] def read(uid = nil) @people ||= begin Entitlements.logger.debug "Loading people from #{filename.inspect}" diff --git a/lib/entitlements/extras/ldap_group/rules/ldap_group.rb b/lib/entitlements/extras/ldap_group/rules/ldap_group.rb index 9dd72e9..b91a24f 100644 --- a/lib/entitlements/extras/ldap_group/rules/ldap_group.rb +++ b/lib/entitlements/extras/ldap_group/rules/ldap_group.rb @@ -16,11 +16,6 @@ class LDAPGroup < Entitlements::Data::Groups::Calculated::Rules::Base # options - Optional hash of additional method-specific options # # Returns a Set[Entitlements::Models::Person]. - Contract C::KeywordArgs[ - value: String, - filename: C::Maybe[String], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::SetOf[Entitlements::Models::Person] def self.matches(value:, filename: nil, options: {}) Entitlements.cache[:ldap_cache] ||= {} Entitlements.cache[:ldap_cache][value] ||= begin diff --git a/lib/entitlements/extras/orgchart/logic.rb b/lib/entitlements/extras/orgchart/logic.rb index dee7bd6..ab334f0 100644 --- a/lib/entitlements/extras/orgchart/logic.rb +++ b/lib/entitlements/extras/orgchart/logic.rb @@ -28,7 +28,6 @@ def initialize(people:) # manager - Entitlements::Models::Person who is the manager or higher # # Returns a Set of Entitlements::Models::Person's. - Contract Entitlements::Models::Person => C::SetOf[Entitlements::Models::Person] def direct_reports(manager) manager_uid = manager.uid.downcase direct_reports_cache.key?(manager_uid) ? direct_reports_cache[manager_uid] : Set.new @@ -41,7 +40,6 @@ def direct_reports(manager) # manager - Entitlements::Models::Person who is the manager or higher # # Returns a Set of LDAP object Entitlements::Models::Persons. - Contract Entitlements::Models::Person => C::SetOf[Entitlements::Models::Person] def all_reports(manager) manager_uid = manager.uid.downcase all_reports_cache.key?(manager_uid) ? all_reports_cache[manager_uid] : Set.new @@ -53,7 +51,6 @@ def all_reports(manager) # person - Entitlements::Models::Person object # # Returns a Set of LDAP object openstructs. - Contract Entitlements::Models::Person => C::SetOf[Entitlements::Models::Person] def management_chain(person) person_uid = person.uid.downcase @@ -84,7 +81,6 @@ def management_chain(person) # manager. Cache this so that the iteration only occurs one time. # # Returns a Hash of { "dn" => Set(Entitlements::Models::Person) } - Contract C::None => C::HashOf[String => C::SetOf[Entitlements::Models::Person]] def direct_reports_cache return @direct_reports_cache if @direct_reports_cache @@ -111,7 +107,6 @@ def direct_reports_cache # manager. Cache this so that the iteration only occurs one time. # # Returns a Hash of { "dn" => Set(Entitlements::Models::Person) } - Contract C::None => C::HashOf[String => C::SetOf[Entitlements::Models::Person]] def all_reports_cache return @all_reports_cache if @all_reports_cache diff --git a/lib/entitlements/extras/orgchart/rules/direct_report.rb b/lib/entitlements/extras/orgchart/rules/direct_report.rb index 57adf7d..1b0b5c1 100644 --- a/lib/entitlements/extras/orgchart/rules/direct_report.rb +++ b/lib/entitlements/extras/orgchart/rules/direct_report.rb @@ -16,11 +16,6 @@ class DirectReport < Entitlements::Data::Groups::Calculated::Rules::Base # options - Optional hash of additional method-specific options # # Returns a Set[Entitlements::Models::Person]. - Contract C::KeywordArgs[ - value: String, - filename: C::Maybe[String], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::SetOf[Entitlements::Models::Person] def self.matches(value:, filename: nil, options: {}) # Construct the manager's DN and object. manager_uid = value.downcase diff --git a/lib/entitlements/extras/orgchart/rules/management.rb b/lib/entitlements/extras/orgchart/rules/management.rb index af0f7a0..5a7285f 100644 --- a/lib/entitlements/extras/orgchart/rules/management.rb +++ b/lib/entitlements/extras/orgchart/rules/management.rb @@ -16,11 +16,6 @@ class Management < Entitlements::Data::Groups::Calculated::Rules::Base # options - Optional hash of additional method-specific options # # Returns a Set[Entitlements::Models::Person]. - Contract C::KeywordArgs[ - value: String, - filename: C::Maybe[String], - options: C::Optional[C::HashOf[Symbol => C::Any]] - ] => C::SetOf[Entitlements::Models::Person] def self.matches(value:, filename: nil, options: {}) begin manager = Entitlements.cache[:people_obj].read(value)