diff --git a/apps/roster/include/roster.hrl b/apps/roster/include/roster.hrl index c01d4edbd91b02f2550fb60badfa025d90115daf..394fd15212fac35972b62866f52646b6217758ad 100644 --- a/apps/roster/include/roster.hrl +++ b/apps/roster/include/roster.hrl @@ -18,6 +18,7 @@ -define(FILE_GROUP, <<"FILE_DATA">>). -define(LANG_GROUP, <<"LANGUAGE_SETTINGS">>). -define(DUMMY_GROUP, <<"DUMMY_GROUP">>). +-define(LINKS_GROUP, <<"LINKS">>). %% #'Feature'{} file group keys -define(SIZE_KEY , <<"SIZE">>). @@ -35,6 +36,7 @@ -define(LANG_KEY , <<"LANGUAGE">>). -define(TRANSLATION_KEY , <<"TRANSLATION">>). -define(USERS_KEY , <<"USERS">>). +-define(GROUP_JOIN_LINK_KEY , <<"GROUP_JOIN_LINK">>). %% #'Feature'{} language group keys -define(DEFAULT_LANGUAGE_KEY, <<"DEFAULT_LANGUAGE">>). @@ -143,6 +145,10 @@ created = 0 :: [] | integer(), %% datetime field for sorting status = [] :: [] | gen | check | add | delete | update }). +-record('JoinLink', {id = [] :: [] | binary(), + room_id = [] :: [] | binary(), + type = [] :: [] | room}). + -record('Room', {id = [] :: [] | binary(), name = [] :: [] | binary(), links = [] :: [] | list(#'Link'{}), diff --git a/apps/roster/include/static/rest_var.hrl b/apps/roster/include/static/rest_var.hrl index b31bbc5cf0a405aed841e2777565e0afdfed090a..581763e488744808cf54eee3eec01292ba35bd7a 100644 --- a/apps/roster/include/static/rest_var.hrl +++ b/apps/roster/include/static/rest_var.hrl @@ -14,6 +14,7 @@ -define(MSG_PUSH_ENDPOINT, "/push/message"). -define(ROOM_ENDPOINT, "/room"). +-define(ROOM_JOIN_ID_ENDPOINT, "/room/join/id"). -define(PUBLISH_ENDPOINT, "/publish"). -define(USERS_ENDPOINT, "/users"). -define(METRICS_ENDPOINT, "/metrics"). diff --git a/apps/roster/src/protocol/roster_room.erl b/apps/roster/src/protocol/roster_room.erl index ee20e2b6ff0559dd0535c121ca83837fdf525be0..4f0a48325bb2175e25f2bcdc9ddbbc8e2fc542d2 100644 --- a/apps/roster/src/protocol/roster_room.erl +++ b/apps/roster/src/protocol/roster_room.erl @@ -35,8 +35,15 @@ info(#'Room'{status = create, id = <>, name = Name, admins = [Owner <<"sys_", _/binary>> -> Owner end, Admin = Adm#'Member'{id = [], status = admin, feed_id = #muc{name = Room}, update = roster:now_msec()}, + RoomJoinId = roster_db:generate_room_join_id(), + JoinLinkFeature = #'Feature'{id = list_to_binary(io_lib:format("~s_~p", [Room, erlang:unique_integer([monotonic, positive])])), + key = ?GROUP_JOIN_LINK_KEY, + value = list_to_binary(io_lib:format("https://web.nynja.net/room/join/~s", [RoomJoinId])), + group = ?LINKS_GROUP}, + kvs:put(#'JoinLink'{id = RoomJoinId, room_id = Room, type = room}), info(R#'Room'{admins = [Admin|lists:keydelete(OwnPId, #'Member'.phone_id, Admins)], - members = lists:keydelete(OwnPId, #'Member'.phone_id, Members)}, + members = lists:keydelete(OwnPId, #'Member'.phone_id, Members), + settings = [JoinLinkFeature]}, Req, State#cx{state = verified}); _ -> {reply, {bert, #io{code = #error{code = invalid_data}}}, Req, State} end; diff --git a/apps/roster/src/rest/rest_group_join_link.erl b/apps/roster/src/rest/rest_group_join_link.erl new file mode 100644 index 0000000000000000000000000000000000000000..db7d6bd88e31198b7c7f63bfac295baa9a7dc26e --- /dev/null +++ b/apps/roster/src/rest/rest_group_join_link.erl @@ -0,0 +1,40 @@ +%%%----------------------------------------------------------------------------- +%%% @doc TODO: write documentation +%%% +%%% @see rest_handler:handle_request/3 +%%% @end +%%%----------------------------------------------------------------------------- +-module(rest_group_join_link). +-include("roster.hrl"). +-include_lib("roster/include/static/rest_var.hrl"). +-include_lib("kvs/include/metainfo.hrl"). + +-export([ + handle_request/3 + ]). + +handle_request('POST', Path, Req) -> + ReqData = Req:parse_post(), + roster:info(?MODULE, "~p:Request:~p:~p", [Req:get(method), Req:get(path), ReqData]), + + case parse_incomming_data(ReqData) of + {ok, RoomJoinId} -> + case kvs:get('JoinLink', RoomJoinId) of + {ok, #'JoinLink'{room_id = RoomId}} -> + {ResponseStatus, ResponseData} = {?HTTP_CODE_200, jsx:encode([{room_id, RoomId}])}, + roster:info(?MODULE, "ResponseData:~p", [ResponseData]), + Req:respond({ResponseStatus, [], ResponseData}); + {error, _} -> + rest_response_helper:error_response(Req, ?HTTP_CODE_404, + io_lib:format("No Room is associated with JoinId: ~s", [RoomJoinId])) + end; + {error, wrong_data} -> + rest_response_helper:error_400_response(Req) + end; + +handle_request(_, _, Req) -> + rest_response_helper:error_405_response(Req). + +-spec parse_incomming_data(list(tuple())) -> {ok, term()} | {error, wrong_data}. +parse_incomming_data([{"room_join_id", RoomJoinId}]) -> {ok, list_to_binary(RoomJoinId)}; +parse_incomming_data(_) -> {error, wrong_data}. \ No newline at end of file diff --git a/apps/roster/src/rest/rest_handler.erl b/apps/roster/src/rest/rest_handler.erl index 6a4375066a284438047c218b11398281011dc172..2cd6269bae7dd189f91cad02769faa0adfe99979 100644 --- a/apps/roster/src/rest/rest_handler.erl +++ b/apps/roster/src/rest/rest_handler.erl @@ -81,6 +81,7 @@ handle_request(Method, Path, Req) %% NOTE! uncomment the row under to turn on call bubbles %% handle_request(_, ?RCI_BUBBLE_ENDPOINT, Req) -> rest_cri :handle_request(Req); +handle_request(Method, ?ROOM_JOIN_ID_ENDPOINT = Path, Req) -> rest_group_join_link:handle_request(Method, Path, Req); handle_request(Method, ?CSV_P2P_ENDPOINT = Path, Req) -> rest_chat_csv:handle_request(Method, Path, Req); handle_request(Method, ?CSV_MUC_ENDPOINT = Path, Req) -> rest_chat_csv:handle_request(Method, Path, Req); handle_request(Method, "/metrics" = Path, Req) -> rest_metric :handle_request(Method, Path, Req); diff --git a/apps/roster/src/roster.erl b/apps/roster/src/roster.erl index 33cdd0e8404aa0ec293c5262bb72e5765aafd04b..06c66b2e3ef1e9dd58197eab913bc76c98a6f2a5 100644 --- a/apps/roster/src/roster.erl +++ b/apps/roster/src/roster.erl @@ -102,7 +102,8 @@ tables() -> [ #table{name = 'Schedule', fields = record_info(fields, 'Schedule'), type = ordered_set}, #table{name = 'Whitelist', fields = record_info(fields, 'Whitelist')}, #table{name = 'StickerPack', fields = record_info(fields, 'StickerPack')}, - #table{name = 'FakeNumbers', fields = record_info(fields, 'FakeNumbers'), keys = [phone]} + #table{name = 'FakeNumbers', fields = record_info(fields, 'FakeNumbers'), keys = [phone]}, + #table{name = 'JoinLink', fields = record_info(fields, 'JoinLink')} ]. %% LOGGER diff --git a/apps/roster/src/roster_db.erl b/apps/roster/src/roster_db.erl index e0a7dfd371a360887cb213b4d8317e30dc383b58..5ab98e3f283da73c53fbbb7d2bb659bd6361d5a7 100644 --- a/apps/roster/src/roster_db.erl +++ b/apps/roster/src/roster_db.erl @@ -603,3 +603,13 @@ remigrate_default_contact_settings() -> kvs:delete(schema_migrations, 20181008144317), roster:migrate(). +generate_room_join_id() -> + RandomValue = list_to_binary( + string:sub_string( + string:uppercase( + base58:binary_to_base58( + crypto:strong_rand_bytes(7))), 1, 8)), + case kvs:get('JoinLink', RandomValue) of + {error, not_found} -> RandomValue; + {ok, _} -> generate_room_join_id() + end. \ No newline at end of file diff --git a/rebar.config b/rebar.config index 3000e846ce29bba6dd7be9fa605ed83681bd2031..20f82ad00546afb16503dd46bdfcfa8ce09a2b08 100644 --- a/rebar.config +++ b/rebar.config @@ -30,7 +30,8 @@ {locus, ".*", {git, "https://github.com/g-andrade/locus.git",{tag,"master"}}}, {prometheus, ".*", {git, "https://github.com/deadtrickster/prometheus.erl",{tag,"master"}}}, {cowboy, ".*", {git, "git://github.com/voxoz/cowboy", {tag,"master"}}}, - {'erlang-uuid', ".*", {git, "https://github.com/avtobiff/erlang-uuid.git",{tag,"master"}}} + {'erlang-uuid', ".*", {git, "https://github.com/avtobiff/erlang-uuid.git",{tag,"master"}}}, + {'erl-base58', ".*", {git, "https://github.com/titan098/erl-base58.git", {tag,"master"}}} % {json_rec, ".*", {git, "https://github.com/justinkirby/json_rec.git",{tag,"master"}}} ]}. {erl_opts, [{parse_transform,lager_transform},{parse_transform, oc_transform},debug_info]}. \ No newline at end of file