diff --git a/apps/roster/src/rest/helpers/rest_main_helper.erl b/apps/roster/src/rest/helpers/rest_main_helper.erl index 2b46f3929ed91933d2a104ac17ebfd5ff8ad96f7..759ab010b57801f39f1e93d3c371a57b11665ddd 100644 --- a/apps/roster/src/rest/helpers/rest_main_helper.erl +++ b/apps/roster/src/rest/helpers/rest_main_helper.erl @@ -4,17 +4,14 @@ -include("roster.hrl"). -include_lib("roster/include/static/rest_text.hrl"). -include_lib("n2o/include/n2o.hrl"). --export([ - description/0, - rest_pid/0, send_to_mqtt/1, send_to_mqtt/2, - get_query_value/2, get_body_value/2, get_body_values/2, get_query_values/2, get_request_headers/2, - check_params_missing/2, - is_base64/1, validate_msg_to_publish/1, - get_profile_by_phone/1, get_phone_number/1, get_client_phone_id/1 -]). -description() -> "Rest Helpers Module". +-export([ description/0 + , rest_pid/0 + , send_to_mqtt/1 + , send_to_mqtt/2 + ]). +description() -> "Rest Helpers Module". -define(REST_HELPER_NAME, rest_main_helper). @@ -40,112 +37,4 @@ send_to_mqtt(Msg) -> ok. send_to_mqtt(sync, Msg) -> -%% NOTE! Debug info is commented under the message -%% {cx,[],[],[],api,[],[],<<>>,bert,<<"sys_rest">>,<<"4">>,<0.1067.0>,[], <<"actions/1/api/sys_rest">>,<<"1">>} -%% #cx{handlers = [],actions = [],req = [],module = api, -%% lang = [],path = [],session = <<>>,formatter = bert, -%% params = <<"sys_rest">>,node = <<"4">>, -%% client_pid = <0.1067.0>,state = [], -%% from = <<"actions/1/api/sys_rest">>,vsn = <<"1">>} roster_proto:info(Msg, [], #cx{params = ?SYS_REST_CLIENT, client_pid = rest_pid()}). - -get_query_value(QuerySet, Key) -> - case lists:keyfind(Key, 1, QuerySet) of - false -> {error, ?ERROR_MISSING_PARAM}; - {Key, Value} -> {ok, Value} - end. - -get_body_value(ReqBody, Key) -> - case to_json(ReqBody) of - R = {error, _} -> R; - {ok, JsonReqBody} -> - case proplists:get_value(nitro:to_binary(Key), JsonReqBody) of - undefined -> {error, ?ERROR_MISSING_PARAM}; - Val -> {ok, Val} - end - end. - -get_body_values(ReqBody, Keys) -> - lists:foldl(fun(Key, Acc) -> - case get_body_value(ReqBody, Key) of - {error, _} -> Acc; - {ok, Val} -> Acc ++ [{nitro:to_binary(Key), Val}] - end - end, [], Keys). - -get_query_values(ReqBody, Keys) -> - lists:foldl(fun(Key, Acc) -> - case get_query_value(ReqBody, Key) of - {error, _} -> Acc; - {ok, Val} -> Acc ++ [{nitro:to_binary(Key), Val}] - end - end, [], Keys). - -get_request_headers(Req, Keys) -> - lists:foldl(fun(Key, Acc) -> - case Req:get_header_value(Key) of - undefined -> Acc; - Val -> Acc ++ [{nitro:to_binary(Key), Val}] - end - end, [], Keys). - -check_params_missing(ExpectedParams, ActualParams) -> - if - length(ExpectedParams) /= length(ActualParams) -> {error, ?ERROR_MISSING_PARAM}; - length(ExpectedParams) == length(ActualParams) -> {ok, ActualParams} - end. - - -to_json(ReqBody) -> - case jsx:is_json(ReqBody) of - false -> {error, ?ERROR_INVALID_JSON}; - _ -> {ok, jsx:decode(ReqBody)} - end. - -%% TODO refactor it. Join with is_base64 fun if it is possible -validate_msg_to_publish(Data) -> -%% check is message data base64 encodded bytearray - try - binary_to_list(base64:decode(Data)) - catch E:R -> - ?LOG_INFO("~p:~pBase64 Decoding Error! ~p", [E, R, Data]), - false - end. - -is_base64(Data) -> - try - base64:decode(Data), - true - catch E:R -> - ?LOG_INFO("~p:~pBase64DecodingError! ~p", [E, R, Data]), - false - end. - -%% TODO remove this method to DB helper - -get_profile_by_phone(PhoneNumber) -> - case kvs:get('Profile', nitro:to_binary(PhoneNumber)) of - ErrorResponse = {error, _} -> ErrorResponse; - SuccessResponse = {ok, _} -> SuccessResponse - end. - -get_phone_number(PhoneId) when not is_binary(PhoneId) -> - get_phone_number(nitro:to_binary(PhoneId)); -get_phone_number(PhoneId) -> -%% get phone number from phone id - case roster:parts_phone_id(PhoneId) of - {error, _} -> PhoneId; - [Phone, _] -> Phone - end. - -get_client_phone_id(Req) -> - case Req:get_header_value("Authorization") of - "Bearer" ++ BearerAuth -> - [_, CId] = string:split(BearerAuth, "/"), - case kvs:get('Auth', list_to_binary(CId)) of - {ok, #'Auth'{user_id = PhoneId}} -> PhoneId; - _ -> throw(authentication_error) - end; - _ -> - throw(authentication_error) - end. diff --git a/apps/roster/src/rest/rest_cowboy_cri_handler.erl b/apps/roster/src/rest/rest_cowboy_cri_handler.erl index f85ac626fc408e44bec2224c060c61be580c0c2e..982a8db1d32cb9507a7c88767ec1a0c91da4b0ff 100644 --- a/apps/roster/src/rest/rest_cowboy_cri_handler.erl +++ b/apps/roster/src/rest/rest_cowboy_cri_handler.erl @@ -95,14 +95,20 @@ malformed_request(Req, State) -> init_phone_header(Req, State) -> case cowboy_req:header(<<"phoneid">>, Req, undefined) of undefined -> throw({init_error, ?ERROR_MISSING_HEADER}); - PhoneHeader -> State#{phone_number => rest_main_helper:get_phone_number(PhoneHeader), + PhoneHeader -> State#{phone_number => get_phone_number(PhoneHeader), phone_id => PhoneHeader } end. +get_phone_number(PhoneNumber) -> + case roster:parts_phone_id(PhoneNumber) of + {error, _} -> PhoneNumber; + [Phone, _] -> Phone + end. + %% NOTE: Exposes information about DB, so it must be handled after authorization check_profile(#{ phone_number := PhoneId}) -> - case rest_main_helper:get_profile_by_phone(PhoneId) of + case kvs:get('Profile', nitro:to_binary(PhoneId)) of {error, _} -> throw({init_error, ""}); %% TODO: Mimicking existing response. {ok, _} -> ok end. @@ -226,7 +232,7 @@ member_tuples(PhoneId, RoomId) -> {<<"is_admin">>, Status =:= admin}, {<<"is_member">>, true}]; [] -> - PhoneNumber = rest_main_helper:get_phone_number(PhoneId), + PhoneNumber = get_phone_number(PhoneId), case kvs:get('Profile', nitro:to_binary(PhoneNumber)) of {error, _} -> [{<<"phone_id">>, PhoneId}, @@ -309,15 +315,16 @@ new_room_member_from_json(Req, #{phone_id := AdminPhoneId} = State) -> parse_new_room_members_body(Body) -> %% room_id, join - always required %% if join == false - phone_ids required - case rest_main_helper:get_body_value(Body, <<"room_id">>) of + ParsedBody = json_parse_body(Body), + case get_body_value(<<"room_id">>, ParsedBody) of {ok, RoomId} -> - case rest_main_helper:get_body_value(Body, <<"join">>) of + case get_body_value(<<"join">>, ParsedBody) of {ok, T} when T =:= true; T =:= <<"true">> -> {ok , #{ room_id => RoomId , join => true }}; {ok, F} when F =:= false; F =:= <<"false">> -> - case rest_main_helper:get_body_value(Body, <<"phone_ids">>) of + case get_body_value(<<"phone_ids">>, ParsedBody) of {ok, PhoneIds} -> {ok, #{ room_id => RoomId , join => false @@ -333,6 +340,20 @@ parse_new_room_members_body(Body) -> Err end. +json_parse_body(Body) -> + try jsx:decode(Body) of + ParsedBody -> {ok, ParsedBody} + catch _:_ -> {error, ?ERROR_INVALID_JSON} + end. + +get_body_value(_, {error, _} = E) -> + E; +get_body_value(Key, {ok, ParsedBody}) -> + case proplists:get_value(Key, ParsedBody) of + undefined -> {error, ?ERROR_MISSING_PARAM}; + Val -> {ok, Val} + end. + %%%=================================================================== bubble_from_json(Req, #{phone_id := FromPhoneId} = State) -> diff --git a/apps/roster/src/rest/rest_cowboy_publish_handler.erl b/apps/roster/src/rest/rest_cowboy_publish_handler.erl index 2ddc1a6faf839860fd4a9ca85ba429f5fbf83250..2c20d0bb53b768264d015e1097c3243b5ea4a6bb 100644 --- a/apps/roster/src/rest/rest_cowboy_publish_handler.erl +++ b/apps/roster/src/rest/rest_cowboy_publish_handler.erl @@ -50,9 +50,7 @@ from_json(Req, State) -> #'PublishService'{message = Msg, topic = Topic, qos = Qos} = PS, [throw({validation, ?ERROR_MISSING_PARAM}) || Msg == [] orelse Topic == []], [throw({validation, ?ERROR_INVALID_QOS_PARAM}) || Qos < 0 orelse Qos > 2], - case rest_main_helper:validate_msg_to_publish(Msg) of - false -> - throw({validation, ?ERROR_INVALID_MESSAGE_PARAM}); + try binary_to_list(base64:decode(Msg)) of DecodedMsg -> Pid = rest_main_helper:rest_pid(), MsgBin = term_to_binary(DecodedMsg), @@ -60,6 +58,8 @@ from_json(Req, State) -> Json = rest_response_helper:success_200(), Req2 = cowboy_req:set_resp_body(Json, Req1), {true, Req2, State} + catch _:_ -> + throw({validation, ?ERROR_INVALID_MESSAGE_PARAM}) end catch throw:{validation, What} -> ErrJson = rest_response_helper:error_response(What), diff --git a/apps/roster/src/roster_client.erl b/apps/roster/src/roster_client.erl index aec8cd2b449c7a12903ab351d9feb3725bf32464..7327f206c659870bc77fafbae9af443a9f6a5ce8 100644 --- a/apps/roster/src/roster_client.erl +++ b/apps/roster/src/roster_client.erl @@ -70,7 +70,7 @@ filter_friend(Term, State) -> proc(#mqttc{}, #handler{} = H) -> {reply, [], H}; proc(init, #handler{name = ?SYS_REST_CLIENT, state = #state{receive_pid = Self} = State} = Async) -> - {ok, C} = application:get_env(rest, rest_pid), + C = rest_main_helper:rest_pid(), Self ! init, {ok, Async#handler{state = State#state{mqttc = C, client_id = ?SYS_REST_CLIENT}, seq = 0}}; proc(init, #handler{name = ?SYS_BRIDGE_TEST_CLIENT, state = #state{receive_pid = Self} = State} = Async) ->