cf-uaac 1.3.4 → 1.3.6
Sign up to get free protection for your applications and to get access to all the features.
- data/cf-uaac.gemspec +1 -1
- data/lib/cli/client_reg.rb +6 -6
- data/lib/cli/common.rb +18 -2
- data/lib/cli/config.rb +2 -0
- data/lib/cli/group.rb +43 -33
- data/lib/cli/token.rb +19 -22
- data/lib/cli/user.rb +6 -10
- data/lib/cli/version.rb +1 -1
- data/lib/stub/scim.rb +30 -12
- data/lib/stub/server.rb +1 -1
- data/lib/stub/uaa.rb +45 -25
- data/spec/client_reg_spec.rb +12 -12
- data/spec/group_spec.rb +101 -27
- data/spec/spec_helper.rb +9 -5
- data/spec/token_spec.rb +8 -3
- data/spec/user_spec.rb +5 -2
- metadata +8 -8
data/cf-uaac.gemspec
CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |s|
|
|
38
38
|
s.add_development_dependency "simplecov"
|
39
39
|
s.add_development_dependency "simplecov-rcov"
|
40
40
|
s.add_development_dependency "ci_reporter"
|
41
|
-
s.add_runtime_dependency "cf-uaa-lib", ">= 1.3.
|
41
|
+
s.add_runtime_dependency "cf-uaa-lib", ">= 1.3.6", "<= 1.3.6"
|
42
42
|
s.add_runtime_dependency "highline"
|
43
43
|
s.add_runtime_dependency "eventmachine"
|
44
44
|
s.add_runtime_dependency "launchy"
|
data/lib/cli/client_reg.rb
CHANGED
@@ -47,15 +47,15 @@ class ClientCli < CommonCli
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
desc "clients", "List client registrations" do
|
51
|
-
|
50
|
+
desc "clients [filter]", "List client registrations", :attrs, :start, :count do |filter|
|
51
|
+
scim_common_list(:client, filter)
|
52
52
|
end
|
53
53
|
|
54
|
-
desc "client get [name]", "Get specific client registration" do |name|
|
55
|
-
pp scim_request { |
|
54
|
+
desc "client get [name]", "Get specific client registration", :attrs do |name|
|
55
|
+
pp scim_request { |sr| scim_get_object(sr, :client, clientname(name), opts[:attrs]) }
|
56
56
|
end
|
57
57
|
|
58
|
-
define_option :clone, "--clone <
|
58
|
+
define_option :clone, "--clone <other>", "get default settings from other"
|
59
59
|
define_option :interact, "--[no-]interactive", "-i", "interactively verify all values"
|
60
60
|
|
61
61
|
desc "client add [name]", "Add client registration",
|
@@ -63,7 +63,7 @@ class ClientCli < CommonCli
|
|
63
63
|
pp scim_request { |cr|
|
64
64
|
opts[:client_id] = clientname(name)
|
65
65
|
opts[:secret] = verified_pwd("New client secret", opts[:secret])
|
66
|
-
defaults = opts[:clone] ? Util.hash_keys!(cr.get(opts[:clone]), :sym) : {}
|
66
|
+
defaults = opts[:clone] ? Util.hash_keys!(cr.get(:client, opts[:clone]), :sym) : {}
|
67
67
|
defaults.delete(:client_id)
|
68
68
|
cr.add(:client, client_info(defaults))
|
69
69
|
}
|
data/lib/cli/common.rb
CHANGED
@@ -80,6 +80,22 @@ class CommonCli < Topic
|
|
80
80
|
info
|
81
81
|
end
|
82
82
|
|
83
|
+
def scim_common_list(type, filter)
|
84
|
+
pp scim_request { |sr|
|
85
|
+
query = { attributes: opts[:attrs], filter: filter }
|
86
|
+
opts[:start] || opts[:count] ?
|
87
|
+
sr.query(type, query.merge!(startIndex: opts[:start], count: opts[:count])):
|
88
|
+
sr.all_pages(type, query)
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def scim_get_object(scim, type, name, attrs = nil)
|
93
|
+
query = { attributes: attrs, filter: "#{scim.name_attr(type)} eq \"#{name}\""}
|
94
|
+
info = scim.all_pages(type, query)
|
95
|
+
raise BadResponse unless info.is_a?(Array) && info.length < 2
|
96
|
+
raise NotFound if info.length == 0
|
97
|
+
info[0]
|
98
|
+
end
|
83
99
|
end
|
84
100
|
|
85
101
|
class MiscCli < CommonCli
|
@@ -141,8 +157,8 @@ class MiscCli < CommonCli
|
|
141
157
|
update_target_info(info) if info[:prompts]
|
142
158
|
end
|
143
159
|
return say "no target set" unless Config.target
|
144
|
-
return say "
|
145
|
-
say "
|
160
|
+
return say "\nTarget: #{Config.target}\n\n" unless Config.context
|
161
|
+
say "\nTarget: #{Config.target}\nContext: #{Config.context}, from client #{Config[:client_id]}\n\n"
|
146
162
|
end
|
147
163
|
|
148
164
|
desc "targets", "Display all targets" do
|
data/lib/cli/config.rb
CHANGED
@@ -120,6 +120,8 @@ class Config
|
|
120
120
|
@config[@target][:contexts][@context][attr]
|
121
121
|
end
|
122
122
|
|
123
|
+
def self.[](attr) value(attr) end
|
124
|
+
|
123
125
|
def self.delete_attr(attr)
|
124
126
|
raise ArgumentError, "target and context not set" unless @target && @context
|
125
127
|
@config[@target][:contexts][@context].delete(attr)
|
data/lib/cli/group.rb
CHANGED
@@ -24,25 +24,20 @@ class GroupCli < CommonCli
|
|
24
24
|
def gname(name) name || ask("Group name") end
|
25
25
|
|
26
26
|
desc "groups [filter]", "List groups", :attrs, :start, :count do |filter|
|
27
|
-
|
28
|
-
query = { attributes: opts[:attrs], filter: filter }
|
29
|
-
opts[:start] || opts[:count] ?
|
30
|
-
ua.query_groups(query.merge!(startIndex: opts[:start], count: opts[:count])):
|
31
|
-
ua.all_pages(:group, query)
|
32
|
-
}
|
27
|
+
scim_common_list(:group, filter)
|
33
28
|
end
|
34
29
|
|
35
|
-
desc "group get [name]", "Get specific group information" do |name|
|
36
|
-
pp scim_request { |
|
30
|
+
desc "group get [name]", "Get specific group information", :attrs do |name|
|
31
|
+
pp scim_request { |sr| scim_get_object(sr, :group, gname(name), opts[:attrs]) }
|
37
32
|
end
|
38
33
|
|
39
34
|
desc "group add [name]", "Adds a group" do |name|
|
40
|
-
pp scim_request { |
|
35
|
+
pp scim_request { |scim| scim.add(:group, displayName: gname(name)) }
|
41
36
|
end
|
42
37
|
|
43
38
|
desc "group delete [name]", "Delete group" do |name|
|
44
|
-
pp scim_request { |
|
45
|
-
|
39
|
+
pp scim_request { |scim|
|
40
|
+
scim.delete(:group, scim.id(:group, gname(name)))
|
46
41
|
"success"
|
47
42
|
}
|
48
43
|
end
|
@@ -55,31 +50,46 @@ class GroupCli < CommonCli
|
|
55
50
|
}
|
56
51
|
end
|
57
52
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
53
|
+
def update_members(scim, name, attr, users, add = true)
|
54
|
+
group = scim_get_object(scim, :group, gname(name))
|
55
|
+
old_ids = id_set(group[attr] || [])
|
56
|
+
new_ids = id_set(scim.ids(:user, *users))
|
57
|
+
if add
|
58
|
+
raise "not all users found, none added" unless new_ids.size == users.size
|
59
|
+
group[attr] = (old_ids + new_ids).to_a
|
60
|
+
raise "no new users given" unless group[attr].size > old_ids.size
|
61
|
+
else
|
62
|
+
raise "not all users found, none deleted" unless new_ids.size == users.size
|
63
|
+
group[attr] = (old_ids - new_ids).to_a
|
64
|
+
raise "no existing users to delete" unless group[attr].size < old_ids.size
|
65
|
+
group.delete(attr) if group[attr].empty?
|
66
|
+
end
|
67
|
+
scim.put(:group, group)
|
67
68
|
"success"
|
68
|
-
}
|
69
69
|
end
|
70
70
|
|
71
|
-
desc "member
|
72
|
-
pp scim_request { |
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
71
|
+
desc "member add [name] [users...]", "add members to a group" do |name, *users|
|
72
|
+
pp scim_request { |scim| update_members(scim, name, "members", users) }
|
73
|
+
end
|
74
|
+
|
75
|
+
desc "member delete [name] [users...]", "remove members from a group" do |name, *users|
|
76
|
+
pp scim_request { |scim| update_members(scim, name, "members", users, false) }
|
77
|
+
end
|
78
|
+
|
79
|
+
desc "group reader add [name] [users...]", "add users who can read the members" do |name, *users|
|
80
|
+
pp scim_request { |scim| update_members(scim, name, "readers", users) }
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "group reader delete [name] [users...]", "delete users who can read members" do |name, *users|
|
84
|
+
pp scim_request { |scim| update_members(scim, name, "readers", users, false) }
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "group writer add [name] [users...]", "add users who can modify group" do |name, *users|
|
88
|
+
pp scim_request { |scim| update_members(scim, name, "writers", users) }
|
89
|
+
end
|
90
|
+
|
91
|
+
desc "group writer delete [name] [users...]", "remove user who can modify group" do |name, *users|
|
92
|
+
pp scim_request { |scim| update_members(scim, name, "writers", users, false) }
|
83
93
|
end
|
84
94
|
|
85
95
|
end
|
data/lib/cli/token.rb
CHANGED
@@ -66,7 +66,16 @@ class TokenCli < CommonCli
|
|
66
66
|
topic "Tokens", "token", "login"
|
67
67
|
|
68
68
|
def say_success(grant)
|
69
|
-
say "\nSuccessfully fetched token via
|
69
|
+
say "\nSuccessfully fetched token via #{grant} grant.\nTarget: #{Config.target}\nContext: #{Config.context}, from client #{Config[:client_id]}\n\n"
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_context(token_info)
|
73
|
+
return gripe "attempt to get token failed\n" unless token_info && token_info["access_token"]
|
74
|
+
contents = TokenCoder.decode(token_info["access_token"], verify: false)
|
75
|
+
Config.context = contents["user_name"] || contents["client_id"] || "bad_token"
|
76
|
+
Config.add_opts(user_id: contents["user_id"]) if contents["user_id"]
|
77
|
+
Config.add_opts(client_id: contents["client_id"]) if contents["client_id"]
|
78
|
+
Config.add_opts token_info
|
70
79
|
end
|
71
80
|
|
72
81
|
def issuer_request(client_id, secret = nil)
|
@@ -83,7 +92,7 @@ class TokenCli < CommonCli
|
|
83
92
|
"Gets a token by posting user credentials with an implicit grant request",
|
84
93
|
:client, :scope do |*args|
|
85
94
|
client_name = opts[:client] || "vmc"
|
86
|
-
|
95
|
+
reply = issuer_request(client_name, "") { |ti|
|
87
96
|
prompts = ti.prompts
|
88
97
|
creds = {}
|
89
98
|
prompts.each do |k, v|
|
@@ -99,41 +108,31 @@ class TokenCli < CommonCli
|
|
99
108
|
end
|
100
109
|
ti.implicit_grant_with_creds(creds, opts[:scope]).info
|
101
110
|
}
|
102
|
-
|
103
|
-
tokinfo = TokenCoder.decode(token["access_token"], verify: false)
|
104
|
-
Config.context = tokinfo["user_name"]
|
105
|
-
Config.add_opts(user_id: tokinfo["user_id"])
|
106
|
-
Config.add_opts token
|
107
|
-
say_success "implicit (with posted credentials)"
|
111
|
+
say_success "implicit (with posted credentials)" if set_context(reply)
|
108
112
|
end
|
109
113
|
|
110
114
|
define_option :secret, "--secret <secret>", "-s", "client secret"
|
111
115
|
desc "token client get [name]",
|
112
116
|
"Gets a token with client credentials grant", :secret, :scope do |id|
|
113
|
-
|
114
|
-
return unless info = issuer_request(id, clientsecret) { |ti|
|
117
|
+
reply = issuer_request(clientname(id), clientsecret) { |ti|
|
115
118
|
ti.client_credentials_grant(opts[:scope]).info
|
116
119
|
}
|
117
|
-
|
118
|
-
Config.add_opts info
|
119
|
-
say_success "client credentials"
|
120
|
+
say_success "client credentials" if set_context(reply)
|
120
121
|
end
|
121
122
|
|
122
123
|
define_option :password, "-p", "--password <password>", "user password"
|
123
124
|
desc "token owner get [client] [user]", "Gets a token with a resource owner password grant",
|
124
125
|
:secret, :password, :scope do |client, user|
|
125
|
-
|
126
|
+
reply = issuer_request(clientname(client), clientsecret) { |ti|
|
126
127
|
ti.owner_password_grant(user = username(user), userpwd, opts[:scope]).info
|
127
128
|
}
|
128
|
-
|
129
|
-
Config.add_opts info
|
130
|
-
say_success "owner password"
|
129
|
+
say_success "owner password" if set_context(reply)
|
131
130
|
end
|
132
131
|
|
133
132
|
desc "token refresh [refreshtoken]", "Gets a new access token from a refresh token", :client, :secret, :scope do |rtok|
|
134
133
|
rtok ||= Config.value(:refresh_token)
|
135
|
-
|
136
|
-
say_success "refresh"
|
134
|
+
reply = issuer_request(clientname, clientsecret) { |ti| ti.refresh_token_grant(rtok, opts[:scope]).info }
|
135
|
+
say_success "refresh" if set_context(reply)
|
137
136
|
end
|
138
137
|
|
139
138
|
VMC_TOKEN_FILE = File.join ENV["HOME"], ".vmc_token"
|
@@ -156,9 +155,7 @@ class TokenCli < CommonCli
|
|
156
155
|
sleep 5
|
157
156
|
print "."
|
158
157
|
end
|
159
|
-
|
160
|
-
Config.add_opts catcher.info
|
161
|
-
say_success secret ? "authorization code" : "implicit"
|
158
|
+
say_success(secret ? "authorization code" : "implicit") if set_context(catcher.info)
|
162
159
|
return unless opts[:vmc]
|
163
160
|
begin
|
164
161
|
vmc_target = File.open(VMC_TARGET_FILE, 'r') { |f| f.read.strip }
|
data/lib/cli/user.rb
CHANGED
@@ -39,23 +39,18 @@ class UserCli < CommonCli
|
|
39
39
|
define_option :start, "--start <number>", "start of output page"
|
40
40
|
define_option :count, "--count <number>", "max number per page"
|
41
41
|
desc "users [filter]", "List user accounts", :attrs, :start, :count do |filter|
|
42
|
-
|
43
|
-
query = { attributes: opts[:attrs], filter: filter }
|
44
|
-
opts[:start] || opts[:count] ?
|
45
|
-
ua.query(:user, query.merge!(startIndex: opts[:start], count: opts[:count])):
|
46
|
-
ua.all_pages(:user, query)
|
47
|
-
}
|
42
|
+
scim_common_list(:user, filter)
|
48
43
|
end
|
49
44
|
|
50
|
-
desc "user get [name]", "Get specific user account" do |name|
|
51
|
-
pp scim_request { |
|
45
|
+
desc "user get [name]", "Get specific user account", :attrs do |name|
|
46
|
+
pp scim_request { |sr| scim_get_object(sr, :user, username(name), opts[:attrs]) }
|
52
47
|
end
|
53
48
|
|
54
49
|
desc "user add [name]", "Add a user account", *USER_INFO_OPTS, :password do |name|
|
55
50
|
info = {userName: username(name), password: verified_pwd("Password", opts[:password])}
|
56
|
-
pp scim_request { |ua|
|
51
|
+
pp scim_request { |ua|
|
57
52
|
ua.add(:user, user_opts(info))
|
58
|
-
"user account successfully added"
|
53
|
+
"user account successfully added"
|
59
54
|
}
|
60
55
|
end
|
61
56
|
|
@@ -97,6 +92,7 @@ class UserCli < CommonCli
|
|
97
92
|
define_option :old_password, "-o", "--old_password <password>", "current password"
|
98
93
|
desc "password change", "Change password for authenticated user in current context", :old_password, :password do
|
99
94
|
pp scim_request { |ua|
|
95
|
+
raise "no user_id in current context" unless Config.value(:user_id)
|
100
96
|
oldpwd = opts[:old_password] || ask_pwd("Current password")
|
101
97
|
ua.change_password(Config.value(:user_id), verified_pwd("New password", opts[:password]), oldpwd)
|
102
98
|
"password successfully changed"
|
data/lib/cli/version.rb
CHANGED
data/lib/stub/scim.rb
CHANGED
@@ -31,8 +31,9 @@ class StubScim
|
|
31
31
|
READ_ONLY_ATTRS = [:rtype, :id, :meta, :groups].to_set
|
32
32
|
BOOLEANS = [:active].to_set
|
33
33
|
NUMBERS = [:access_token_validity, :refresh_token_validity].to_set
|
34
|
-
GROUPS = [:groups, :
|
35
|
-
|
34
|
+
GROUPS = [:groups, :autoapprove, :scope, :authorities].to_set # values must be group ID
|
35
|
+
MEMBERSHIP = [:members, :writers, :readers].to_set # users or groups
|
36
|
+
REFERENCES = GROUPS + MEMBERSHIP # users or groups
|
36
37
|
ENUMS = { authorized_grant_types: ["client_credentials", "implicit",
|
37
38
|
"authorization_code", "password", "refresh_token"].to_set }
|
38
39
|
GENERAL_MULTI = [:emails, :phonenumbers, :ims, :photos, :entitlements,
|
@@ -57,9 +58,9 @@ class StubScim
|
|
57
58
|
:entitlements, :roles, :x509certificates, :name, :addresses,
|
58
59
|
:authorizations, :groups].to_set,
|
59
60
|
client: [*COMMON_ATTRS, :client_id, :client_secret, :authorities,
|
60
|
-
:authorized_grant_types, :scope, :
|
61
|
+
:authorized_grant_types, :scope, :autoapprove,
|
61
62
|
:access_token_validity, :refresh_token_validity, :redirect_uri].to_set,
|
62
|
-
group: [*COMMON_ATTRS, :displayname, :members, :
|
63
|
+
group: [*COMMON_ATTRS, :displayname, :members, :writers, :readers].to_set }
|
63
64
|
VISIBLE_ATTRS = {user: Set.new(LEGAL_ATTRS[:user] - HIDDEN_ATTRS),
|
64
65
|
client: Set.new(LEGAL_ATTRS[:client] - HIDDEN_ATTRS),
|
65
66
|
group: Set.new(LEGAL_ATTRS[:group] - HIDDEN_ATTRS)}
|
@@ -123,7 +124,7 @@ class StubScim
|
|
123
124
|
when *NUMBERS then v.is_a?(Integer)
|
124
125
|
when *GENERAL_MULTI then valid_multi?(v, GENERAL_SUBATTRS, true)
|
125
126
|
when *GROUPS then valid_ids?(v, :group)
|
126
|
-
when *
|
127
|
+
when *MEMBERSHIP then valid_ids?(v)
|
127
128
|
when ENUMS[k] then ENUMS[k].include?(v)
|
128
129
|
when *EXPLICIT_SINGLE.keys then valid_complex?(v, EXPLICIT_SINGLE[k])
|
129
130
|
when *EXPLICIT_MULTI.keys then valid_multi?(v, EXPLICIT_MULTI[k])
|
@@ -158,7 +159,11 @@ class StubScim
|
|
158
159
|
attrs.each_with_object({}) {|a, o|
|
159
160
|
next unless thing[a]
|
160
161
|
case a
|
161
|
-
when *
|
162
|
+
when *MEMBERSHIP
|
163
|
+
o[a] = thing[a].each_with_object([]) { |v, a|
|
164
|
+
a << { value: v, type: ref_by_id(v)[:rtype] }
|
165
|
+
}
|
166
|
+
when *GROUPS then o[a] = thing[a].to_a
|
162
167
|
when *GENERAL_MULTI then o[a] = thing[a].values
|
163
168
|
else o[a] = thing[a]
|
164
169
|
end
|
@@ -169,10 +174,16 @@ class StubScim
|
|
169
174
|
members.each {|m| (m[:groups] ||= Set.new) << gid if m = ref_by_id(m, :user)} if members
|
170
175
|
end
|
171
176
|
|
172
|
-
def
|
177
|
+
def delete_user_groups(gid, members)
|
173
178
|
members.each {|m| m[:groups].delete(gid) if m = ref_by_id(m, :user) } if members
|
174
179
|
end
|
175
180
|
|
181
|
+
def delete_references(id)
|
182
|
+
@things_by_id.each { |k, v|
|
183
|
+
REFERENCES.each { |a| v.delete(a) if v[a] && v[a].delete(id) && v[a].empty? }
|
184
|
+
}
|
185
|
+
end
|
186
|
+
|
176
187
|
public
|
177
188
|
|
178
189
|
def initialize; @things_by_id, @things_by_name = {}, {} end
|
@@ -208,7 +219,7 @@ class StubScim
|
|
208
219
|
if new_thing[:members] || thing[:members]
|
209
220
|
old_members = thing[:members] || Set.new
|
210
221
|
new_members = new_thing[:members] || Set.new
|
211
|
-
|
222
|
+
delete_user_groups(id, old_members - new_members)
|
212
223
|
add_user_groups(id, new_members - old_members)
|
213
224
|
end
|
214
225
|
READ_ONLY_ATTRS.each { |a| new_thing[a] = thing[a] if thing[a] }
|
@@ -225,18 +236,23 @@ class StubScim
|
|
225
236
|
add_user_groups(gid, Set[member])
|
226
237
|
end
|
227
238
|
|
239
|
+
def is_member(gid, member, attr = :members)
|
240
|
+
(g = ref_by_id(gid, :group)) && (a = g[attr]) && a.include?(member)
|
241
|
+
end
|
242
|
+
|
228
243
|
def set_hidden_attr(id, attr, value)
|
229
244
|
raise NotFound unless thing = ref_by_id(id)
|
230
245
|
raise ArgumentError unless HIDDEN_ATTRS.include?(attr)
|
231
246
|
thing[attr] = value
|
232
247
|
end
|
233
248
|
|
234
|
-
def
|
249
|
+
def delete(id, rtype = nil)
|
235
250
|
return unless thing = ref_by_id(id, rtype)
|
236
251
|
rtype = thing[:rtype]
|
237
|
-
|
252
|
+
delete_user_groups(id, thing[:members])
|
238
253
|
@things_by_id.delete(id)
|
239
254
|
thing = @things_by_name.delete(rtype.to_s + thing[NAME_ATTR[rtype]].downcase)
|
255
|
+
delete_references(id)
|
240
256
|
remove_attrs(output(thing))
|
241
257
|
end
|
242
258
|
|
@@ -250,10 +266,12 @@ class StubScim
|
|
250
266
|
output(thing, attrs)
|
251
267
|
end
|
252
268
|
|
253
|
-
def find(rtype,
|
254
|
-
filter, total = ScimFilter.new(
|
269
|
+
def find(rtype, opts = {})
|
270
|
+
filter, total, start = ScimFilter.new(opts[:filter]), 0, (opts[:start] || 0)
|
271
|
+
count, attrs, acl, acl_id = opts[:count], opts[:attrs], opts[:acl], opts[:acl_id]
|
255
272
|
objs = @things_by_id.each_with_object([]) { |(k, v), o|
|
256
273
|
next unless rtype == v[:rtype] && filter.match?(v)
|
274
|
+
next if acl && acl_id && !is_member(v[:id], acl_id, acl)
|
257
275
|
o << output(v, attrs) if total >= start && (count.nil? || o.length < count)
|
258
276
|
total += 1
|
259
277
|
}
|
data/lib/stub/server.rb
CHANGED
@@ -176,7 +176,7 @@ class Base
|
|
176
176
|
request.path.slice!(0..server.root.length - 1)
|
177
177
|
end
|
178
178
|
@match, handler = self.class.find_route(request)
|
179
|
-
server.logger.debug "processing request to path #{request.path}
|
179
|
+
server.logger.debug "processing #{request.method} to path #{request.path}"
|
180
180
|
send handler
|
181
181
|
reply.headers['connection'] ||= request.headers['connection'] if request.headers['connection']
|
182
182
|
server.logger.debug "replying to path #{request.path} with #{reply.body.length} bytes of #{reply.headers['content-type']}"
|
data/lib/stub/uaa.rb
CHANGED
@@ -30,23 +30,22 @@ class StubUAAConn < Stub::Base
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
contents["scope"], required_scope = Util.arglist(contents["scope"]), Util.arglist(required_scope)
|
37
|
-
return contents if required_scope.nil? || !(required_scope & contents["scope"]).empty?
|
38
|
-
reply_in_kind(403, error: "insufficient_scope",
|
39
|
-
error_description: "required scope #{Util.strlist(required_scope)}")
|
40
|
-
nil
|
41
|
-
end
|
42
|
-
|
33
|
+
def bad_request(msg = nil); reply_in_kind(400, error: "bad request#{msg ? ',' : ''} #{msg}") end
|
34
|
+
def not_found(name = nil); reply_in_kind(404, error: "#{name} not found") end
|
35
|
+
def access_denied(msg = "access denied") reply_in_kind(403, error: "access_denied", error_description: msg) end
|
43
36
|
def ids_to_names(ids); ids ? ids.map { |id| server.scim.name(id) } : [] end
|
44
37
|
def names_to_ids(names, rtype); names ? names.map { |name| server.scim.id(name, rtype) } : [] end
|
45
|
-
def bad_request(message = nil); reply_in_kind(400, error: "bad request#{message ? ',' : ''} #{message}") end
|
46
|
-
def not_found(name = nil); reply_in_kind(404, error: "#{name} not found") end
|
47
38
|
def encode_cookie(obj = {}) Util.json_encode64(obj) end
|
48
39
|
def decode_cookie(str) Util.json.decode64(str) end
|
49
40
|
|
41
|
+
def valid_token(accepted_scope)
|
42
|
+
return nil unless (ah = request.headers["authorization"]) && (ah = ah.split(' '))[0] =~ /^bearer$/i
|
43
|
+
contents = TokenCoder.decode(ah[1], accept_algorithms: "none")
|
44
|
+
contents["scope"], accepted_scope = Util.arglist(contents["scope"]), Util.arglist(accepted_scope)
|
45
|
+
return contents if accepted_scope.nil? || !(accepted_scope & contents["scope"]).empty?
|
46
|
+
access_denied("accepted scope #{Util.strlist(accepted_scope)}")
|
47
|
+
end
|
48
|
+
|
50
49
|
def primary_email(emails)
|
51
50
|
return unless emails
|
52
51
|
emails.each {|e| return e[:value] if e[:type] && e[:type] == "primary"}
|
@@ -325,12 +324,12 @@ class StubUAAConn < Stub::Base
|
|
325
324
|
# client endpoints
|
326
325
|
#
|
327
326
|
def client_to_scim(info)
|
328
|
-
['authorities', 'scope', '
|
327
|
+
['authorities', 'scope', 'autoapprove'].each { |a| info[a] = names_to_ids(info[a], :group) if info.key?(a) }
|
329
328
|
info
|
330
329
|
end
|
331
330
|
|
332
331
|
def scim_to_client(info)
|
333
|
-
[:authorities, :scope, :
|
332
|
+
[:authorities, :scope, :autoapprove].each { |a| info[a] = ids_to_names(info[a]) if info.key?(a) }
|
334
333
|
info.delete(:id)
|
335
334
|
info
|
336
335
|
end
|
@@ -362,7 +361,7 @@ class StubUAAConn < Stub::Base
|
|
362
361
|
|
363
362
|
route :delete, %r{^/oauth/clients/([^/]+)$} do
|
364
363
|
return unless valid_token("clients.write")
|
365
|
-
return not_found(match[1]) unless server.scim.
|
364
|
+
return not_found(match[1]) unless server.scim.delete(server.scim.id(match[1], :client))
|
366
365
|
end
|
367
366
|
|
368
367
|
route :put, %r{^/oauth/clients/([^/]+)/secret$}, "content-type" => %r{application/json} do
|
@@ -390,11 +389,25 @@ class StubUAAConn < Stub::Base
|
|
390
389
|
reply_in_kind server.scim.get(id, rtype, *StubScim::VISIBLE_ATTRS[rtype])
|
391
390
|
end
|
392
391
|
|
392
|
+
def obj_access?(rtype, oid, perm)
|
393
|
+
major_scope = perm == :writers ? "scim.write" : "scim.read"
|
394
|
+
return unless tkn = valid_token("#{major_scope} scim.me")
|
395
|
+
return tkn if tkn["scope"].include?(major_scope) ||
|
396
|
+
rtype == :group && server.scim.is_member(oid, tkn["user_id"], perm)
|
397
|
+
access_denied
|
398
|
+
end
|
399
|
+
|
393
400
|
route :put, %r{^/(Users|Groups)/([^/]+)$}, "content-type" => %r{application/json} do
|
394
|
-
return unless valid_token("scim.write")
|
395
401
|
rtype = match[1] == "Users"? :user : :group
|
396
|
-
|
397
|
-
|
402
|
+
return unless obj_access?(rtype, match[2], :writers)
|
403
|
+
version = request.headers['if-match']
|
404
|
+
version = version.to_i if version.to_i.to_s == version
|
405
|
+
begin
|
406
|
+
id = server.scim.update(match[2], Util.json_parse(request.body, :down), version, rtype)
|
407
|
+
reply_in_kind server.scim.get(id, rtype, *StubScim::VISIBLE_ATTRS[rtype])
|
408
|
+
rescue BadVersion; reply_in_kind(409, error: "invalid object version")
|
409
|
+
rescue NotFound; not_found(match[2])
|
410
|
+
end
|
398
411
|
end
|
399
412
|
|
400
413
|
def sanitize_int(arg, default, min, max = nil)
|
@@ -403,7 +416,7 @@ class StubUAAConn < Stub::Base
|
|
403
416
|
max && i > max ? max : i
|
404
417
|
end
|
405
418
|
|
406
|
-
def page_query(rtype, query, attrs)
|
419
|
+
def page_query(rtype, query, attrs, acl = nil, acl_id = nil)
|
407
420
|
if query['attributes']
|
408
421
|
attrs = attrs & Util.arglist(query['attributes']).each_with_object([]) {|a, o|
|
409
422
|
o << a.to_sym if StubScim::ATTR_NAMES.include?(a = a.downcase)
|
@@ -412,26 +425,33 @@ class StubUAAConn < Stub::Base
|
|
412
425
|
start = sanitize_int(query['startindex'], 1, 1)
|
413
426
|
count = sanitize_int(query['count'], 15, 1, 3000)
|
414
427
|
return bad_request("invalid startIndex or count") unless start && count
|
415
|
-
info, total = server.scim.find(rtype, start - 1, count
|
428
|
+
info, total = server.scim.find(rtype, start: start - 1, count: count,
|
429
|
+
filter: query['filter'], attrs: attrs, acl: acl, acl_id: acl_id)
|
416
430
|
reply_in_kind(resources: info, itemsPerPage: info.length, startIndex: start, totalResults: total)
|
417
431
|
end
|
418
432
|
|
419
433
|
route :get, %r{^/(Users|Groups)(\?|$)(.*)} do
|
420
|
-
return unless valid_token("scim.read")
|
421
434
|
rtype = match[1] == "Users"? :user : :group
|
422
|
-
|
435
|
+
return unless tkn = valid_token("scim.read scim.me")
|
436
|
+
acl = acl_id = nil
|
437
|
+
unless tkn["scope"].include?("scim.read")
|
438
|
+
acl, acl_id = :readers, tkn["user_id"]
|
439
|
+
return access_denied unless rtype == :group && acl_id
|
440
|
+
end
|
441
|
+
page_query(rtype, Util.decode_form(match[3], :down),
|
442
|
+
StubScim::VISIBLE_ATTRS[rtype], acl, acl_id)
|
423
443
|
end
|
424
444
|
|
425
445
|
route :get, %r{^/(Users|Groups)/([^/]+)$} do
|
426
|
-
return unless valid_token("scim.read")
|
427
446
|
rtype = match[1] == "Users"? :user : :group
|
447
|
+
return unless obj_access?(rtype, match[2], :readers)
|
428
448
|
return not_found(match[2]) unless obj = server.scim.get(match[2], rtype, *StubScim::VISIBLE_ATTRS[rtype])
|
429
449
|
reply_in_kind(obj)
|
430
450
|
end
|
431
451
|
|
432
452
|
route :delete, %r{^/(Users|Groups)/([^/]+)$} do
|
433
453
|
return unless valid_token("scim.write")
|
434
|
-
not_found(match[2]) unless server.scim.
|
454
|
+
not_found(match[2]) unless server.scim.delete(match[2], match[1] == "Users"? :user : :group)
|
435
455
|
end
|
436
456
|
|
437
457
|
route :put, %r{^/Users/([^/]+)/password$}, "content-type" => %r{application/json} do
|
@@ -465,7 +485,7 @@ class StubUAA < Stub::Server
|
|
465
485
|
@scim = StubScim.new
|
466
486
|
@auto_groups = ["password.write", "openid"]
|
467
487
|
.each_with_object([]) { |g, o| o << @scim.add(:group, 'displayname' => g) }
|
468
|
-
["scim.read", "scim.write", "uaa.resource"]
|
488
|
+
["scim.read", "scim.write", "scim.me", "uaa.resource"]
|
469
489
|
.each { |g| @scim.add(:group, 'displayname' => g) }
|
470
490
|
gids = ["clients.write", "clients.read", "clients.secret", "uaa.admin"]
|
471
491
|
.each_with_object([]) { |s, o| o << @scim.add(:group, 'displayname' => s) }
|
data/spec/client_reg_spec.rb
CHANGED
@@ -56,7 +56,7 @@ describe ClientCli do
|
|
56
56
|
|
57
57
|
it "fails to create a user account as test client" do
|
58
58
|
Cli.run("user add #{@test_user} -p #{@test_pwd}").should be_nil
|
59
|
-
Cli.output.string.should include "
|
59
|
+
Cli.output.string.should include "access_denied"
|
60
60
|
end
|
61
61
|
|
62
62
|
context "as updated client" do
|
@@ -73,7 +73,7 @@ describe ClientCli do
|
|
73
73
|
it "fails to create a user account with old token" do
|
74
74
|
Cli.run("context #{@test_client}").should be
|
75
75
|
Cli.run("user add #{@test_user} -p #{@test_pwd}").should be_nil
|
76
|
-
Cli.output.string.should include "
|
76
|
+
Cli.output.string.should include "access_denied"
|
77
77
|
end
|
78
78
|
|
79
79
|
it "creates a user account with a new token" do
|
@@ -81,7 +81,7 @@ describe ClientCli do
|
|
81
81
|
Cli.run("token client get #{@test_client} -s #{@test_secret}").should be
|
82
82
|
Cli.run("token decode")
|
83
83
|
Cli.run("user add #{@test_user.capitalize} -p #{@test_pwd} --email #{@test_user}@example.com --family_name #{@test_user.capitalize} --given_name joe").should be
|
84
|
-
Cli.output.string.should_not include "
|
84
|
+
Cli.output.string.should_not include "access_denied"
|
85
85
|
Cli.run("user get #{@test_user}").should be
|
86
86
|
Cli.output.string.should include @test_user.capitalize
|
87
87
|
end
|
@@ -89,15 +89,15 @@ describe ClientCli do
|
|
89
89
|
|
90
90
|
end
|
91
91
|
|
92
|
-
context "as admin client" do
|
93
|
-
it "deletes a client registration" do
|
94
|
-
client = @test_client.dup
|
95
|
-
@test_client.replace("")
|
96
|
-
Cli.run("context #{@admin_client}").should be
|
97
|
-
Cli.run("client delete #{client}").should be
|
98
|
-
Cli.output.string.should include "deleted"
|
99
|
-
end
|
100
|
-
end
|
92
|
+
# context "as admin client" do
|
93
|
+
# it "deletes a client registration" do
|
94
|
+
# client = @test_client.dup
|
95
|
+
# @test_client.replace("")
|
96
|
+
# Cli.run("context #{@admin_client}").should be
|
97
|
+
# Cli.run("client delete #{client}").should be
|
98
|
+
# Cli.output.string.should include "deleted"
|
99
|
+
# end
|
100
|
+
# end
|
101
101
|
|
102
102
|
end
|
103
103
|
|
data/spec/group_spec.rb
CHANGED
@@ -25,67 +25,141 @@ describe GroupCli do
|
|
25
25
|
Cli.configure("", nil, StringIO.new, true)
|
26
26
|
setup_target(authorities: "clients.read,scim.read,scim.write,uaa.admin")
|
27
27
|
Cli.run("token client get #{@test_client} -s #{@test_secret}").should be
|
28
|
-
@test_user, @test_pwd = "
|
28
|
+
@test_user, @test_pwd = "SaM_#{Time.now.to_i}_", "correcthorsebatterystaple"
|
29
29
|
@test_group = "JaNiToRs_#{Time.now.to_i}"
|
30
|
+
@users = ["w", "r", "m", "n"].map { |v| @test_user + v }
|
31
|
+
5.times { |i| @users << @test_user + i.to_s }
|
32
|
+
@users.each { |u| Cli.run("user add #{u} -p #{@test_pwd} --email sam@example.com").should be }
|
33
|
+
Cli.run("group add #{@test_group}").should be
|
34
|
+
Cli.run("groups -a displayName").should be
|
35
|
+
Cli.output.string.should include @test_group
|
30
36
|
end
|
31
37
|
|
32
|
-
after :all do
|
33
|
-
|
38
|
+
after :all do
|
39
|
+
Cli.run "context #{@test_client}"
|
40
|
+
@users.each { |u| Cli.run("user delete #{u}") }
|
41
|
+
@users.each { |u| Cli.run("user get #{u}").should be_nil }
|
42
|
+
Cli.run("group delete #{@test_group}").should be
|
43
|
+
cleanup_target
|
44
|
+
end
|
34
45
|
|
46
|
+
# actual user and group creation happens in before_all
|
35
47
|
it "creates many users and a group as the test client" do
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
"--family_name #{@test_user.capitalize} --given_name joe").should be }
|
42
|
-
Cli.run("group add #{@test_group}").should be
|
48
|
+
@users.each { |u|
|
49
|
+
Cli.run("user get #{u}").should be
|
50
|
+
Cli.output.string.should include u
|
51
|
+
}
|
52
|
+
@users.each { |u| Cli.run("member add scim.me #{u}").should be }
|
43
53
|
Cli.run("groups -a displayName").should be
|
44
54
|
Cli.output.string.should include @test_group
|
55
|
+
Cli.run("group get #{@test_group.upcase}").should be
|
56
|
+
Cli.output.string.should include @test_group
|
57
|
+
pending "real uaa can't add members to scim.read group yet" unless @stub_uaa
|
58
|
+
Cli.run("member add scim.read #{@test_user}w").should be
|
45
59
|
end
|
46
60
|
|
47
61
|
it "gets attributes with case-insensitive attribute names" do
|
48
|
-
Cli.run("groups -a
|
62
|
+
Cli.run("groups -a dISPLAYNAME").should be
|
49
63
|
Cli.output.string.should include @test_group
|
50
64
|
end
|
51
65
|
|
52
66
|
it "lists all users" do
|
53
67
|
Cli.run("users -a UsernamE").should be
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
it "preserves case in names" do
|
58
|
-
Cli.run("users -a username").should be
|
59
|
-
29.times { |i| Cli.output.string.should =~ /#{@test_user.capitalize}-#{i}/ }
|
68
|
+
@users.each { |u| Cli.output.string.should include u }
|
60
69
|
end
|
61
70
|
|
62
71
|
it "lists a page of users" do
|
63
|
-
Cli.run("users -a userName --count
|
64
|
-
Cli.output.string.should match /itemsPerPage:
|
72
|
+
Cli.run("users -a userName --count 4 --start 5").should be
|
73
|
+
Cli.output.string.should match /itemsPerPage: 4/i
|
65
74
|
Cli.output.string.should match /startIndex: 5/i
|
66
75
|
end
|
67
76
|
|
77
|
+
it "adds one user to the group" do
|
78
|
+
Cli.run("member add #{@test_group} #{@users[0]}").should be
|
79
|
+
Cli.output.string.should include "success"
|
80
|
+
end
|
81
|
+
|
68
82
|
it "adds users to the group" do
|
69
83
|
cmd = "member add #{@test_group}"
|
70
|
-
|
84
|
+
@users.each { |u| cmd << " #{u.upcase}" }
|
71
85
|
Cli.run(cmd).should be
|
72
86
|
Cli.output.string.should include "success"
|
73
87
|
end
|
74
88
|
|
75
|
-
|
76
|
-
Cli.
|
89
|
+
def check_members
|
90
|
+
ids = Cli.output.string.scan(/.*value:\s+([^\s]+)/).flatten
|
91
|
+
ids.size.should == @users.size
|
92
|
+
@users.each { |u|
|
93
|
+
Cli.run("user get #{u} -a id").should be
|
94
|
+
Cli.output.string =~ /.*id:\s+([^\s]+)/
|
95
|
+
ids.delete($1).should == $1
|
96
|
+
}
|
97
|
+
ids.should be_empty
|
98
|
+
end
|
99
|
+
|
100
|
+
it "lists all group members" do
|
101
|
+
Cli.run("group get #{@test_group} -a memBers").should be
|
102
|
+
check_members
|
103
|
+
end
|
104
|
+
|
105
|
+
it "adds one reader to the group" do
|
106
|
+
Cli.run("group reader add #{@test_group} #{@test_user}r").should be
|
107
|
+
Cli.output.string.should include "success"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "adds one writer to the group" do
|
111
|
+
Cli.run("group writer add #{@test_group} #{@test_user}w").should be
|
112
|
+
Cli.run("group reader add #{@test_group} #{@test_user}w").should be
|
77
113
|
Cli.output.string.should include "success"
|
78
114
|
end
|
79
115
|
|
116
|
+
it "gets readers and writers in the group" do
|
117
|
+
Cli.run("group get #{@test_group}").should be
|
118
|
+
Cli.output.string.should be
|
119
|
+
#puts Cli.output.string
|
120
|
+
end
|
121
|
+
|
122
|
+
it "reads members as a reader" do
|
123
|
+
Cli.run("token owner get #{@test_client} -s #{@test_secret} #{@test_user}r -p #{@test_pwd}").should be
|
124
|
+
Cli.run("group get #{@test_group} -a memBers").should be
|
125
|
+
ids = Cli.output.string.scan(/.*value:\s+([^\s]+)/).flatten
|
126
|
+
@users.size.should == ids.size
|
127
|
+
end
|
128
|
+
|
129
|
+
it "can't write members as a reader" do
|
130
|
+
pending "real uaa can't search for groups by name by scim.me/readers" unless @stub_uaa
|
131
|
+
Cli.run("token owner get #{@test_client} -s #{@test_secret} #{@test_user}r -p #{@test_pwd}").should be
|
132
|
+
Cli.run("member add #{@test_group} #{@test_user}z").should_not be
|
133
|
+
Cli.output.string.should include "access_denied"
|
134
|
+
end
|
135
|
+
|
136
|
+
it "adds a member as a writer" do
|
137
|
+
Cli.run "context #{@test_client}"
|
138
|
+
Cli.run("user add #{@test_user}z -p #{@test_pwd} --email sam@example.com").should be
|
139
|
+
@users << "#{@test_user}z"
|
140
|
+
Cli.run("token owner get #{@test_client} -s #{@test_secret} #{@test_user}w -p #{@test_pwd}").should be
|
141
|
+
Cli.run("member add #{@test_group} #{@test_user}z").should be
|
142
|
+
Cli.run("group get #{@test_group} -a memBers").should be
|
143
|
+
ids = Cli.output.string.scan(/.*value:\s+([^\s]+)/).flatten
|
144
|
+
@users.size.should == ids.size
|
145
|
+
# check_members
|
146
|
+
end
|
147
|
+
|
148
|
+
it "can't read members as a non-reader" do
|
149
|
+
pending "real uaa still returns members even if user is not in readers list" unless @stub_uaa
|
150
|
+
Cli.run("token owner get #{@test_client} -s #{@test_secret} #{@test_user}m -p #{@test_pwd}").should be
|
151
|
+
Cli.run("group get #{@test_group}").should be_nil
|
152
|
+
Cli.output.string.should include "NotFound"
|
153
|
+
end
|
154
|
+
|
80
155
|
it "deletes all members from a group" do
|
81
|
-
|
82
|
-
cmd = "member delete #{@test_group}
|
83
|
-
|
156
|
+
Cli.run "context #{@test_client}"
|
157
|
+
cmd = "member delete #{@test_group.downcase} "
|
158
|
+
@users.each { |u| cmd << " #{u.downcase}" }
|
84
159
|
Cli.run(cmd).should be
|
85
160
|
Cli.output.string.should include "success"
|
86
|
-
# and they should really be gone
|
87
161
|
Cli.run("group get #{@test_group}")
|
88
|
-
Cli.output.string.should_not match /members/i
|
162
|
+
Cli.output.string.should_not match /members/i # they should really be gone
|
89
163
|
end
|
90
164
|
|
91
165
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -42,8 +42,7 @@ module SpecHelper
|
|
42
42
|
# restriction that the given block cannot include rspec matchers.
|
43
43
|
def frequest(on_fiber, &blk)
|
44
44
|
return capture_exception(&blk) unless on_fiber
|
45
|
-
result = nil
|
46
|
-
cthred = Thread.current
|
45
|
+
result, cthred = nil, Thread.current
|
47
46
|
EM.schedule { Fiber.new { result = capture_exception(&blk); cthred.run }.resume }
|
48
47
|
Thread.stop
|
49
48
|
result
|
@@ -51,8 +50,9 @@ module SpecHelper
|
|
51
50
|
|
52
51
|
def setup_target(opts = {})
|
53
52
|
opts = { authorities: "clients.read,scim.read,scim.write,uaa.resource",
|
54
|
-
grant_types: "client_credentials,password",
|
55
|
-
scope: "openid,password.write"
|
53
|
+
grant_types: "client_credentials,password,refresh_token",
|
54
|
+
scope: "openid,password.write,scim.me,scim.read",
|
55
|
+
autoapprove: "openid,password.write,scim.me,scim.read"}.update(opts)
|
56
56
|
@admin_client = ENV["UAA_CLIENT_ID"] || "admin"
|
57
57
|
@admin_secret = ENV["UAA_CLIENT_SECRET"] || "adminsecret"
|
58
58
|
if ENV["UAA_CLIENT_TARGET"]
|
@@ -68,12 +68,16 @@ module SpecHelper
|
|
68
68
|
@test_secret = "+=tEsTsEcRet~!@"
|
69
69
|
Cli.run("client add #{test_client} -s #{@test_secret} " +
|
70
70
|
"--authorities #{opts[:authorities]} --scope #{opts[:scope]} " +
|
71
|
-
"--authorized_grant_types #{opts[:grant_types]}"
|
71
|
+
"--authorized_grant_types #{opts[:grant_types]} " +
|
72
|
+
"--autoapprove #{opts[:autoapprove]}").should be
|
72
73
|
opts.each { |k, a| Util.arglist(a).each {|v| Cli.output.string.should include(v) }}
|
73
74
|
@test_client = test_client
|
74
75
|
end
|
75
76
|
|
76
77
|
def cleanup_target
|
78
|
+
#Cli.run "context #{@test_client}"
|
79
|
+
#Cli.run("groups"); puts Cli.output.string
|
80
|
+
#Cli.run("users"); puts Cli.output.string
|
77
81
|
Cli.run("context #{@admin_client}")
|
78
82
|
if @test_client && !@test_client.empty?
|
79
83
|
Cli.run("client delete #{@test_client}").should be
|
data/spec/token_spec.rb
CHANGED
@@ -26,14 +26,19 @@ describe TokenCli do
|
|
26
26
|
setup_target(authorities: "clients.read,scim.read,scim.write,uaa.resource")
|
27
27
|
Cli.run("token client get #{@test_client} -s #{@test_secret}").should be
|
28
28
|
Config.yaml.should include("access_token")
|
29
|
-
@test_pwd = "
|
30
|
-
@test_user = "
|
29
|
+
@test_pwd = "@~`!$@%#%^$^&*)(|}{[]\":';?><,./"
|
30
|
+
@test_user = "test_user_#{Time.now.to_i}"
|
31
31
|
Cli.run("user add #{@test_user} -p #{@test_pwd} " +
|
32
32
|
"--emails sam@example.com,joNES@sample.com --given_name SamueL " +
|
33
33
|
"--phones 801-555-1212 --family_name jonES").should be
|
34
34
|
end
|
35
35
|
|
36
|
-
after :all do
|
36
|
+
after :all do
|
37
|
+
Cli.run "context #{@test_client}"
|
38
|
+
Cli.run("user delete #{@test_user}").should be
|
39
|
+
Cli.run("user get #{@test_user}").should be_nil
|
40
|
+
cleanup_target
|
41
|
+
end
|
37
42
|
|
38
43
|
it "logs in with implicit grant & posted credentials as a user" do
|
39
44
|
Cli.run("token get #{@test_user} #{@test_pwd}").should be
|
data/spec/user_spec.rb
CHANGED
@@ -28,12 +28,15 @@ describe UserCli do
|
|
28
28
|
Config.yaml.should include("access_token")
|
29
29
|
@test_pwd = "TesTpwd$%^"
|
30
30
|
@test_user = "tEst_UseR_#{Time.now.to_i}"
|
31
|
-
Cli.run("user add #{@test_user} -p #{@test_pwd} " +
|
31
|
+
Cli.run("user add #{@test_user} -p #{@test_pwd} " +
|
32
32
|
"--emails sam@example.com,joNES@sample.com --given_name SamueL " +
|
33
33
|
"--phones 801-555-1212 --family_name jonES").should be
|
34
34
|
end
|
35
35
|
|
36
|
-
after :all do
|
36
|
+
after :all do
|
37
|
+
Cli.run("user delete #{@test_user}")
|
38
|
+
cleanup_target
|
39
|
+
end
|
37
40
|
|
38
41
|
it "creates a user" do
|
39
42
|
Cli.output.string.should include "success"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cf-uaac
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-01-
|
16
|
+
date: 2013-01-29 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: bundler
|
@@ -118,10 +118,10 @@ dependencies:
|
|
118
118
|
requirements:
|
119
119
|
- - ! '>='
|
120
120
|
- !ruby/object:Gem::Version
|
121
|
-
version: 1.3.
|
121
|
+
version: 1.3.6
|
122
122
|
- - <=
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.3.
|
124
|
+
version: 1.3.6
|
125
125
|
type: :runtime
|
126
126
|
prerelease: false
|
127
127
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -129,10 +129,10 @@ dependencies:
|
|
129
129
|
requirements:
|
130
130
|
- - ! '>='
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: 1.3.
|
132
|
+
version: 1.3.6
|
133
133
|
- - <=
|
134
134
|
- !ruby/object:Gem::Version
|
135
|
-
version: 1.3.
|
135
|
+
version: 1.3.6
|
136
136
|
- !ruby/object:Gem::Dependency
|
137
137
|
name: highline
|
138
138
|
requirement: !ruby/object:Gem::Requirement
|
@@ -282,7 +282,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
282
282
|
version: '0'
|
283
283
|
segments:
|
284
284
|
- 0
|
285
|
-
hash:
|
285
|
+
hash: 4530157202147700966
|
286
286
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
287
287
|
none: false
|
288
288
|
requirements:
|
@@ -291,7 +291,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
291
291
|
version: '0'
|
292
292
|
segments:
|
293
293
|
- 0
|
294
|
-
hash:
|
294
|
+
hash: 4530157202147700966
|
295
295
|
requirements: []
|
296
296
|
rubyforge_project: cf-uaac
|
297
297
|
rubygems_version: 1.8.23
|