feat: specialist_invite API + user lookup. Fixes EventHub/EventHubBack#55
This commit is contained in:
Executable
+54
@@ -0,0 +1,54 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @doc Lookup пользователей для typeahead (specialist invite).
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(logic_user_lookup).
|
||||
-include("records.hrl").
|
||||
|
||||
-export([lookup/1]).
|
||||
|
||||
-define(MAX_RESULTS, 20).
|
||||
-define(MIN_Q, 2).
|
||||
|
||||
-spec lookup(Q :: binary()) -> {ok, [map()]} | {error, bad_request}.
|
||||
lookup(Q0) when is_binary(Q0) ->
|
||||
Q = string:trim(Q0),
|
||||
case byte_size(Q) < ?MIN_Q of
|
||||
true -> {error, bad_request};
|
||||
false ->
|
||||
QLower = string:lowercase(Q),
|
||||
Users = [U || U <- mnesia:dirty_match_object(#user{_ = '_'}),
|
||||
U#user.status =:= active],
|
||||
ExactEmail = [U || U <- Users, string:lowercase(U#user.email) =:= QLower],
|
||||
NickPrefix = [U || U <- Users, is_nick_prefix(QLower, U#user.nickname)],
|
||||
Merged = unique_by_id(ExactEmail ++ NickPrefix),
|
||||
Limited = lists:sublist(Merged, ?MAX_RESULTS),
|
||||
{ok, [to_public(U, string:lowercase(U#user.email) =:= QLower) || U <- Limited]}
|
||||
end;
|
||||
lookup(_) ->
|
||||
{error, bad_request}.
|
||||
|
||||
is_nick_prefix(QLower, Nick) when is_binary(Nick) ->
|
||||
Lower = string:lowercase(Nick),
|
||||
byte_size(Lower) >= byte_size(QLower) andalso
|
||||
binary:part(Lower, 0, byte_size(QLower)) =:= QLower;
|
||||
is_nick_prefix(_, _) -> false.
|
||||
|
||||
unique_by_id(Users) ->
|
||||
maps:values(lists:foldl(fun(U, Acc) ->
|
||||
maps:put(U#user.id, U, Acc)
|
||||
end, #{}, Users)).
|
||||
|
||||
to_public(#user{id = Id, nickname = Nick, email = Email}, true) ->
|
||||
#{id => Id, nickname => Nick, email => Email};
|
||||
to_public(#user{id = Id, nickname = Nick, email = Email}, false) ->
|
||||
#{id => Id, nickname => Nick, email => mask_email(Email)}.
|
||||
|
||||
mask_email(<<>>) -> <<>>;
|
||||
mask_email(Email) ->
|
||||
case binary:split(Email, <<"@">>) of
|
||||
[Local, Domain] when byte_size(Local) > 0 ->
|
||||
First = binary:part(Local, 0, 1),
|
||||
<<First/binary, "***@", Domain/binary>>;
|
||||
_ -> <<"***">>
|
||||
end.
|
||||
Reference in New Issue
Block a user