lib/uaa/scim.rb in cf-uaa-lib-3.2.4 vs lib/uaa/scim.rb in cf-uaa-lib-3.2.5

- old
+ new

@@ -53,10 +53,16 @@ "externalid" => "externalId", "phonenumbers" => "phoneNumbers", "startindex" => "startIndex"}[kd] kc || kd end + def headers() + hdrs = { 'authorization' => @auth_header } + hdrs['X-Identity-Zone-Subdomain'] = @zone if @zone + hdrs + end + # This is very inefficient and should be unnecessary. SCIM (1.1 and early # 2.0 drafts) specify that attribute names are case insensitive. However # in the UAA attribute names are currently case sensitive. This hack takes # a hash with keys as symbols or strings and with any case, and forces # the attribute name to the case that the uaa expects. @@ -100,12 +106,14 @@ def initialize(target, auth_header, options = {}) @target, @auth_header = target, auth_header @key_style = options[:symbolize_keys] ? :downsym : :down self.skip_ssl_validation = options[:skip_ssl_validation] self.ssl_ca_file = options[:ssl_ca_file] + self.ssl_cert_store = options[:ssl_cert_store] self.http_proxy = options[:http_proxy] self.https_proxy = options[:https_proxy] + @zone = options[:zone] end # Convenience method to get the naming attribute, e.g. userName for user, # displayName for group, client_id for client. # @param type (see #add) @@ -118,31 +126,31 @@ # each type of object see {Scim}. # @return [Hash] contents of the object, including its +id+ and meta-data. def add(type, info) path, info = type_info(type, :path), force_case(info) reply = json_parse_reply(@key_style, *json_post(@target, path, info, - "authorization" => @auth_header)) + headers)) fake_client_id(reply) if type == :client # hide client reply, not quite scim reply end # Deletes a SCIM resource # @param type (see #add) # @param [String] id the id attribute of the SCIM object # @return [nil] def delete(type, id) - http_delete @target, "#{type_info(type, :path)}/#{URI.encode(id)}", @auth_header + http_delete @target, "#{type_info(type, :path)}/#{URI.encode(id)}", @auth_header, @zone end # Replaces the contents of a SCIM object. # @param (see #add) # @return (see #add) def put(type, info) path, info = type_info(type, :path), force_case(info) ida = type == :client ? 'client_id' : 'id' raise ArgumentError, "info must include #{ida}" unless id = info[ida] - hdrs = {'authorization' => @auth_header} + hdrs = headers if info && info['meta'] && (etag = info['meta']['version']) hdrs.merge!('if-match' => etag) end reply = json_parse_reply(@key_style, *json_put(@target, "#{path}/#{URI.encode(id)}", info, hdrs)) @@ -156,11 +164,11 @@ # @return (see #add) def patch(type, info) path, info = type_info(type, :path), force_case(info) ida = type == :client ? 'client_id' : 'id' raise ArgumentError, "info must include #{ida}" unless id = info[ida] - hdrs = {'authorization' => @auth_header} + hdrs = headers if info && info['meta'] && (etag = info['meta']['version']) hdrs.merge!('if-match' => etag) end reply = json_parse_reply(@key_style, *json_patch(@target, "#{path}/#{URI.encode(id)}", info, hdrs)) @@ -187,11 +195,11 @@ attrs = Util.arglist(attrs).map {|a| force_attr(a)} query['attributes'] = Util.strlist(attrs, ",") end qstr = query.empty?? '': "?#{Util.encode_form(query)}" info = json_get(@target, "#{type_info(type, :path)}#{qstr}", - @key_style, 'authorization' => @auth_header) + @key_style, headers) unless info.is_a?(Hash) && info[rk = jkey(:resources)].is_a?(Array) # hide client endpoints that are not yet scim compatible if type == :client && info.is_a?(Hash) info = info.each{ |k, v| fake_client_id(v) }.values @@ -210,11 +218,11 @@ # Get information about a specific object. # @param (see #delete) # @return (see #add) def get(type, id) info = json_get(@target, "#{type_info(type, :path)}/#{URI.encode(id)}", - @key_style, 'authorization' => @auth_header) + @key_style, headers) fake_client_id(info) if type == :client # hide client reply, not quite scim info end @@ -286,12 +294,11 @@ # @return [Hash] success message from server def change_password(user_id, new_password, old_password = nil) req = {"password" => new_password} req["oldPassword"] = old_password if old_password json_parse_reply(@key_style, *json_put(@target, - "#{type_info(:user, :path)}/#{URI.encode(user_id)}/password", req, - 'authorization' => @auth_header)) + "#{type_info(:user, :path)}/#{URI.encode(user_id)}/password", req, headers)) end # Change client secret. # * For a client to change its own secret, the token in @auth_header must contain # "client.secret" scope and the correct +old_secret+ must be given. @@ -303,30 +310,28 @@ # @return [Hash] success message from server def change_secret(client_id, new_secret, old_secret = nil) req = {"secret" => new_secret } req["oldSecret"] = old_secret if old_secret json_parse_reply(@key_style, *json_put(@target, - "#{type_info(:client, :path)}/#{URI.encode(client_id)}/secret", req, - 'authorization' => @auth_header)) + "#{type_info(:client, :path)}/#{URI.encode(client_id)}/secret", req, headers)) end def map_group(group, is_id, external_group) key_name = is_id ? :groupId : :displayName request = {key_name => group, :externalGroup => external_group, :schemas => ["urn:scim:schemas:core:1.0"] } result = json_parse_reply(@key_style, *json_post(@target, "#{type_info(:group_mapping, :path)}", request, - 'authorization' => @auth_header)) + headers)) result end def unmap_group(group_id, external_group) http_delete(@target, "#{type_info(:group_mapping, :path)}/id/#{group_id}/#{URI.encode(external_group)}", - @auth_header) + @auth_header, @zone) end def list_group_mappings(start = nil, count = nil) - json_get(@target, "#{type_info(:group_mapping, :path)}/list?startIndex=#{start}&count=#{count}", @key_style, 'authorization' => @auth_header) + json_get(@target, "#{type_info(:group_mapping, :path)}/list?startIndex=#{start}&count=#{count}", @key_style, headers) end end end -