aboutsummaryrefslogtreecommitdiff
path: root/src/mod_privacy_sql.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_privacy_sql.erl')
-rw-r--r--src/mod_privacy_sql.erl397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/mod_privacy_sql.erl b/src/mod_privacy_sql.erl
new file mode 100644
index 000000000..ffaf55188
--- /dev/null
+++ b/src/mod_privacy_sql.erl
@@ -0,0 +1,397 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 14 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mod_privacy_sql).
+
+-behaviour(mod_privacy).
+
+%% API
+-export([init/2, process_lists_get/2, process_list_get/3,
+ process_default_set/3, process_active_set/3,
+ remove_privacy_list/3, set_privacy_list/1,
+ set_privacy_list/4, get_user_list/2, get_user_lists/2,
+ remove_user/2, import/1, import/2, export/1]).
+
+-export([item_to_raw/1, raw_to_item/1,
+ sql_add_privacy_list/2,
+ sql_get_default_privacy_list/2,
+ sql_get_default_privacy_list_t/1,
+ sql_get_privacy_list_data/3,
+ sql_get_privacy_list_data_by_id_t/1,
+ sql_get_privacy_list_id_t/2,
+ sql_set_default_privacy_list/2, sql_set_privacy_list/2]).
+
+-include("jlib.hrl").
+-include("mod_privacy.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ ok.
+
+process_lists_get(LUser, LServer) ->
+ Default = case catch sql_get_default_privacy_list(LUser, LServer) of
+ {selected, []} -> none;
+ {selected, [{DefName}]} -> DefName;
+ _ -> none
+ end,
+ case catch sql_get_privacy_list_names(LUser, LServer) of
+ {selected, Names} ->
+ LItems = lists:map(fun ({N}) ->
+ #xmlel{name = <<"list">>,
+ attrs = [{<<"name">>, N}],
+ children = []}
+ end,
+ Names),
+ {Default, LItems};
+ _ -> error
+ end.
+
+process_list_get(LUser, LServer, Name) ->
+ case catch sql_get_privacy_list_id(LUser, LServer, Name) of
+ {selected, []} -> not_found;
+ {selected, [{ID}]} ->
+ case catch sql_get_privacy_list_data_by_id(ID, LServer) of
+ {selected, RItems} ->
+ lists:flatmap(fun raw_to_item/1, RItems);
+ _ -> error
+ end;
+ _ -> error
+ end.
+
+process_default_set(LUser, LServer, {value, Name}) ->
+ F = fun () ->
+ case sql_get_privacy_list_names_t(LUser) of
+ {selected, []} -> not_found;
+ {selected, Names} ->
+ case lists:member({Name}, Names) of
+ true -> sql_set_default_privacy_list(LUser, Name), ok;
+ false -> not_found
+ end
+ end
+ end,
+ odbc_queries:sql_transaction(LServer, F);
+process_default_set(LUser, LServer, false) ->
+ case catch sql_unset_default_privacy_list(LUser,
+ LServer)
+ of
+ {'EXIT', _Reason} -> {atomic, error};
+ {error, _Reason} -> {atomic, error};
+ _ -> {atomic, ok}
+ end.
+
+process_active_set(LUser, LServer, Name) ->
+ case catch sql_get_privacy_list_id(LUser, LServer, Name) of
+ {selected, []} -> error;
+ {selected, [{ID}]} ->
+ case catch sql_get_privacy_list_data_by_id(ID, LServer) of
+ {selected, RItems} ->
+ lists:flatmap(fun raw_to_item/1, RItems);
+ _ -> error
+ end;
+ _ -> error
+ end.
+
+remove_privacy_list(LUser, LServer, Name) ->
+ F = fun () ->
+ case sql_get_default_privacy_list_t(LUser) of
+ {selected, []} ->
+ sql_remove_privacy_list(LUser, Name), ok;
+ {selected, [{Default}]} ->
+ if Name == Default -> conflict;
+ true -> sql_remove_privacy_list(LUser, Name), ok
+ end
+ end
+ end,
+ odbc_queries:sql_transaction(LServer, F).
+
+set_privacy_list(#privacy{us = {LUser, LServer},
+ default = Default,
+ lists = Lists}) ->
+ F = fun() ->
+ lists:foreach(
+ fun({Name, List}) ->
+ sql_add_privacy_list(LUser, Name),
+ {selected, [<<"id">>], [[I]]} =
+ sql_get_privacy_list_id_t(LUser, Name),
+ RItems = lists:map(fun item_to_raw/1, List),
+ sql_set_privacy_list(I, RItems),
+ if is_binary(Default) ->
+ sql_set_default_privacy_list(LUser, Default),
+ ok;
+ true ->
+ ok
+ end
+ end, Lists)
+ end,
+ odbc_queries:sql_transaction(LServer, F).
+
+set_privacy_list(LUser, LServer, Name, List) ->
+ RItems = lists:map(fun item_to_raw/1, List),
+ F = fun () ->
+ ID = case sql_get_privacy_list_id_t(LUser, Name) of
+ {selected, []} ->
+ sql_add_privacy_list(LUser, Name),
+ {selected, [{I}]} =
+ sql_get_privacy_list_id_t(LUser, Name),
+ I;
+ {selected, [{I}]} -> I
+ end,
+ sql_set_privacy_list(ID, RItems),
+ ok
+ end,
+ odbc_queries:sql_transaction(LServer, F).
+
+get_user_list(LUser, LServer) ->
+ case catch sql_get_default_privacy_list(LUser, LServer)
+ of
+ {selected, []} -> {none, []};
+ {selected, [{Default}]} ->
+ case catch sql_get_privacy_list_data(LUser, LServer,
+ Default) of
+ {selected, RItems} ->
+ {Default, lists:flatmap(fun raw_to_item/1, RItems)};
+ _ -> {none, []}
+ end;
+ _ -> {none, []}
+ end.
+
+get_user_lists(LUser, LServer) ->
+ Default = case catch sql_get_default_privacy_list(LUser, LServer) of
+ {selected, []} ->
+ none;
+ {selected, [{DefName}]} ->
+ DefName;
+ _ ->
+ none
+ end,
+ case catch sql_get_privacy_list_names(LUser, LServer) of
+ {selected, Names} ->
+ Lists =
+ lists:flatmap(
+ fun({Name}) ->
+ case catch sql_get_privacy_list_data(
+ LUser, LServer, Name) of
+ {selected, RItems} ->
+ [{Name, lists:flatmap(fun raw_to_item/1, RItems)}];
+ _ ->
+ []
+ end
+ end, Names),
+ {ok, #privacy{default = Default,
+ us = {LUser, LServer},
+ lists = Lists}};
+ _ ->
+ error
+ end.
+
+remove_user(LUser, LServer) ->
+ sql_del_privacy_lists(LUser, LServer).
+
+export(Server) ->
+ case catch ejabberd_odbc:sql_query(jid:nameprep(Server),
+ [<<"select id from privacy_list order by "
+ "id desc limit 1;">>]) of
+ {selected, [<<"id">>], [[I]]} ->
+ put(id, jlib:binary_to_integer(I));
+ _ ->
+ put(id, 0)
+ end,
+ [{privacy,
+ fun(Host, #privacy{us = {LUser, LServer}, lists = Lists,
+ default = Default})
+ when LServer == Host ->
+ Username = ejabberd_odbc:escape(LUser),
+ if Default /= none ->
+ SDefault = ejabberd_odbc:escape(Default),
+ [[<<"delete from privacy_default_list where ">>,
+ <<"username='">>, Username, <<"';">>],
+ [<<"insert into privacy_default_list(username, "
+ "name) ">>,
+ <<"values ('">>, Username, <<"', '">>,
+ SDefault, <<"');">>]];
+ true ->
+ []
+ end ++
+ lists:flatmap(
+ fun({Name, List}) ->
+ SName = ejabberd_odbc:escape(Name),
+ RItems = lists:map(fun item_to_raw/1, List),
+ ID = jlib:integer_to_binary(get_id()),
+ [[<<"delete from privacy_list where username='">>,
+ Username, <<"' and name='">>,
+ SName, <<"';">>],
+ [<<"insert into privacy_list(username, "
+ "name, id) values ('">>,
+ Username, <<"', '">>, SName,
+ <<"', '">>, ID, <<"');">>],
+ [<<"delete from privacy_list_data where "
+ "id='">>, ID, <<"';">>]] ++
+ [[<<"insert into privacy_list_data(id, t, "
+ "value, action, ord, match_all, match_iq, "
+ "match_message, match_presence_in, "
+ "match_presence_out) values ('">>,
+ ID, <<"', '">>, str:join(Items, <<"', '">>),
+ <<"');">>] || Items <- RItems]
+ end,
+ Lists);
+ (_Host, _R) ->
+ []
+ end}].
+
+get_id() ->
+ ID = get(id),
+ put(id, ID + 1),
+ ID + 1.
+
+import(LServer) ->
+ [{<<"select username from privacy_list;">>,
+ fun([LUser]) ->
+ Default = case sql_get_default_privacy_list_t(LUser) of
+ {selected, [<<"name">>], []} ->
+ none;
+ {selected, [<<"name">>], [[DefName]]} ->
+ DefName;
+ _ ->
+ none
+ end,
+ {selected, [<<"name">>], Names} =
+ sql_get_privacy_list_names_t(LUser),
+ Lists = lists:flatmap(
+ fun([Name]) ->
+ case sql_get_privacy_list_data_t(LUser, Name) of
+ {selected, _, RItems} ->
+ [{Name,
+ lists:map(fun raw_to_item/1,
+ RItems)}];
+ _ ->
+ []
+ end
+ end, Names),
+ #privacy{default = Default,
+ us = {LUser, LServer},
+ lists = Lists}
+ end}].
+
+import(_, _) ->
+ pass.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+raw_to_item({SType, SValue, SAction, Order, MatchAll,
+ MatchIQ, MatchMessage, MatchPresenceIn,
+ MatchPresenceOut} = Row) ->
+ try
+ {Type, Value} = case SType of
+ <<"n">> -> {none, none};
+ <<"j">> ->
+ case jid:from_string(SValue) of
+ #jid{} = JID ->
+ {jid, jid:tolower(JID)}
+ end;
+ <<"g">> -> {group, SValue};
+ <<"s">> ->
+ case SValue of
+ <<"none">> -> {subscription, none};
+ <<"both">> -> {subscription, both};
+ <<"from">> -> {subscription, from};
+ <<"to">> -> {subscription, to}
+ end
+ end,
+ Action = case SAction of
+ <<"a">> -> allow;
+ <<"d">> -> deny
+ end,
+ [#listitem{type = Type, value = Value, action = Action,
+ order = Order, match_all = MatchAll, match_iq = MatchIQ,
+ match_message = MatchMessage,
+ match_presence_in = MatchPresenceIn,
+ match_presence_out = MatchPresenceOut}]
+ catch _:_ ->
+ ?WARNING_MSG("failed to parse row: ~p", [Row]),
+ []
+ end.
+
+item_to_raw(#listitem{type = Type, value = Value,
+ action = Action, order = Order, match_all = MatchAll,
+ match_iq = MatchIQ, match_message = MatchMessage,
+ match_presence_in = MatchPresenceIn,
+ match_presence_out = MatchPresenceOut}) ->
+ {SType, SValue} = case Type of
+ none -> {<<"n">>, <<"">>};
+ jid ->
+ {<<"j">>,
+ ejabberd_odbc:escape(jid:to_string(Value))};
+ group -> {<<"g">>, ejabberd_odbc:escape(Value)};
+ subscription ->
+ case Value of
+ none -> {<<"s">>, <<"none">>};
+ both -> {<<"s">>, <<"both">>};
+ from -> {<<"s">>, <<"from">>};
+ to -> {<<"s">>, <<"to">>}
+ end
+ end,
+ SAction = case Action of
+ allow -> <<"a">>;
+ deny -> <<"d">>
+ end,
+ {SType, SValue, SAction, Order, MatchAll, MatchIQ,
+ MatchMessage, MatchPresenceIn, MatchPresenceOut}.
+
+sql_get_default_privacy_list(LUser, LServer) ->
+ odbc_queries:get_default_privacy_list(LServer, LUser).
+
+sql_get_default_privacy_list_t(LUser) ->
+ odbc_queries:get_default_privacy_list_t(LUser).
+
+sql_get_privacy_list_names(LUser, LServer) ->
+ odbc_queries:get_privacy_list_names(LServer, LUser).
+
+sql_get_privacy_list_names_t(LUser) ->
+ odbc_queries:get_privacy_list_names_t(LUser).
+
+sql_get_privacy_list_id(LUser, LServer, Name) ->
+ odbc_queries:get_privacy_list_id(LServer, LUser, Name).
+
+sql_get_privacy_list_id_t(LUser, Name) ->
+ odbc_queries:get_privacy_list_id_t(LUser, Name).
+
+sql_get_privacy_list_data(LUser, LServer, Name) ->
+ odbc_queries:get_privacy_list_data(LServer, LUser, Name).
+
+sql_get_privacy_list_data_t(LUser, Name) ->
+ Username = ejabberd_odbc:escape(LUser),
+ SName = ejabberd_odbc:escape(Name),
+ odbc_queries:get_privacy_list_data_t(Username, SName).
+
+sql_get_privacy_list_data_by_id(ID, LServer) ->
+ odbc_queries:get_privacy_list_data_by_id(LServer, ID).
+
+sql_get_privacy_list_data_by_id_t(ID) ->
+ odbc_queries:get_privacy_list_data_by_id_t(ID).
+
+sql_set_default_privacy_list(LUser, Name) ->
+ odbc_queries:set_default_privacy_list(LUser, Name).
+
+sql_unset_default_privacy_list(LUser, LServer) ->
+ odbc_queries:unset_default_privacy_list(LServer, LUser).
+
+sql_remove_privacy_list(LUser, Name) ->
+ odbc_queries:remove_privacy_list(LUser, Name).
+
+sql_add_privacy_list(LUser, Name) ->
+ odbc_queries:add_privacy_list(LUser, Name).
+
+sql_set_privacy_list(ID, RItems) ->
+ odbc_queries:set_privacy_list(ID, RItems).
+
+sql_del_privacy_lists(LUser, LServer) ->
+ odbc_queries:del_privacy_lists(LServer, LUser).