Files
EventHubBack/src/logic/logic_user_lookup.erl
T
aleksey 571f04737d
CI / test (push) Successful in 6m47s
CI / deploy-ift (push) Successful in 3m23s
CI / e2e-ift (push) Successful in 1m58s
CI / deploy-stage (push) Successful in 2m1s
CI / e2e-stage (push) Successful in 1m13s
feat: specialist_invite API + user lookup. Fixes EventHub/EventHubBack#55
2026-07-22 18:52:35 +03:00

55 lines
1.9 KiB
Erlang
Executable File

%%%-------------------------------------------------------------------
%%% @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.