Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
Signed-off-by: Jeremy Coffield <jcoffield@pivotal.io>
  • Loading branch information
Bharath Sekar authored and Jeremy Coffield committed May 8, 2017
2 parents 0ff99b7 + b7533da commit 8fa662f
Show file tree
Hide file tree
Showing 11 changed files with 188 additions and 29 deletions.
File renamed without changes.
11 changes: 11 additions & 0 deletions NOTICE
@@ -0,0 +1,11 @@
Copyright (c) 2015-Present CloudFoundry.org Foundation, Inc. All Rights Reserved.

This project contains software that is Copyright (c) 2012-2015 Pivotal Software, Inc.

This project is licensed to you under the Apache License, Version 2.0 (the "License").

You may not use this project except in compliance with the License.

This project may include a number of subcomponents with separate copyright notices
and license terms. Your use of these subcomponents is subject to the terms and
conditions of the subcomponent's license, as noted in the LICENSE file.
10 changes: 0 additions & 10 deletions NOTICE.TXT

This file was deleted.

9 changes: 5 additions & 4 deletions lib/uaa/cli/base.rb
Expand Up @@ -148,10 +148,10 @@ def opt_strs(opts)
}.join(' ')
end

def say_cmd_helper(info, suffix = nil)
def say_cmd_helper(info, topic, suffix = nil)
say_definition 2, info[:template], info[:desc]
info[:options].each do |o|
odef, desc = opt_help(o, @cli_class.option_defs[o])
odef, desc = opt_help(o, topic.option_defs[o] ? topic.option_defs[o]: @cli_class.option_defs[o])
say_definition help_col_start, "", desc ? "#{odef}, #{desc}" : odef
end
@output.print suffix
Expand All @@ -162,7 +162,7 @@ def say_command_help(args)
@cli_class.topics.each do |tpc|
tpc.commands.each do |k, v|
if args[0..v[:parts].length - 1] == v[:parts]
say_cmd_helper(v, "\n")
say_cmd_helper(v, tpc, "\n")
return "help command"
end
end
Expand All @@ -177,7 +177,7 @@ def say_help(topic = nil)
@cli_class.topics.each do |tpc|
next if topic && topic != tpc
@output.print "\n#{tpc.topic}\n"
tpc.commands.each { |k, v| say_cmd_helper v }
tpc.commands.each { |k, v| say_cmd_helper v, tpc }
end
if topic || !@cli_class.global_options
@output.print("\n")
Expand Down Expand Up @@ -229,6 +229,7 @@ def say_commands
class BaseCli

class << self
attr_writer :input
attr_reader :input, :output, :option_defs
attr_accessor :overview, :topics, :global_options
end
Expand Down
30 changes: 29 additions & 1 deletion lib/uaa/cli/common.rb
Expand Up @@ -103,14 +103,42 @@ def scim_common_list(type, filter)
}
end

def scim_get_user_object(scim, type, name, origin, attrs = nil)
origin_filter = origin ? " and origin eq \"#{origin}\"" : ''
query = { attributes: attrs, filter: "#{scim.name_attr(type)} eq \"#{name}\"#{origin_filter}"}
info = scim.all_pages(type, query)
raise BadResponse unless info.is_a?(Array)
raise NotFound if info.length == 0
if info.length >= 2
info.each_with_index do |i, idx|
puts "#{idx+1}: #{i['username']} from #{i['origin']}"
end

choice = @highline.ask("Select user: ").to_i
if choice > info.length || choice <= 0
raise ArgumentError 'bad input, klugscheisser'
end
info = info[choice - 1]
else
info = info[0]
end

# when getting whole object, handle case of UAA < 1.3 which did not return meta attr from query
attrs || !info["id"] || info["meta"] ? info : scim.get(type, info["id"])
end

def scim_get_object(scim, type, name, attrs = nil)
query = { attributes: attrs, filter: "#{scim.name_attr(type)} eq \"#{name}\""}
scim_get_helper(attrs, query, scim, type)
end

def scim_get_helper(attrs, query, scim, type)
info = scim.all_pages(type, query)
raise BadResponse unless info.is_a?(Array) && info.length < 2
raise NotFound if info.length == 0
info = info[0]
# when getting whole object, handle case of UAA < 1.3 which did not return meta attr from query
attrs || !info["id"] || info["meta"]? info : scim.get(type, info["id"])
attrs || !info["id"] || info["meta"] ? info : scim.get(type, info["id"])
end
end

Expand Down
15 changes: 9 additions & 6 deletions lib/uaa/cli/user.rb
Expand Up @@ -23,7 +23,8 @@ class UserCli < CommonCli
define_option :familyName, '--family_name <name>'
define_option :emails, '--emails <addresses>'
define_option :phoneNumbers, '--phones <phone_numbers>'
USER_INFO_OPTS = [:givenName, :familyName, :emails, :phoneNumbers]
define_option :origin, '--origin <identity provider origin, defaults to UAA>'
USER_INFO_OPTS = [:givenName, :familyName, :emails, :phoneNumbers, :origin]

def user_opts(info = {})
[:emails, :phoneNumbers].each do |o|
Expand All @@ -32,6 +33,7 @@ def user_opts(info = {})
end
n = [:givenName, :familyName].each_with_object({}) { |o, n| n[o] = opts[o] if opts[o] }
info[:name] = n unless n.empty?
info[:origin] = opts[:origin] if opts[:origin]
info
end

Expand All @@ -42,8 +44,8 @@ def user_opts(info = {})
scim_common_list(:user, filter)
end

desc 'user get [name]', 'Get specific user account', :attrs do |name|
pp scim_request { |sr| scim_get_object(sr, :user, username(name), opts[:attrs]) }
desc 'user get [name]', 'Get specific user account', :origin, :attrs do |name|
pp scim_request { |sr| scim_get_user_object(sr, :user, username(name), opts[:origin], opts[:attrs]) }
end

desc 'user add [name]', 'Add a user account', *USER_INFO_OPTS, :password do |name|
Expand All @@ -59,16 +61,17 @@ def user_opts(info = {})
*USER_INFO_OPTS, :del_attrs do |name|
return say 'no user updates specified' if (updates = user_opts).empty?
pp scim_request { |ua|
info = ua.get(:user, ua.id(:user, username(name)))
info = scim_get_user_object(ua, :user, username(name), opts[:origin])
opts[:del_attrs].each { |a| info.delete(a.to_s) } if opts[:del_attrs]
ua.put(:user, info.merge(updates))
'user account successfully updated'
}
end

desc 'user delete [name]', 'Delete user account' do |name|
desc 'user delete [name]', 'Delete user account', :origin do |name|
pp scim_request { |ua|
ua.delete(:user, ua.id(:user, username(name)))
user = scim_get_user_object(ua, :user, username(name), opts[:origin])
ua.delete(:user, user['id'])
'user account successfully deleted'
}
end
Expand Down
2 changes: 1 addition & 1 deletion lib/uaa/cli/version.rb
Expand Up @@ -14,6 +14,6 @@
# Cloud Foundry namespace
module CF
module UAA
CLI_VERSION = '3.10.0'
CLI_VERSION = '3.11.0'
end
end
26 changes: 21 additions & 5 deletions lib/uaa/stub/scim.rb
Expand Up @@ -60,7 +60,7 @@ class StubScim
LEGAL_ATTRS = {
user: [*COMMON_ATTRS, :displayname, :username, :nickname,
:profileurl, :title, :usertype, :preferredlanguage, :locale,
:timezone, :active, :password, :emails, :phonenumbers, :ims, :photos,
:timezone, :active, :password, :emails, :phonenumbers, :origin, :ims, :photos,
:entitlements, :roles, :x509certificates, :name, :addresses,
:authorizations, :groups].to_set,
client: [*COMMON_ATTRS, :client_id, :name, :client_secret, :authorities,
Expand Down Expand Up @@ -199,12 +199,16 @@ def initialize
end

def name(id, rtype = nil) (t = ref_by_id(id, rtype))? t[NAME_ATTR[t[:rtype]]]: nil end
def id(name, rtype) (t = ref_by_name(name, rtype))? t[:id] : nil end
def id(name, rtype)
name = append_origin_to_username(name, rtype, nil)
(t = ref_by_name(name, rtype))? t[:id] : nil
end

def add(rtype, stuff)
unless stuff.is_a?(Hash) && (name = stuff[NAME_ATTR[rtype].to_s])
raise SchemaViolation, "new #{rtype} has no name #{NAME_ATTR[rtype]}"
end
name = append_origin_to_username(name, rtype, stuff['origin'])
raise AlreadyExists if @things_by_name.key?(name = rtype.to_s + name.downcase)
enforce_schema(rtype, stuff)
thing = input(stuff).merge!(rtype: rtype, id: (id = SecureRandom.uuid),
Expand All @@ -225,9 +229,10 @@ def update(id, stuff, match_version = nil, match_type = nil)
if newname = new_thing[NAME_ATTR[rtype]]
oldname = rtype.to_s + thing[NAME_ATTR[rtype]].downcase
unless (newname = rtype.to_s + newname.downcase) == oldname
raise AlreadyExists if @things_by_name.key?(newname)
name = append_origin_to_username(newname, rtype, stuff['origin'])
raise AlreadyExists if @things_by_name.key?(name)
@things_by_name.delete(oldname)
@things_by_name[newname] = thing
@things_by_name[name] = thing
end
end
if new_thing[:members] || thing[:members]
Expand Down Expand Up @@ -293,8 +298,10 @@ def delete(id, rtype = nil)
return unless thing = ref_by_id(id, rtype)
rtype = thing[:rtype]
delete_user_groups(id, thing[:members])
origin = @things_by_id[id][:origin]
@things_by_id.delete(id)
thing = @things_by_name.delete(rtype.to_s + thing[NAME_ATTR[rtype]].downcase)
name = append_origin_to_username(rtype.to_s + thing[NAME_ATTR[rtype]].downcase, rtype, origin)
thing = @things_by_name.delete(name)
delete_references(id)
remove_attrs(output(thing))
end
Expand All @@ -309,10 +316,19 @@ def get_client_meta(client_id)
end

def get_by_name(name, rtype, *attrs)
name = append_origin_to_username(name, rtype, nil)
return unless thing = ref_by_name(name, rtype)
output(thing, attrs)
end

def append_origin_to_username(name, rtype, origin)
if rtype == :user
origin = origin || 'uaa'
name = "#{name}_#{origin}"
end
name
end

def find(rtype, opts = {})
filter, total, start = ScimFilter.new(opts[:filter]), 0, (opts[:start] || 0)
count, attrs, acl, acl_id = opts[:count], opts[:attrs], opts[:acl], opts[:acl_id]
Expand Down
10 changes: 10 additions & 0 deletions spec/common_spec.rb
Expand Up @@ -42,6 +42,16 @@ module CF::UAA
end
end

it "displays user help with -h has --origin option" do
Cli.run("user -h")
Cli.output.string.should include("--origin <identity provider origin, defaults to UAA>")
end

it "displays group help with -h has --origin option" do
Cli.run("group -h")
Cli.output.string.should include("--origin <origin>, map uaa scope to external group for this origin. Defaults to ldap.")
end

it "gets commands in bash completion format" do
Cli.run("help commands").should be
[/--no-version/, /--version/, /^#{File.basename($0)}/, /help/].each do |s|
Expand Down
2 changes: 1 addition & 1 deletion spec/info_spec.rb
Expand Up @@ -39,7 +39,7 @@ module CF::UAA

it "gets server info" do
Cli.run("info").should be
Cli.output.string.should match /\d.\d.\d/
Cli.output.string.should match /\d.\d+.\d+/
Cli.output.string.should include "prompts", "commit_id"
end

Expand Down
102 changes: 101 additions & 1 deletion spec/user_spec.rb
Expand Up @@ -29,7 +29,7 @@ module CF::UAA
@test_pwd = 'TesTpwd$%^'
@test_user = "tEst_UseR_#{Time.now.to_i}"
Cli.run("user add #{@test_user} -p #{@test_pwd} " +
'--emails sam@example.com,joNES@sample.com --given_name SamueL ' +
'--emails sam@example.com --given_name SamueL ' +
'--phones 801-555-1212 --family_name jonES').should be
end

Expand All @@ -42,6 +42,97 @@ module CF::UAA
Cli.output.string.should include 'success'
end

it 'does not set a origin (defaults to uaa through api)' do
Cli.run("user get #{@test_user.upcase}").should_not include 'origin'
end

it 'sets an origin when specified' do
user_with_origin = "#{@test_user}_with_origin"
create_user_by_origin( user_with_origin, 'ldap')
Cli.run("user delete #{user_with_origin}")
end

it 'updates origin when specified' do
user_with_origin = "#{@test_user}_with_origin"
create_user_by_origin( user_with_origin, 'ldap')
create_user_by_origin( user_with_origin, 'saml')

Cli.run("user update #{user_with_origin} --origin saml --given_name snoopy")

returned_user = Cli.run("user get #{user_with_origin.upcase} --origin saml")
returned_user['origin'].should match 'saml'
returned_user['name']['givenname'].should match 'snoopy'
Cli.run("user delete #{user_with_origin} --origin saml")
Cli.run("user delete #{user_with_origin} --origin ldap")
end

it 'gets user when origin specified' do
user_with_diff_origin = "same_username_with_two_origins"
create_user_by_origin( user_with_diff_origin, 'ldap')
create_user_by_origin( user_with_diff_origin, 'saml')

returned_user = Cli.run("user get #{user_with_diff_origin.upcase} --origin ldap")
returned_user['origin'].should match 'ldap'
Cli.run("user delete #{user_with_diff_origin} --origin ldap")
Cli.run("user delete #{user_with_diff_origin} --origin saml")
end

it 'gets user when origin not specified' do
Cli.input = StringIO.new("1") # selecting first origin through stdin
user_with_diff_origin = "same_username_with_two_origins"
create_user_by_origin( user_with_diff_origin, 'ldap')
create_user_by_origin( user_with_diff_origin, 'saml')

Cli.run("user get #{user_with_diff_origin.upcase}")

expect(Cli.output.string).to match 'Select user:'
expect(Cli.output.string).to match 'ldap'
Cli.run("user delete #{user_with_diff_origin} --origin ldap")
Cli.run("user delete #{user_with_diff_origin} --origin saml")
end

it 'deletes user when origin not specified' do
Cli.input = StringIO.new("2") # selecting first origin through stdin
user_with_diff_origin = "same_username_with_two_origins"
create_user_by_origin( user_with_diff_origin, 'ldap')
create_user_by_origin( user_with_diff_origin, 'saml')

Cli.run("user delete #{user_with_diff_origin.upcase}")

expect(Cli.output.string).to match 'Select user:'
expect(Cli.output.string).to match 'successfully deleted'
Cli.run("user get #{user_with_diff_origin.upcase} --origin saml")
expect(Cli.output.string).to match 'NotFound'
Cli.run("user delete #{user_with_diff_origin} --origin ldap")
end

it 'updates user when origin not specified' do
Cli.input = StringIO.new("2") # selecting first origin through stdin
user_with_diff_origin = "same_username_with_two_origins"
create_user_by_origin( user_with_diff_origin, 'ldap')
create_user_by_origin( user_with_diff_origin, 'saml')

Cli.run("user update #{user_with_diff_origin.upcase} --given_name rumpelstiltskin")

expect(Cli.output.string).to match 'Select user:'
expect(Cli.output.string).to match 'successfully updated'
Cli.run("user get #{user_with_diff_origin.upcase} --origin saml")
expect(Cli.output.string).to match 'rumpelstiltskin'

Cli.run("user delete #{user_with_diff_origin} --origin saml")
Cli.run("user delete #{user_with_diff_origin} --origin ldap")
end

it 'deletes user when origin specified' do
user_with_diff_origin = "same_username_with_two_origins"
create_user_by_origin( user_with_diff_origin, 'ldap')
create_user_by_origin( user_with_diff_origin, 'saml')

Cli.run("user delete #{user_with_diff_origin.upcase} --origin ldap")
Cli.output.string.should include 'successfully deleted'
Cli.run("user delete #{user_with_diff_origin} --origin saml")
end

it "fails to change a user's password with the wrong old pwd" do
Cli.run('password change -p newpwd --old_password not-the-password').should be_nil
end
Expand Down Expand Up @@ -84,6 +175,15 @@ module CF::UAA
Cli.output.string.should include 'active: true'
end

def create_user_by_origin(user_name, origin)
Cli.run("user add #{user_name} -p #{@test_pwd} " +
'--emails sam@example.com,joNES@sample.com --given_name SamueL ' +
"--phones 801-555-1212 --family_name jonES --origin #{origin}").should be
user_name = Cli.run("user get #{user_name.upcase} --origin #{origin}")
user_name['origin'].should match origin
user_name
end

describe 'get list of users' do
before :all do
i = 1
Expand Down

0 comments on commit 8fa662f

Please sign in to comment.