diff --git a/src/riak_cs_control_formatting.erl b/src/riak_cs_control_formatting.erl index ab1cd92..52d70a6 100644 --- a/src/riak_cs_control_formatting.erl +++ b/src/riak_cs_control_formatting.erl @@ -12,25 +12,36 @@ -module(riak_cs_control_formatting). -author('Christopher Meiklejohn '). --export([strip_root_node/1, +-export([format_incoming_user/1, + format_users/1, format_user/1, iso8601/1]). -%% @spec strip_root_node(list()) -> list() -%% @doc Remove root node from user structure. -strip_root_node(Attributes) -> +%% @doc Format an incoming user for an S3 request. +%% @spec format_incoming_user(list()) -> list() +format_incoming_user(Attributes) -> {struct, [{<<"user">>, DecodedAttributes}]} = mochijson2:decode(Attributes), mochijson2:encode(DecodedAttributes). - -%% @spec format_user({term(), list()}) -> {term(), list()} -%% @doc Format a user object, by adding a admin key derived from the -%% running environment. -format_user({struct, Attributes}) -> +%% @doc Format a user, by ensuring that all keys are atomized. +%% @spec format_user(term()) -> term() +format_user({struct, _} = Attributes) -> + {struct, AttributeList} = atomize(Attributes), + {struct, append_admin_status(AttributeList)}; +format_user(Attributes) -> + Attributes. + +%% @doc Given a proplist of attributes, add admin status. +%% @spec append_admin_status(proplist()) -> proplist() +append_admin_status(Attributes) -> RiakCsAdminKey = riak_cs_control_configuration:cs_configuration(cs_admin_key), + BinaryAdminKey = list_to_binary(RiakCsAdminKey), KeyId = proplists:get_value(key_id, Attributes), - {struct, Attributes ++ {admin, KeyId =:= RiakCsAdminKey}}. + lists:append(Attributes, [{admin, KeyId =:= BinaryAdminKey}]). +%% @spec format_users(list()) -> list() +%% @doc Format an entire list of users. +format_users(Users) -> [format_user(User) || User <- Users]. %% @spec iso8601({{term(), term(), term()}, %% {term(), term(), term()}}) -> binary() @@ -39,3 +50,12 @@ iso8601({{Y,M,D},{H,I,S}}) -> iolist_to_binary( io_lib:format("~4..0b~2..0b~2..0bT~2..0b~2..0b~2..0bZ", [Y, M, D, H, I, S])). + +%% @doc Given a struct/proplist that we've received via JSON, +%% recursively turn the keys into atoms from binaries. +atomize({struct,L}) -> + {struct, [{binary_to_atom(I, utf8), atomize(J)} || {I, J} <- L]}; +atomize(L) when is_list(L) -> + [atomize(I) || I <- L]; +atomize(X) -> + X. diff --git a/src/riak_cs_control_session.erl b/src/riak_cs_control_session.erl index 90901b8..1d4048a 100644 --- a/src/riak_cs_control_session.erl +++ b/src/riak_cs_control_session.erl @@ -62,19 +62,23 @@ init([]) -> handle_call(get_users, _From, State) -> Response = handle_request({multipart_get, "users"}), - {reply, {ok, Response}, State}; + Users = riak_cs_control_formatting:format_users(Response), + {reply, {ok, Users}, State}; handle_call({get_user, KeyId}, _From, State) -> Response = handle_request({get, "user/" ++ KeyId}), - {reply, {ok, Response}, State}; + User = riak_cs_control_formatting:format_user(Response), + {reply, {ok, User}, State}; handle_call({put_user, Attributes}, _From, State) -> Response = handle_request({put, "user", Attributes}), - {reply, {ok, Response}, State}; + User = riak_cs_control_formatting:format_user(Response), + {reply, {ok, User}, State}; handle_call({put_user, KeyId, Attributes}, _From, State) -> Response = handle_request({put, "user/" ++ KeyId, Attributes}), - {reply, {ok, Response}, State}; + User = riak_cs_control_formatting:format_user(Response), + {reply, {ok, User}, State}; handle_call(_Request, _From, State) -> {reply, ok, State}. @@ -133,8 +137,7 @@ handle_request({multipart_get, Url}) -> case get_request(Url) of {ok, Content} -> riak_cs_control_multipart:parse_multipart_response(Content); - {error, Reason} -> - lager:info("Multipart request failed: ~s", [Reason]), + _ -> [] end; @@ -145,8 +148,7 @@ handle_request({get, Url}) -> {ok, Content} -> Body = proplists:get_value(content, Content), mochijson2:decode(Body); - {error, Reason} -> - lager:info("Get request failed: ~s", [Reason]), + _ -> empty_response() end; @@ -156,7 +158,6 @@ handle_request({put, Url, Body}) -> case put_request(Url, Body) of {ok, {_Headers, Body}} -> mochijson2:decode(Body); - {error, Reason} -> - lager:info("Put request failed: ~s", [Reason]), + _ -> empty_response() end. diff --git a/src/riak_cs_control_wm_user.erl b/src/riak_cs_control_wm_user.erl index f7a387f..44f32a8 100644 --- a/src/riak_cs_control_wm_user.erl +++ b/src/riak_cs_control_wm_user.erl @@ -90,7 +90,7 @@ from_json(ReqData, Context) -> case maybe_retrieve_user(Context, KeyId) of {true, NewContext} -> Attributes = wrq:req_body(ReqData), - NewAttributes = riak_cs_control_formatting:strip_root_node(Attributes), + NewAttributes = riak_cs_control_formatting:format_incoming_user(Attributes), case riak_cs_control_session:put_user(KeyId, NewAttributes) of {ok, _Response} -> Resource = "/users/" ++ KeyId, diff --git a/src/riak_cs_control_wm_users.erl b/src/riak_cs_control_wm_users.erl index ef57242..850a31a 100644 --- a/src/riak_cs_control_wm_users.erl +++ b/src/riak_cs_control_wm_users.erl @@ -56,7 +56,7 @@ post_is_create(ReqData, Context) -> %% @doc Extract key out of response from riak-cs. extract_key_id(User) -> {struct, UserDetails} = User, - binary_to_list(proplists:get_value(list_to_binary("key_id"), UserDetails)). + binary_to_list(proplists:get_value(key_id, UserDetails)). %% @doc Attempt to create the user if possible, and generate the path %% using the key_id of the new user. @@ -107,7 +107,7 @@ maybe_create_user(ReqData, Context) -> case Context#context.user of undefined -> Attributes = wrq:req_body(ReqData), - NewAttributes = riak_cs_control_formatting:strip_root_node(Attributes), + NewAttributes = riak_cs_control_formatting:format_incoming_user(Attributes), case riak_cs_control_session:put_user(NewAttributes) of {ok, Response} -> {true, Context#context{user=Response}};