-
-
Notifications
You must be signed in to change notification settings - Fork 590
Expand file tree
/
Copy pathattributes.rb
More file actions
148 lines (129 loc) · 4.47 KB
/
attributes.rb
File metadata and controls
148 lines (129 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# frozen_string_literal: true
module RubySaml
# SAML2 Attributes. Parse the Attributes from the AttributeStatement of the SAML Response.
#
class Attributes
include Enumerable
attr_reader :attributes
# By default Attributes#[] is backwards compatible and
# returns only the first value for the attribute
# Setting this to `false` returns all values for an attribute
@@single_value_compatibility = true
# @return [Boolean] Get current status of backwards compatibility mode.
#
def self.single_value_compatibility
@@single_value_compatibility
end
# Sets the backwards compatibility mode on/off.
# @param value [Boolean]
#
def self.single_value_compatibility=(value)
@@single_value_compatibility = value
end
# @param attrs [Hash] The +attrs+ must be a Hash with attribute names as keys and **arrays** as values:
# Attributes.new({
# 'name' => ['value1', 'value2'],
# 'mail' => ['value1'],
# })
#
def initialize(attrs = {})
@attributes = attrs
end
# Iterate over all attributes
#
def each(&block)
attributes.each(&block)
end
# Test attribute presence by name
# @param name [String] The attribute name to be checked
#
def include?(name)
attributes.key?(canonize_name(name))
end
# Return first value for an attribute
# @param name [String] The attribute name
# @return [String] The value (First occurrence)
#
def single(name)
attributes[canonize_name(name)].first if include?(name)
end
# Return all values for an attribute
# @param name [String] The attribute name
# @return [Array] Values of the attribute
#
def multi(name)
attributes[canonize_name(name)]
end
# Retrieve attribute value(s)
# @param name [String] The attribute name
# @return [String|Array] Depending on the single value compatibility status this returns:
# - First value if single_value_compatibility = true
# response.attributes['mail'] # => '[email protected]'
# - All values if single_value_compatibility = false
# response.attributes['mail'] # => ['[email protected]','[email protected]']
#
def [](name)
self.class.single_value_compatibility ? single(canonize_name(name)) : multi(canonize_name(name))
end
# @return [Hash] Return all attributes as a hash
#
def all
attributes
end
# @param name [String] The attribute name
# @param values [Array] The values
#
def set(name, values)
attributes[canonize_name(name)] = values
end
alias_method :[]=, :set
# @param name [String] The attribute name
# @param values [Array] The values
#
def add(name, values = [])
attributes[canonize_name(name)] ||= []
attributes[canonize_name(name)] += Array(values)
end
# Make comparable to another Attributes collection based on attributes
# @param other [Attributes] An Attributes object to compare with
# @return [Boolean] True if it contains the same attributes and values
#
def ==(other)
if other.is_a?(Attributes)
all == other.all
else
super
end
end
# Fetch attribute value using name or regex
# @param name [String|Regexp] The attribute name
# @return [String|Array] Depending on the single value compatibility status this returns:
# - First value if single_value_compatibility = true
# response.attributes['mail'] # => '[email protected]'
# - All values if single_value_compatibility = false
# response.attributes['mail'] # => ['[email protected]','[email protected]']
#
def fetch(name)
attributes.each_key do |attribute_key|
if name.is_a?(Regexp)
if name.respond_to? :match?
return self[attribute_key] if name.match?(attribute_key)
elsif name.match(attribute_key)
return self[attribute_key]
end
elsif canonize_name(name) == canonize_name(attribute_key)
return self[attribute_key]
end
end
nil
end
protected
# stringifies all names so both 'email' and :email return the same result
# @param name [String] The attribute name
# @return [String] stringified name
#
def canonize_name(name)
name.to_s
end
end
end