summaryrefslogtreecommitdiff
path: root/lib/chef_zero/endpoints/actor_endpoint.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef_zero/endpoints/actor_endpoint.rb')
-rw-r--r--lib/chef_zero/endpoints/actor_endpoint.rb113
1 files changed, 96 insertions, 17 deletions
diff --git a/lib/chef_zero/endpoints/actor_endpoint.rb b/lib/chef_zero/endpoints/actor_endpoint.rb
index 1572ac1..12fbe11 100644
--- a/lib/chef_zero/endpoints/actor_endpoint.rb
+++ b/lib/chef_zero/endpoints/actor_endpoint.rb
@@ -10,6 +10,7 @@ module ChefZero
class ActorEndpoint < RestObjectEndpoint
def delete(request)
result = super
+
if request.rest_path[0] == 'users'
list_data(request, [ 'organizations' ]).each do |org|
begin
@@ -18,12 +19,15 @@ module ChefZero
end
end
end
+
+ delete_actor_keys!(request)
result
end
def put(request)
# Find out if we're updating the public key.
request_body = FFI_Yajl::Parser.parse(request.body, :create_additions => false)
+
if request_body['public_key'].nil?
# If public_key is null, then don't overwrite it. Weird patchiness.
body_modified = true
@@ -33,17 +37,17 @@ module ChefZero
end
# Generate private_key if requested.
- if request_body.has_key?('private_key')
+ if request_body.key?('private_key')
body_modified = true
- if request_body['private_key']
+
+ if request_body.delete('private_key')
private_key, public_key = server.gen_key_pair
updating_public_key = true
request_body['public_key'] = public_key
end
- request_body.delete('private_key')
end
- # Save request
+ # Put modified body back in `request.body`
request.body = FFI_Yajl::Encoder.encode(request_body, :pretty => true) if body_modified
# PUT /clients is patchy
@@ -53,27 +57,29 @@ module ChefZero
# Inject private_key into response, delete public_key/password if applicable
if result[0] == 200 || result[0] == 201
+ client_or_user_name = identity_key_value(request) || request.rest_path[-1]
+
+ if is_rename?(request)
+ rename_keys!(request, client_or_user_name)
+ end
+
if request.rest_path[0] == 'users'
- key = nil
- identity_keys.each do |identity_key|
- key ||= request_body[identity_key]
- end
- key ||= request.rest_path[-1]
response = {
- 'uri' => build_uri(request.base_uri, [ 'users', key ])
+ 'uri' => build_uri(request.base_uri, [ 'users', client_or_user_name ])
}
else
response = FFI_Yajl::Parser.parse(result[2], :create_additions => false)
end
- if request.rest_path[2] == 'clients'
+ if client?(request)
response['private_key'] = private_key ? private_key : false
else
response['private_key'] = private_key if private_key
+ response.delete('public_key') unless updating_public_key
end
- response.delete('public_key') if !updating_public_key && request.rest_path[2] == 'users'
response.delete('password')
+
json_response(result[0], response)
else
result
@@ -81,13 +87,86 @@ module ChefZero
end
def populate_defaults(request, response_json)
- response = FFI_Yajl::Parser.parse(response_json, :create_additions => false)
- if request.rest_path[2] == 'clients'
- response = ChefData::DataNormalizer.normalize_client(response,request.rest_path[3], request.rest_path[1])
+ response = FFI_Yajl::Parser.parse(response_json, create_additions: false)
+
+ populated_response =
+ if client?(request)
+ ChefData::DataNormalizer.normalize_client(
+ response,
+ response["name"] || request.rest_path[-1],
+ request.rest_path[1]
+ )
+ else
+ ChefData::DataNormalizer.normalize_user(
+ response,
+ response["username"] || request.rest_path[-1],
+ identity_keys,
+ server.options[:osc_compat],
+ request.method
+ )
+ end
+
+ FFI_Yajl::Encoder.encode(populated_response, pretty: true)
+ end
+
+ private
+
+ # Move key data to new path
+ def rename_keys!(request, new_client_or_user_name)
+ orig_keys_path = keys_path_base(request)
+ new_keys_path = orig_keys_path.dup
+ .tap {|path| path[-2] = new_client_or_user_name }
+
+ key_names = list_data_or_else(request, orig_keys_path, nil)
+ return unless key_names # No keys to move
+
+ key_names.each do |key_name|
+ # Get old data
+ orig_path = [ *orig_keys_path, key_name ]
+ data = get_data(request, orig_path, :data_store_exceptions)
+
+ # Copy data to new path
+ create_data(
+ request,
+ new_keys_path, key_name,
+ data,
+ :create_dir
+ )
+ end
+
+ # Delete original data
+ delete_data_dir(request, orig_keys_path, :recursive, :data_store_exceptions)
+ end
+
+ def delete_actor_keys!(request)
+ path = keys_path_base(request)[0..-2]
+ delete_data_dir(request, path, :recursive, :data_store_exceptions)
+ rescue DataStore::DataNotFoundError
+ end
+
+ def client?(request, rest_path=nil)
+ rest_path ||= request.rest_path
+ request.rest_path[2] == "clients"
+ end
+
+ # Return the data store keys path for the request client or user, e.g.
+ #
+ # [ "organizations", <org>, "client_keys", <client>, "keys" ]
+ #
+ # Or:
+ #
+ # [ "user_keys", <user>, "keys" ]
+ #
+ def keys_path_base(request, client_or_user_name=nil)
+ rest_path = (rest_path || request.rest_path).dup
+ rest_path[-1] = client_or_user_name if client_or_user_name
+
+ if client?(request, rest_path)
+ [ *rest_path[0..1], "client_keys" ]
else
- response = ChefData::DataNormalizer.normalize_user(response, request.rest_path[3], identity_keys, server.options[:osc_compat], request.method)
+ [ "user_keys" ]
end
- FFI_Yajl::Encoder.encode(response, :pretty => true)
+ .push(rest_path.last, "keys")
end
end
end