aboutsummaryrefslogtreecommitdiff
path: root/src/mod_roster_sql.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-04-14 10:58:32 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-04-14 10:58:32 +0300
commit398f1de5aecc574d65f8f3308fe3cba037ad8a99 (patch)
tree5d31403456b113c67062e777e48db85b31bf80dc /src/mod_roster_sql.erl
parentClean mod_muc.erl from DB specific code (diff)
Clean mod_roster.erl from DB specific code
Diffstat (limited to 'src/mod_roster_sql.erl')
-rw-r--r--src/mod_roster_sql.erl308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/mod_roster_sql.erl b/src/mod_roster_sql.erl
new file mode 100644
index 000000000..826628659
--- /dev/null
+++ b/src/mod_roster_sql.erl
@@ -0,0 +1,308 @@
+%%%-------------------------------------------------------------------
+%%% @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_roster_sql).
+
+-behaviour(mod_roster).
+
+%% API
+-export([init/2, read_roster_version/2, write_roster_version/4,
+ get_roster/2, get_roster_by_jid/3,
+ roster_subscribe/4, get_roster_by_jid_with_groups/3,
+ remove_user/2, update_roster/4, del_roster/3, transaction/2,
+ read_subscription_and_groups/3, get_only_items/2,
+ import/1, import/2, export/1]).
+
+-include("jlib.hrl").
+-include("mod_roster.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ ok.
+
+read_roster_version(LUser, LServer) ->
+ case odbc_queries:get_roster_version(LServer, LUser) of
+ {selected, [{Version}]} -> Version;
+ {selected, []} -> error
+ end.
+
+write_roster_version(LUser, LServer, InTransaction, Ver) ->
+ Username = ejabberd_odbc:escape(LUser),
+ EVer = ejabberd_odbc:escape(Ver),
+ if InTransaction ->
+ odbc_queries:set_roster_version(Username, EVer);
+ true ->
+ odbc_queries:sql_transaction(
+ LServer,
+ fun () ->
+ odbc_queries:set_roster_version(Username, EVer)
+ end)
+ end.
+
+get_roster(LUser, LServer) ->
+ case catch odbc_queries:get_roster(LServer, LUser) of
+ {selected, Items} when is_list(Items) ->
+ JIDGroups = case catch odbc_queries:get_roster_jid_groups(
+ LServer, LUser) of
+ {selected, JGrps} when is_list(JGrps) ->
+ JGrps;
+ _ ->
+ []
+ end,
+ GroupsDict = lists:foldl(fun({J, G}, Acc) ->
+ dict:append(J, G, Acc)
+ end,
+ dict:new(), JIDGroups),
+ lists:flatmap(
+ fun(I) ->
+ case raw_to_record(LServer, I) of
+ %% Bad JID in database:
+ error -> [];
+ R ->
+ SJID = jid:to_string(R#roster.jid),
+ Groups = case dict:find(SJID, GroupsDict) of
+ {ok, Gs} -> Gs;
+ error -> []
+ end,
+ [R#roster{groups = Groups}]
+ end
+ end, Items);
+ _ ->
+ []
+ end.
+
+get_roster_by_jid(LUser, LServer, LJID) ->
+ {selected, Res} =
+ odbc_queries:get_roster_by_jid(LServer, LUser, jid:to_string(LJID)),
+ case Res of
+ [] ->
+ #roster{usj = {LUser, LServer, LJID},
+ us = {LUser, LServer}, jid = LJID};
+ [I] ->
+ R = raw_to_record(LServer, I),
+ case R of
+ %% Bad JID in database:
+ error ->
+ #roster{usj = {LUser, LServer, LJID},
+ us = {LUser, LServer}, jid = LJID};
+ _ ->
+ R#roster{usj = {LUser, LServer, LJID},
+ us = {LUser, LServer}, jid = LJID, name = <<"">>}
+ end
+ end.
+
+get_only_items(LUser, LServer) ->
+ case catch odbc_queries:get_roster(LServer, LUser) of
+ {selected, Is} when is_list(Is) ->
+ lists:map(fun(I) -> raw_to_record(LServer, I) end, Is);
+ _ -> []
+ end.
+
+roster_subscribe(_LUser, _LServer, _LJID, Item) ->
+ ItemVals = record_to_row(Item),
+ odbc_queries:roster_subscribe(ItemVals).
+
+transaction(LServer, F) ->
+ ejabberd_odbc:sql_transaction(LServer, F).
+
+get_roster_by_jid_with_groups(LUser, LServer, LJID) ->
+ SJID = jid:to_string(LJID),
+ case odbc_queries:get_roster_by_jid(LServer, LUser, SJID) of
+ {selected, [I]} ->
+ R = raw_to_record(LServer, I),
+ Groups =
+ case odbc_queries:get_roster_groups(LServer, LUser, SJID) of
+ {selected, JGrps} when is_list(JGrps) ->
+ [JGrp || {JGrp} <- JGrps];
+ _ -> []
+ end,
+ R#roster{groups = Groups};
+ {selected, []} ->
+ #roster{usj = {LUser, LServer, LJID},
+ us = {LUser, LServer}, jid = LJID}
+ end.
+
+remove_user(LUser, LServer) ->
+ odbc_queries:del_user_roster_t(LServer, LUser),
+ {atomic, ok}.
+
+update_roster(LUser, LServer, LJID, Item) ->
+ SJID = jid:to_string(LJID),
+ ItemVals = record_to_row(Item),
+ ItemGroups = Item#roster.groups,
+ odbc_queries:update_roster(LServer, LUser, SJID, ItemVals,
+ ItemGroups).
+
+del_roster(LUser, LServer, LJID) ->
+ SJID = jid:to_string(LJID),
+ odbc_queries:del_roster(LServer, LUser, SJID).
+
+read_subscription_and_groups(LUser, LServer, LJID) ->
+ SJID = jid:to_string(LJID),
+ case catch odbc_queries:get_subscription(LServer, LUser, SJID) of
+ {selected, [{SSubscription}]} ->
+ Subscription = case SSubscription of
+ <<"B">> -> both;
+ <<"T">> -> to;
+ <<"F">> -> from;
+ _ -> none
+ end,
+ Groups = case catch odbc_queries:get_rostergroup_by_jid(
+ LServer, LUser, SJID) of
+ {selected, JGrps} when is_list(JGrps) ->
+ [JGrp || {JGrp} <- JGrps];
+ _ -> []
+ end,
+ {Subscription, Groups};
+ _ ->
+ error
+ end.
+
+export(_Server) ->
+ [{roster,
+ fun(Host, #roster{usj = {LUser, LServer, LJID}} = R)
+ when LServer == Host ->
+ Username = ejabberd_odbc:escape(LUser),
+ SJID = ejabberd_odbc:escape(jid:to_string(LJID)),
+ ItemVals = record_to_string(R),
+ ItemGroups = groups_to_string(R),
+ odbc_queries:update_roster_sql(Username, SJID,
+ ItemVals, ItemGroups);
+ (_Host, _R) ->
+ []
+ end},
+ {roster_version,
+ fun(Host, #roster_version{us = {LUser, LServer}, version = Ver})
+ when LServer == Host ->
+ Username = ejabberd_odbc:escape(LUser),
+ SVer = ejabberd_odbc:escape(Ver),
+ [[<<"delete from roster_version where username='">>,
+ Username, <<"';">>],
+ [<<"insert into roster_version(username, version) values('">>,
+ Username, <<"', '">>, SVer, <<"');">>]];
+ (_Host, _R) ->
+ []
+ end}].
+
+import(LServer) ->
+ [{<<"select username, jid, nick, subscription, "
+ "ask, askmessage, server, subscribe, type from rosterusers;">>,
+ fun([LUser, JID|_] = Row) ->
+ Item = raw_to_record(LServer, Row),
+ Username = ejabberd_odbc:escape(LUser),
+ SJID = ejabberd_odbc:escape(JID),
+ {selected, _, Rows} =
+ ejabberd_odbc:sql_query_t(
+ [<<"select grp from rostergroups where username='">>,
+ Username, <<"' and jid='">>, SJID, <<"'">>]),
+ Groups = [Grp || [Grp] <- Rows],
+ Item#roster{groups = Groups}
+ end},
+ {<<"select username, version from roster_version;">>,
+ fun([LUser, Ver]) ->
+ #roster_version{us = {LUser, LServer}, version = Ver}
+ end}].
+
+import(_, _) ->
+ pass.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+raw_to_record(LServer,
+ [User, SJID, Nick, SSubscription, SAsk, SAskMessage,
+ _SServer, _SSubscribe, _SType]) ->
+ raw_to_record(LServer,
+ {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
+ _SServer, _SSubscribe, _SType});
+raw_to_record(LServer,
+ {User, SJID, Nick, SSubscription, SAsk, SAskMessage,
+ _SServer, _SSubscribe, _SType}) ->
+ case jid:from_string(SJID) of
+ error -> error;
+ JID ->
+ LJID = jid:tolower(JID),
+ Subscription = case SSubscription of
+ <<"B">> -> both;
+ <<"T">> -> to;
+ <<"F">> -> from;
+ _ -> none
+ end,
+ Ask = case SAsk of
+ <<"S">> -> subscribe;
+ <<"U">> -> unsubscribe;
+ <<"B">> -> both;
+ <<"O">> -> out;
+ <<"I">> -> in;
+ _ -> none
+ end,
+ #roster{usj = {User, LServer, LJID},
+ us = {User, LServer}, jid = LJID, name = Nick,
+ subscription = Subscription, ask = Ask,
+ askmessage = SAskMessage}
+ end.
+
+record_to_string(#roster{us = {User, _Server},
+ jid = JID, name = Name, subscription = Subscription,
+ ask = Ask, askmessage = AskMessage}) ->
+ Username = ejabberd_odbc:escape(User),
+ SJID =
+ ejabberd_odbc:escape(jid:to_string(jid:tolower(JID))),
+ Nick = ejabberd_odbc:escape(Name),
+ SSubscription = case Subscription of
+ both -> <<"B">>;
+ to -> <<"T">>;
+ from -> <<"F">>;
+ none -> <<"N">>
+ end,
+ SAsk = case Ask of
+ subscribe -> <<"S">>;
+ unsubscribe -> <<"U">>;
+ both -> <<"B">>;
+ out -> <<"O">>;
+ in -> <<"I">>;
+ none -> <<"N">>
+ end,
+ SAskMessage = ejabberd_odbc:escape(AskMessage),
+ [Username, SJID, Nick, SSubscription, SAsk, SAskMessage,
+ <<"N">>, <<"">>, <<"item">>].
+
+record_to_row(
+ #roster{us = {LUser, _LServer},
+ jid = JID, name = Name, subscription = Subscription,
+ ask = Ask, askmessage = AskMessage}) ->
+ SJID = jid:to_string(jid:tolower(JID)),
+ SSubscription = case Subscription of
+ both -> <<"B">>;
+ to -> <<"T">>;
+ from -> <<"F">>;
+ none -> <<"N">>
+ end,
+ SAsk = case Ask of
+ subscribe -> <<"S">>;
+ unsubscribe -> <<"U">>;
+ both -> <<"B">>;
+ out -> <<"O">>;
+ in -> <<"I">>;
+ none -> <<"N">>
+ end,
+ {LUser, SJID, Name, SSubscription, SAsk, AskMessage}.
+
+groups_to_string(#roster{us = {User, _Server},
+ jid = JID, groups = Groups}) ->
+ Username = ejabberd_odbc:escape(User),
+ SJID =
+ ejabberd_odbc:escape(jid:to_string(jid:tolower(JID))),
+ lists:foldl(fun (<<"">>, Acc) -> Acc;
+ (Group, Acc) ->
+ G = ejabberd_odbc:escape(Group),
+ [[Username, SJID, G] | Acc]
+ end,
+ [], Groups).