summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-04-13 21:07:32 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2016-04-13 21:07:32 +0300
commit0b439a7d5b28a5de8d4c2e108333ad20189b580e (patch)
treede6ced6a618ed7fb3122526626d44d73512ff836 /src
parentClean mod_vcard.erl from DB specific code (diff)
Clean mod_muc.erl from DB specific code
Diffstat (limited to 'src')
-rw-r--r--src/mod_muc.erl447
-rw-r--r--src/mod_muc_mnesia.erl163
-rw-r--r--src/mod_muc_riak.erl117
-rw-r--r--src/mod_muc_sql.erl202
4 files changed, 519 insertions, 410 deletions
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index 9d4b4985..95631e25 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -48,6 +48,7 @@
export/1,
import/1,
import/3,
+ opts_to_binary/1,
can_use_nick/4]).
-export([init/1, handle_call/3, handle_cast/2,
@@ -72,6 +73,17 @@
-define(MAX_ROOMS_DISCOITEMS, 100).
+-type muc_room_opts() :: [{atom(), any()}].
+-callback init(binary(), gen_mod:opts()) -> any().
+-callback import(binary(), #muc_room{} | #muc_registered{}) -> ok | pass.
+-callback store_room(binary(), binary(), binary(), list()) -> {atomic, any()}.
+-callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error.
+-callback forget_room(binary(), binary(), binary()) -> {atomic, any()}.
+-callback can_use_nick(binary(), binary(), jid(), binary()) -> boolean().
+-callback get_rooms(binary(), binary()) -> [#muc_room{}].
+-callback get_nick(binary(), binary(), jid()) -> binary() | error.
+-callback set_nick(binary(), binary(), jid(), binary()) -> {atomic, ok | false}.
+
%%====================================================================
%% API
%%====================================================================
@@ -125,83 +137,19 @@ create_room(Host, Name, From, Nick, Opts) ->
store_room(ServerHost, Host, Name, Opts) ->
LServer = jid:nameprep(ServerHost),
- store_room(LServer, Host, Name, Opts,
- gen_mod:db_type(LServer, ?MODULE)).
-
-store_room(_LServer, Host, Name, Opts, mnesia) ->
- F = fun () ->
- mnesia:write(#muc_room{name_host = {Name, Host},
- opts = Opts})
- end,
- mnesia:transaction(F);
-store_room(_LServer, Host, Name, Opts, riak) ->
- {atomic, ejabberd_riak:put(#muc_room{name_host = {Name, Host},
- opts = Opts},
- muc_room_schema())};
-store_room(LServer, Host, Name, Opts, odbc) ->
- SName = ejabberd_odbc:escape(Name),
- SHost = ejabberd_odbc:escape(Host),
- SOpts = ejabberd_odbc:encode_term(Opts),
- F = fun () ->
- odbc_queries:update_t(<<"muc_room">>,
- [<<"name">>, <<"host">>, <<"opts">>],
- [SName, SHost, SOpts],
- [<<"name='">>, SName, <<"' and host='">>,
- SHost, <<"'">>])
- end,
- ejabberd_odbc:sql_transaction(LServer, F).
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:store_room(LServer, Host, Name, Opts).
restore_room(ServerHost, Host, Name) ->
LServer = jid:nameprep(ServerHost),
- restore_room(LServer, Host, Name,
- gen_mod:db_type(LServer, ?MODULE)).
-
-restore_room(_LServer, Host, Name, mnesia) ->
- case catch mnesia:dirty_read(muc_room, {Name, Host}) of
- [#muc_room{opts = Opts}] -> Opts;
- _ -> error
- end;
-restore_room(_LServer, Host, Name, riak) ->
- case ejabberd_riak:get(muc_room, muc_room_schema(), {Name, Host}) of
- {ok, #muc_room{opts = Opts}} -> Opts;
- _ -> error
- end;
-restore_room(LServer, Host, Name, odbc) ->
- SName = ejabberd_odbc:escape(Name),
- SHost = ejabberd_odbc:escape(Host),
- case catch ejabberd_odbc:sql_query(LServer,
- [<<"select opts from muc_room where name='">>,
- SName, <<"' and host='">>, SHost,
- <<"';">>])
- of
- {selected, [<<"opts">>], [[Opts]]} ->
- opts_to_binary(ejabberd_odbc:decode_term(Opts));
- _ -> error
- end.
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:restore_room(LServer, Host, Name).
forget_room(ServerHost, Host, Name) ->
LServer = jid:nameprep(ServerHost),
- forget_room(LServer, Host, Name,
- gen_mod:db_type(LServer, ?MODULE)).
-
-forget_room(LServer, Host, Name, mnesia) ->
- remove_room_mam(LServer, Host, Name),
- F = fun () -> mnesia:delete({muc_room, {Name, Host}})
- end,
- mnesia:transaction(F);
-forget_room(LServer, Host, Name, riak) ->
remove_room_mam(LServer, Host, Name),
- {atomic, ejabberd_riak:delete(muc_room, {Name, Host})};
-forget_room(LServer, Host, Name, odbc) ->
- remove_room_mam(LServer, Host, Name),
- SName = ejabberd_odbc:escape(Name),
- SHost = ejabberd_odbc:escape(Host),
- F = fun () ->
- ejabberd_odbc:sql_query_t([<<"delete from muc_room where name='">>,
- SName, <<"' and host='">>, SHost,
- <<"';">>])
- end,
- ejabberd_odbc:sql_transaction(LServer, F).
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:forget_room(LServer, Host, Name).
remove_room_mam(LServer, Host, Name) ->
case gen_mod:is_loaded(LServer, mod_mam) of
@@ -233,48 +181,8 @@ process_iq_disco_items(Host, From, To,
can_use_nick(_ServerHost, _Host, _JID, <<"">>) -> false;
can_use_nick(ServerHost, Host, JID, Nick) ->
LServer = jid:nameprep(ServerHost),
- can_use_nick(LServer, Host, JID, Nick,
- gen_mod:db_type(LServer, ?MODULE)).
-
-can_use_nick(_LServer, Host, JID, Nick, mnesia) ->
- {LUser, LServer, _} = jid:tolower(JID),
- LUS = {LUser, LServer},
- case catch mnesia:dirty_select(muc_registered,
- [{#muc_registered{us_host = '$1',
- nick = Nick, _ = '_'},
- [{'==', {element, 2, '$1'}, Host}],
- ['$_']}])
- of
- {'EXIT', _Reason} -> true;
- [] -> true;
- [#muc_registered{us_host = {U, _Host}}] -> U == LUS
- end;
-can_use_nick(LServer, Host, JID, Nick, riak) ->
- {LUser, LServer, _} = jid:tolower(JID),
- LUS = {LUser, LServer},
- case ejabberd_riak:get_by_index(muc_registered,
- muc_registered_schema(),
- <<"nick_host">>, {Nick, Host}) of
- {ok, []} ->
- true;
- {ok, [#muc_registered{us_host = {U, _Host}}]} ->
- U == LUS;
- {error, _} ->
- true
- end;
-can_use_nick(LServer, Host, JID, Nick, odbc) ->
- SJID =
- jid:to_string(jid:tolower(jid:remove_resource(JID))),
- SNick = ejabberd_odbc:escape(Nick),
- SHost = ejabberd_odbc:escape(Host),
- case catch ejabberd_odbc:sql_query(LServer,
- [<<"select jid from muc_registered ">>,
- <<"where nick='">>, SNick,
- <<"' and host='">>, SHost, <<"';">>])
- of
- {selected, [<<"jid">>], [[SJID1]]} -> SJID == SJID1;
- _ -> true
- end.
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:can_use_nick(LServer, Host, JID, Nick).
%%====================================================================
%% gen_server callbacks
@@ -283,21 +191,8 @@ can_use_nick(LServer, Host, JID, Nick, odbc) ->
init([Host, Opts]) ->
MyHost = gen_mod:get_opt_host(Host, Opts,
<<"conference.@HOST@">>),
- case gen_mod:db_type(Host, Opts) of
- mnesia ->
- mnesia:create_table(muc_room,
- [{disc_copies, [node()]},
- {attributes,
- record_info(fields, muc_room)}]),
- mnesia:create_table(muc_registered,
- [{disc_copies, [node()]},
- {attributes,
- record_info(fields, muc_registered)}]),
- update_tables(MyHost),
- mnesia:add_table_index(muc_registered, nick);
- _ ->
- ok
- end,
+ Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
+ Mod:init(Host, [{host, MyHost}|Opts]),
mnesia:create_table(muc_online_room,
[{ram_copies, [node()]},
{attributes, record_info(fields, muc_online_room)}]),
@@ -647,43 +542,8 @@ check_create_roomid(ServerHost, RoomID) ->
get_rooms(ServerHost, Host) ->
LServer = jid:nameprep(ServerHost),
- get_rooms(LServer, Host,
- gen_mod:db_type(LServer, ?MODULE)).
-
-get_rooms(_LServer, Host, mnesia) ->
- case catch mnesia:dirty_select(muc_room,
- [{#muc_room{name_host = {'_', Host},
- _ = '_'},
- [], ['$_']}])
- of
- {'EXIT', Reason} -> ?ERROR_MSG("~p", [Reason]), [];
- Rs -> Rs
- end;
-get_rooms(_LServer, Host, riak) ->
- case ejabberd_riak:get(muc_room, muc_room_schema()) of
- {ok, Rs} ->
- lists:filter(
- fun(#muc_room{name_host = {_, H}}) ->
- Host == H
- end, Rs);
- _Err ->
- []
- end;
-get_rooms(LServer, Host, odbc) ->
- SHost = ejabberd_odbc:escape(Host),
- case catch ejabberd_odbc:sql_query(LServer,
- [<<"select name, opts from muc_room ">>,
- <<"where host='">>, SHost, <<"';">>])
- of
- {selected, [<<"name">>, <<"opts">>], RoomOpts} ->
- lists:map(fun ([Room, Opts]) ->
- #muc_room{name_host = {Room, Host},
- opts = opts_to_binary(
- ejabberd_odbc:decode_term(Opts))}
- end,
- RoomOpts);
- Err -> ?ERROR_MSG("failed to get rooms: ~p", [Err]), []
- end.
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:get_rooms(LServer, Host).
load_permanent_rooms(Host, ServerHost, Access,
HistorySize, RoomShaper) ->
@@ -873,41 +733,8 @@ iq_get_unique(From) ->
get_nick(ServerHost, Host, From) ->
LServer = jid:nameprep(ServerHost),
- get_nick(LServer, Host, From,
- gen_mod:db_type(LServer, ?MODULE)).
-
-get_nick(_LServer, Host, From, mnesia) ->
- {LUser, LServer, _} = jid:tolower(From),
- LUS = {LUser, LServer},
- case catch mnesia:dirty_read(muc_registered,
- {LUS, Host})
- of
- {'EXIT', _Reason} -> error;
- [] -> error;
- [#muc_registered{nick = Nick}] -> Nick
- end;
-get_nick(LServer, Host, From, riak) ->
- {LUser, LServer, _} = jid:tolower(From),
- US = {LUser, LServer},
- case ejabberd_riak:get(muc_registered,
- muc_registered_schema(),
- {US, Host}) of
- {ok, #muc_registered{nick = Nick}} -> Nick;
- {error, _} -> error
- end;
-get_nick(LServer, Host, From, odbc) ->
- SJID =
- ejabberd_odbc:escape(jid:to_string(jid:tolower(jid:remove_resource(From)))),
- SHost = ejabberd_odbc:escape(Host),
- case catch ejabberd_odbc:sql_query(LServer,
- [<<"select nick from muc_registered where "
- "jid='">>,
- SJID, <<"' and host='">>, SHost,
- <<"';">>])
- of
- {selected, [<<"nick">>], [[Nick]]} -> Nick;
- _ -> error
- end.
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:get_nick(LServer, Host, From).
iq_get_register_info(ServerHost, Host, From, Lang) ->
{Nick, Registered} = case get_nick(ServerHost, Host,
@@ -946,107 +773,8 @@ iq_get_register_info(ServerHost, Host, From, Lang) ->
set_nick(ServerHost, Host, From, Nick) ->
LServer = jid:nameprep(ServerHost),
- set_nick(LServer, Host, From, Nick,
- gen_mod:db_type(LServer, ?MODULE)).
-
-set_nick(_LServer, Host, From, Nick, mnesia) ->
- {LUser, LServer, _} = jid:tolower(From),
- LUS = {LUser, LServer},
- F = fun () ->
- case Nick of
- <<"">> ->
- mnesia:delete({muc_registered, {LUS, Host}}), ok;
- _ ->
- Allow = case mnesia:select(muc_registered,
- [{#muc_registered{us_host =
- '$1',
- nick = Nick,
- _ = '_'},
- [{'==', {element, 2, '$1'},
- Host}],
- ['$_']}])
- of
- [] -> true;
- [#muc_registered{us_host = {U, _Host}}] ->
- U == LUS
- end,
- if Allow ->
- mnesia:write(#muc_registered{us_host = {LUS, Host},
- nick = Nick}),
- ok;
- true -> false
- end
- end
- end,
- mnesia:transaction(F);
-set_nick(LServer, Host, From, Nick, riak) ->
- {LUser, LServer, _} = jid:tolower(From),
- LUS = {LUser, LServer},
- {atomic,
- case Nick of
- <<"">> ->
- ejabberd_riak:delete(muc_registered, {LUS, Host});
- _ ->
- Allow = case ejabberd_riak:get_by_index(
- muc_registered,
- muc_registered_schema(),
- <<"nick_host">>, {Nick, Host}) of
- {ok, []} ->
- true;
- {ok, [#muc_registered{us_host = {U, _Host}}]} ->
- U == LUS;
- {error, _} ->
- false
- end,
- if Allow ->
- ejabberd_riak:put(#muc_registered{us_host = {LUS, Host},
- nick = Nick},
- muc_registered_schema(),
- [{'2i', [{<<"nick_host">>,
- {Nick, Host}}]}]);
- true ->
- false
- end
- end};
-set_nick(LServer, Host, From, Nick, odbc) ->
- JID =
- jid:to_string(jid:tolower(jid:remove_resource(From))),
- SJID = ejabberd_odbc:escape(JID),
- SNick = ejabberd_odbc:escape(Nick),
- SHost = ejabberd_odbc:escape(Host),
- F = fun () ->
- case Nick of
- <<"">> ->
- ejabberd_odbc:sql_query_t([<<"delete from muc_registered where ">>,
- <<"jid='">>, SJID,
- <<"' and host='">>, Host,
- <<"';">>]),
- ok;
- _ ->
- Allow = case
- ejabberd_odbc:sql_query_t([<<"select jid from muc_registered ">>,
- <<"where nick='">>,
- SNick,
- <<"' and host='">>,
- SHost, <<"';">>])
- of
- {selected, [<<"jid">>], [[J]]} -> J == JID;
- _ -> true
- end,
- if Allow ->
- odbc_queries:update_t(<<"muc_registered">>,
- [<<"jid">>, <<"host">>,
- <<"nick">>],
- [SJID, SHost, SNick],
- [<<"jid='">>, SJID,
- <<"' and host='">>, SHost,
- <<"'">>]),
- ok;
- true -> false
- end
- end
- end,
- ejabberd_odbc:sql_transaction(LServer, F).
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:set_nick(LServer, Host, From, Nick).
iq_set_register_info(ServerHost, Host, From, Nick,
Lang) ->
@@ -1192,118 +920,17 @@ opts_to_binary(Opts) ->
Opt
end, Opts).
-update_tables(Host) ->
- update_muc_room_table(Host),
- update_muc_registered_table(Host).
-
-muc_room_schema() ->
- {record_info(fields, muc_room), #muc_room{}}.
-
-muc_registered_schema() ->
- {record_info(fields, muc_registered), #muc_registered{}}.
-
-update_muc_room_table(_Host) ->
- Fields = record_info(fields, muc_room),
- case mnesia:table_info(muc_room, attributes) of
- Fields ->
- ejabberd_config:convert_table_to_binary(
- muc_room, Fields, set,
- fun(#muc_room{name_host = {N, _}}) -> N end,
- fun(#muc_room{name_host = {N, H},
- opts = Opts} = R) ->
- R#muc_room{name_host = {iolist_to_binary(N),
- iolist_to_binary(H)},
- opts = opts_to_binary(Opts)}
- end);
- _ ->
- ?INFO_MSG("Recreating muc_room table", []),
- mnesia:transform_table(muc_room, ignore, Fields)
- end.
+export(LServer) ->
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:export(LServer).
-update_muc_registered_table(_Host) ->
- Fields = record_info(fields, muc_registered),
- case mnesia:table_info(muc_registered, attributes) of
- Fields ->
- ejabberd_config:convert_table_to_binary(
- muc_registered, Fields, set,
- fun(#muc_registered{us_host = {_, H}}) -> H end,
- fun(#muc_registered{us_host = {{U, S}, H},
- nick = Nick} = R) ->
- R#muc_registered{us_host = {{iolist_to_binary(U),
- iolist_to_binary(S)},
- iolist_to_binary(H)},
- nick = iolist_to_binary(Nick)}
- end);
- _ ->
- ?INFO_MSG("Recreating muc_registered table", []),
- mnesia:transform_table(muc_registered, ignore, Fields)
- end.
+import(LServer) ->
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ Mod:import(LServer).
-export(_Server) ->
- [{muc_room,
- fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) ->
- case str:suffix(Host, RoomHost) of
- true ->
- SName = ejabberd_odbc:escape(Name),
- SRoomHost = ejabberd_odbc:escape(RoomHost),
- SOpts = ejabberd_odbc:encode_term(Opts),
- [[<<"delete from muc_room where name='">>, SName,
- <<"' and host='">>, SRoomHost, <<"';">>],
- [<<"insert into muc_room(name, host, opts) ",
- "values (">>,
- <<"'">>, SName, <<"', '">>, SRoomHost,
- <<"', '">>, SOpts, <<"');">>]];
- false ->
- []
- end
- end},
- {muc_registered,
- fun(Host, #muc_registered{us_host = {{U, S}, RoomHost},
- nick = Nick}) ->
- case str:suffix(Host, RoomHost) of
- true ->
- SJID = ejabberd_odbc:escape(
- jid:to_string(
- jid:make(U, S, <<"">>))),
- SNick = ejabberd_odbc:escape(Nick),
- SRoomHost = ejabberd_odbc:escape(RoomHost),
- [[<<"delete from muc_registered where jid='">>,
- SJID, <<"' and host='">>, SRoomHost, <<"';">>],
- [<<"insert into muc_registered(jid, host, "
- "nick) values ('">>,
- SJID, <<"', '">>, SRoomHost, <<"', '">>, SNick,
- <<"');">>]];
- false ->
- []
- end
- end}].
-
-import(_LServer) ->
- [{<<"select name, host, opts from muc_room;">>,
- fun([Name, RoomHost, SOpts]) ->
- Opts = opts_to_binary(ejabberd_odbc:decode_term(SOpts)),
- #muc_room{name_host = {Name, RoomHost}, opts = Opts}
- end},
- {<<"select jid, host, nick from muc_registered;">>,
- fun([J, RoomHost, Nick]) ->
- #jid{user = U, server = S} =
- jid:from_string(J),
- #muc_registered{us_host = {{U, S}, RoomHost},
- nick = Nick}
- end}].
-
-import(_LServer, mnesia, #muc_room{} = R) ->
- mnesia:dirty_write(R);
-import(_LServer, mnesia, #muc_registered{} = R) ->
- mnesia:dirty_write(R);
-import(_LServer, riak, #muc_room{} = R) ->
- ejabberd_riak:put(R, muc_room_schema());
-import(_LServer, riak,
- #muc_registered{us_host = {_, Host}, nick = Nick} = R) ->
- ejabberd_riak:put(R, muc_registered_schema(),
- [{'2i', [{<<"nick_host">>, {Nick, Host}}]}]);
-import(_, _, _) ->
- pass.
+import(LServer, DBType, Data) ->
+ Mod = gen_mod:db_mod(DBType, ?MODULE),
+ Mod:import(LServer, Data).
mod_opt_type(access) ->
fun (A) when is_atom(A) -> A end;
diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl
new file mode 100644
index 00000000..e3ae3697
--- /dev/null
+++ b/src/mod_muc_mnesia.erl
@@ -0,0 +1,163 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mod_muc_mnesia).
+
+-behaviour(mod_muc).
+
+%% API
+-export([init/2, import/2, store_room/4, restore_room/3, forget_room/3,
+ can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]).
+
+-include("mod_muc.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, Opts) ->
+ MyHost = proplists:get_value(host, Opts),
+ mnesia:create_table(muc_room,
+ [{disc_copies, [node()]},
+ {attributes,
+ record_info(fields, muc_room)}]),
+ mnesia:create_table(muc_registered,
+ [{disc_copies, [node()]},
+ {attributes,
+ record_info(fields, muc_registered)}]),
+ update_tables(MyHost),
+ mnesia:add_table_index(muc_registered, nick).
+
+store_room(_LServer, Host, Name, Opts) ->
+ F = fun () ->
+ mnesia:write(#muc_room{name_host = {Name, Host},
+ opts = Opts})
+ end,
+ mnesia:transaction(F).
+
+restore_room(_LServer, Host, Name) ->
+ case catch mnesia:dirty_read(muc_room, {Name, Host}) of
+ [#muc_room{opts = Opts}] -> Opts;
+ _ -> error
+ end.
+
+forget_room(_LServer, Host, Name) ->
+ F = fun () -> mnesia:delete({muc_room, {Name, Host}})
+ end,
+ mnesia:transaction(F).
+
+can_use_nick(_LServer, Host, JID, Nick) ->
+ {LUser, LServer, _} = jid:tolower(JID),
+ LUS = {LUser, LServer},
+ case catch mnesia:dirty_select(muc_registered,
+ [{#muc_registered{us_host = '$1',
+ nick = Nick, _ = '_'},
+ [{'==', {element, 2, '$1'}, Host}],
+ ['$_']}])
+ of
+ {'EXIT', _Reason} -> true;
+ [] -> true;
+ [#muc_registered{us_host = {U, _Host}}] -> U == LUS
+ end.
+
+get_rooms(_LServer, Host) ->
+ mnesia:dirty_select(muc_room,
+ [{#muc_room{name_host = {'_', Host},
+ _ = '_'},
+ [], ['$_']}]).
+
+get_nick(_LServer, Host, From) ->
+ {LUser, LServer, _} = jid:tolower(From),
+ LUS = {LUser, LServer},
+ case mnesia:dirty_read(muc_registered, {LUS, Host}) of
+ [] -> error;
+ [#muc_registered{nick = Nick}] -> Nick
+ end.
+
+set_nick(_LServer, Host, From, Nick) ->
+ {LUser, LServer, _} = jid:tolower(From),
+ LUS = {LUser, LServer},
+ F = fun () ->
+ case Nick of
+ <<"">> ->
+ mnesia:delete({muc_registered, {LUS, Host}}),
+ ok;
+ _ ->
+ Allow = case mnesia:select(
+ muc_registered,
+ [{#muc_registered{us_host =
+ '$1',
+ nick = Nick,
+ _ = '_'},
+ [{'==', {element, 2, '$1'},
+ Host}],
+ ['$_']}]) of
+ [] -> true;
+ [#muc_registered{us_host = {U, _Host}}] ->
+ U == LUS
+ end,
+ if Allow ->
+ mnesia:write(#muc_registered{
+ us_host = {LUS, Host},
+ nick = Nick}),
+ ok;
+ true ->
+ false
+ end
+ end
+ end,
+ mnesia:transaction(F).
+
+import(_LServer, #muc_room{} = R) ->
+ mnesia:dirty_write(R);
+import(_LServer, #muc_registered{} = R) ->
+ mnesia:dirty_write(R).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+update_tables(Host) ->
+ update_muc_room_table(Host),
+ update_muc_registered_table(Host).
+
+update_muc_room_table(_Host) ->
+ Fields = record_info(fields, muc_room),
+ case mnesia:table_info(muc_room, attributes) of
+ Fields ->
+ ejabberd_config:convert_table_to_binary(
+ muc_room, Fields, set,
+ fun(#muc_room{name_host = {N, _}}) -> N end,
+ fun(#muc_room{name_host = {N, H},
+ opts = Opts} = R) ->
+ R#muc_room{name_host = {iolist_to_binary(N),
+ iolist_to_binary(H)},
+ opts = mod_muc:opts_to_binary(Opts)}
+ end);
+ _ ->
+ ?INFO_MSG("Recreating muc_room table", []),
+ mnesia:transform_table(muc_room, ignore, Fields)
+ end.
+
+update_muc_registered_table(_Host) ->
+ Fields = record_info(fields, muc_registered),
+ case mnesia:table_info(muc_registered, attributes) of
+ Fields ->
+ ejabberd_config:convert_table_to_binary(
+ muc_registered, Fields, set,
+ fun(#muc_registered{us_host = {_, H}}) -> H end,
+ fun(#muc_registered{us_host = {{U, S}, H},
+ nick = Nick} = R) ->
+ R#muc_registered{us_host = {{iolist_to_binary(U),
+ iolist_to_binary(S)},
+ iolist_to_binary(H)},
+ nick = iolist_to_binary(Nick)}
+ end);
+ _ ->
+ ?INFO_MSG("Recreating muc_registered table", []),
+ mnesia:transform_table(muc_registered, ignore, Fields)
+ end.
diff --git a/src/mod_muc_riak.erl b/src/mod_muc_riak.erl
new file mode 100644
index 00000000..bc6e5959
--- /dev/null
+++ b/src/mod_muc_riak.erl
@@ -0,0 +1,117 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mod_muc_riak).
+
+-behaviour(mod_muc).
+
+%% API
+-export([init/2, import/2, store_room/4, restore_room/3, forget_room/3,
+ can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4]).
+
+-include("mod_muc.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ ok.
+
+store_room(_LServer, Host, Name, Opts) ->
+ {atomic, ejabberd_riak:put(#muc_room{name_host = {Name, Host},
+ opts = Opts},
+ muc_room_schema())}.
+
+restore_room(_LServer, Host, Name) ->
+ case ejabberd_riak:get(muc_room, muc_room_schema(), {Name, Host}) of
+ {ok, #muc_room{opts = Opts}} -> Opts;
+ _ -> error
+ end.
+
+forget_room(_LServer, Host, Name) ->
+ {atomic, ejabberd_riak:delete(muc_room, {Name, Host})}.
+
+can_use_nick(LServer, Host, JID, Nick) ->
+ {LUser, LServer, _} = jid:tolower(JID),
+ LUS = {LUser, LServer},
+ case ejabberd_riak:get_by_index(muc_registered,
+ muc_registered_schema(),
+ <<"nick_host">>, {Nick, Host}) of
+ {ok, []} ->
+ true;
+ {ok, [#muc_registered{us_host = {U, _Host}}]} ->
+ U == LUS;
+ {error, _} ->
+ true
+ end.
+
+get_rooms(_LServer, Host) ->
+ case ejabberd_riak:get(muc_room, muc_room_schema()) of
+ {ok, Rs} ->
+ lists:filter(
+ fun(#muc_room{name_host = {_, H}}) ->
+ Host == H
+ end, Rs);
+ _Err ->
+ []
+ end.
+
+get_nick(LServer, Host, From) ->
+ {LUser, LServer, _} = jid:tolower(From),
+ US = {LUser, LServer},
+ case ejabberd_riak:get(muc_registered,
+ muc_registered_schema(),
+ {US, Host}) of
+ {ok, #muc_registered{nick = Nick}} -> Nick;
+ {error, _} -> error
+ end.
+
+set_nick(LServer, Host, From, Nick) ->
+ {LUser, LServer, _} = jid:tolower(From),
+ LUS = {LUser, LServer},
+ {atomic,
+ case Nick of
+ <<"">> ->
+ ejabberd_riak:delete(muc_registered, {LUS, Host});
+ _ ->
+ Allow = case ejabberd_riak:get_by_index(
+ muc_registered,
+ muc_registered_schema(),
+ <<"nick_host">>, {Nick, Host}) of
+ {ok, []} ->
+ true;
+ {ok, [#muc_registered{us_host = {U, _Host}}]} ->
+ U == LUS;
+ {error, _} ->
+ false
+ end,
+ if Allow ->
+ ejabberd_riak:put(#muc_registered{us_host = {LUS, Host},
+ nick = Nick},
+ muc_registered_schema(),
+ [{'2i', [{<<"nick_host">>,
+ {Nick, Host}}]}]);
+ true ->
+ false
+ end
+ end}.
+
+import(_LServer, #muc_room{} = R) ->
+ ejabberd_riak:put(R, muc_room_schema());
+import(_LServer, #muc_registered{us_host = {_, Host}, nick = Nick} = R) ->
+ ejabberd_riak:put(R, muc_registered_schema(),
+ [{'2i', [{<<"nick_host">>, {Nick, Host}}]}]).
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================
+muc_room_schema() ->
+ {record_info(fields, muc_room), #muc_room{}}.
+
+muc_registered_schema() ->
+ {record_info(fields, muc_registered), #muc_registered{}}.
diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl
new file mode 100644
index 00000000..9acd9f8d
--- /dev/null
+++ b/src/mod_muc_sql.erl
@@ -0,0 +1,202 @@
+%%%-------------------------------------------------------------------
+%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%% @copyright (C) 2016, Evgeny Khramtsov
+%%% @doc
+%%%
+%%% @end
+%%% Created : 13 Apr 2016 by Evgeny Khramtsov <ekhramtsov@process-one.net>
+%%%-------------------------------------------------------------------
+-module(mod_muc_sql).
+
+-behaviour(mod_muc).
+
+%% API
+-export([init/2, store_room/4, restore_room/3, forget_room/3,
+ can_use_nick/4, get_rooms/2, get_nick/3, set_nick/4,
+ import/1, import/2, export/1]).
+
+-include("jlib.hrl").
+-include("mod_muc.hrl").
+-include("logger.hrl").
+
+%%%===================================================================
+%%% API
+%%%===================================================================
+init(_Host, _Opts) ->
+ ok.
+
+store_room(LServer, Host, Name, Opts) ->
+ SName = ejabberd_odbc:escape(Name),
+ SHost = ejabberd_odbc:escape(Host),
+ SOpts = ejabberd_odbc:encode_term(Opts),
+ F = fun () ->
+ odbc_queries:update_t(<<"muc_room">>,
+ [<<"name">>, <<"host">>, <<"opts">>],
+ [SName, SHost, SOpts],
+ [<<"name='">>, SName, <<"' and host='">>,
+ SHost, <<"'">>])
+ end,
+ ejabberd_odbc:sql_transaction(LServer, F).
+
+restore_room(LServer, Host, Name) ->
+ SName = ejabberd_odbc:escape(Name),
+ SHost = ejabberd_odbc:escape(Host),
+ case catch ejabberd_odbc:sql_query(LServer,
+ [<<"select opts from muc_room where name='">>,
+ SName, <<"' and host='">>, SHost,
+ <<"';">>]) of
+ {selected, [<<"opts">>], [[Opts]]} ->
+ mod_muc:opts_to_binary(ejabberd_odbc:decode_term(Opts));
+ _ ->
+ error
+ end.
+
+forget_room(LServer, Host, Name) ->
+ SName = ejabberd_odbc:escape(Name),
+ SHost = ejabberd_odbc:escape(Host),
+ F = fun () ->
+ ejabberd_odbc:sql_query_t([<<"delete from muc_room where name='">>,
+ SName, <<"' and host='">>, SHost,
+ <<"';">>])
+ end,
+ ejabberd_odbc:sql_transaction(LServer, F).
+
+can_use_nick(LServer, Host, JID, Nick) ->
+ SJID = jid:to_string(jid:tolower(jid:remove_resource(JID))),
+ SNick = ejabberd_odbc:escape(Nick),
+ SHost = ejabberd_odbc:escape(Host),
+ case catch ejabberd_odbc:sql_query(LServer,
+ [<<"select jid from muc_registered ">>,
+ <<"where nick='">>, SNick,
+ <<"' and host='">>, SHost, <<"';">>]) of
+ {selected, [<<"jid">>], [[SJID1]]} -> SJID == SJID1;
+ _ -> true
+ end.
+
+get_rooms(LServer, Host) ->
+ SHost = ejabberd_odbc:escape(Host),
+ case catch ejabberd_odbc:sql_query(LServer,
+ [<<"select name, opts from muc_room ">>,
+ <<"where host='">>, SHost, <<"';">>]) of
+ {selected, [<<"name">>, <<"opts">>], RoomOpts} ->
+ lists:map(
+ fun([Room, Opts]) ->
+ #muc_room{name_host = {Room, Host},
+ opts = mod_muc:opts_to_binary(
+ ejabberd_odbc:decode_term(Opts))}
+ end, RoomOpts);
+ Err ->
+ ?ERROR_MSG("failed to get rooms: ~p", [Err]),
+ []
+ end.
+
+get_nick(LServer, Host, From) ->
+ SJID = ejabberd_odbc:escape(jid:to_string(jid:tolower(jid:remove_resource(From)))),
+ SHost = ejabberd_odbc:escape(Host),
+ case catch ejabberd_odbc:sql_query(LServer,
+ [<<"select nick from muc_registered where "
+ "jid='">>,
+ SJID, <<"' and host='">>, SHost,
+ <<"';">>]) of
+ {selected, [<<"nick">>], [[Nick]]} -> Nick;
+ _ -> error
+ end.
+
+set_nick(LServer, Host, From, Nick) ->
+ JID = jid:to_string(jid:tolower(jid:remove_resource(From))),
+ SJID = ejabberd_odbc:escape(JID),
+ SNick = ejabberd_odbc:escape(Nick),
+ SHost = ejabberd_odbc:escape(Host),
+ F = fun () ->
+ case Nick of
+ <<"">> ->
+ ejabberd_odbc:sql_query_t(
+ [<<"delete from muc_registered where ">>,
+ <<"jid='">>, SJID,
+ <<"' and host='">>, Host,
+ <<"';">>]),
+ ok;
+ _ ->
+ Allow = case ejabberd_odbc:sql_query_t(
+ [<<"select jid from muc_registered ">>,
+ <<"where nick='">>,
+ SNick,
+ <<"' and host='">>,
+ SHost, <<"';">>]) of
+ {selected, [<<"jid">>], [[J]]} -> J == JID;
+ _ -> true
+ end,
+ if Allow ->
+ odbc_queries:update_t(<<"muc_registered">>,
+ [<<"jid">>, <<"host">>,
+ <<"nick">>],
+ [SJID, SHost, SNick],
+ [<<"jid='">>, SJID,
+ <<"' and host='">>, SHost,
+ <<"'">>]),
+ ok;
+ true ->
+ false
+ end
+ end
+ end,
+ ejabberd_odbc:sql_transaction(LServer, F).
+
+export(_Server) ->
+ [{muc_room,
+ fun(Host, #muc_room{name_host = {Name, RoomHost}, opts = Opts}) ->
+ case str:suffix(Host, RoomHost) of
+ true ->
+ SName = ejabberd_odbc:escape(Name),
+ SRoomHost = ejabberd_odbc:escape(RoomHost),
+ SOpts = ejabberd_odbc:encode_term(Opts),
+ [[<<"delete from muc_room where name='">>, SName,
+ <<"' and host='">>, SRoomHost, <<"';">>],
+ [<<"insert into muc_room(name, host, opts) ",
+ "values (">>,
+ <<"'">>, SName, <<"', '">>, SRoomHost,
+ <<"', '">>, SOpts, <<"');">>]];
+ false ->
+ []
+ end
+ end},
+ {muc_registered,
+ fun(Host, #muc_registered{us_host = {{U, S}, RoomHost},
+ nick = Nick}) ->
+ case str:suffix(Host, RoomHost) of
+ true ->
+ SJID = ejabberd_odbc:escape(
+ jid:to_string(
+ jid:make(U, S, <<"">>))),
+ SNick = ejabberd_odbc:escape(Nick),
+ SRoomHost = ejabberd_odbc:escape(RoomHost),
+ [[<<"delete from muc_registered where jid='">>,
+ SJID, <<"' and host='">>, SRoomHost, <<"';">>],
+ [<<"insert into muc_registered(jid, host, "
+ "nick) values ('">>,
+ SJID, <<"', '">>, SRoomHost, <<"', '">>, SNick,
+ <<"');">>]];
+ false ->
+ []
+ end
+ end}].
+
+import(_LServer) ->
+ [{<<"select name, host, opts from muc_room;">>,
+ fun([Name, RoomHost, SOpts]) ->
+ Opts = mod_muc:opts_to_binary(ejabberd_odbc:decode_term(SOpts)),
+ #muc_room{name_host = {Name, RoomHost}, opts = Opts}
+ end},
+ {<<"select jid, host, nick from muc_registered;">>,
+ fun([J, RoomHost, Nick]) ->
+ #jid{user = U, server = S} = jid:from_string(J),
+ #muc_registered{us_host = {{U, S}, RoomHost},
+ nick = Nick}
+ end}].
+
+import(_, _) ->
+ pass.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================