25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-20 17:27:00 +01:00

Add option to restrict max offline messages by Access and ACL (EJAB-951)

New option for mod_offline: access_max_user_messages.
The old option user_max_messages is no longer supported.

SVN Revision: 2162
This commit is contained in:
Badlop 2009-06-15 17:43:18 +00:00
parent de15168cdb
commit e0370d89b4
5 changed files with 116 additions and 40 deletions

View File

@ -2423,11 +2423,31 @@ sent to an offline user will be stored on the server until that user comes
online again. Thus it is very similar to how email works. Note that
<TT>ejabberdctl</TT> has a command to delete expired messages
(see section&#XA0;<A HREF="#ejabberdctl">4.1</A>).</P><DL CLASS="description"><DT CLASS="dt-description">
<B><TT>user_max_messages</TT></B></DT><DD CLASS="dd-description">This option
is use to set a max number of offline messages per user (quota). Its
value can be either <TT>infinity</TT> or a strictly positive
integer. The default value is <TT>infinity</TT>.
</DD></DL><P> <A NAME="modprivacy"></A> </P><!--TOC subsection <TT>mod_privacy</TT>-->
<B><TT>access_max_user_messages</TT></B></DT><DD CLASS="dd-description">
This option defines which access rule will be enforced to limit
the maximum number of offline messages that a user can have (quota).
When a user has too many offline messages, any new messages that he receive are discarded,
and a resource-constraint error is returned to the sender.
The default value is <TT>max_user_offline_messages</TT>.
Then you can define an access rule with a syntax similar to
<TT>max_user_sessions</TT> (see <A HREF="#configmaxsessions">3.1.5</A>).
</DD></DL><P>This example allows power users to have as much as 5000 offline messages,
administrators up to 2000,
and all the other users up to 100.
</P><PRE CLASS="verbatim">{acl, admin, {user, "admin1", "localhost"}}.
{acl, admin, {user, "admin2", "example.org"}}.
{acl, poweruser, {user, "bob", "example.org"}}.
{acl, poweruser, {user, "jane", "example.org"}}.
{access, max_user_offline_messages, [ {5000, poweruser}, {2000, admin}, {100, all} ]}.
{modules,
[
...
{mod_offline, [ {access_max_user_messages, max_user_offline_messages} ]},
...
]}.
</PRE><P> <A NAME="modprivacy"></A> </P><!--TOC subsection <TT>mod_privacy</TT>-->
<H3 CLASS="subsection"><!--SEC ANCHOR --><A NAME="htoc48">3.3.11</A>&#XA0;&#XA0;<A HREF="#modprivacy"><TT>mod_privacy</TT></A></H3><!--SEC END --><P> <A NAME="modprivacy"></A>
</P><P>This module implements Blocking Communication (also known as Privacy Rules)
as defined in section 10 from XMPP IM. If end users have support for it in
@ -2538,12 +2558,27 @@ is replaced at start time with the real virtual host name.
</DD><DT CLASS="dt-description"><B><TT>access_createnode</TT></B></DT><DD CLASS="dd-description">
This option restricts which users are allowed to create pubsub nodes using
ACL and ACCESS. The default value is <TT>pubsub_createnode</TT>. </DD><DT CLASS="dt-description"><B><TT>plugins</TT></B></DT><DD CLASS="dd-description"> To specify which pubsub node plugins to use. If not defined, the default
ACL and ACCESS. The default value is <TT>pubsub_createnode</TT>. </DD><DT CLASS="dt-description"><B><TT>plugins</TT></B></DT><DD CLASS="dd-description">
To specify which pubsub node plugins to use. If not defined, the default
pubsub plugin is always used.
</DD><DT CLASS="dt-description"><B><TT>nodetree</TT></B></DT><DD CLASS="dd-description"> To specify which nodetree to use. If not defined, the default pubsub
nodetree is used. Nodetrees are default and virtual. Only one nodetree can be used
</DD><DT CLASS="dt-description"><B><TT>nodetree</TT></B></DT><DD CLASS="dd-description">
To specify which nodetree to use. If not defined, the default pubsub
nodetree is used. Only one nodetree can be used per host,
and is shared by all node plugins.
</DD></DL><P>Example:
</DD><DT CLASS="dt-description"><B><TT>pep_sendlast_offline</TT></B></DT><DD CLASS="dd-description">
To specify whether or not we should get last published PEP items
from users in our roster which are offline when we connect. Value is true or false.
If not defined, pubsub assumes false so we only get last items of online contacts.
</DD><DT CLASS="dt-description"><B><TT>last_item_cache</TT></B></DT><DD CLASS="dd-description">
To specify whether or not pubsub should cache last items. Value is true
or false. If not defined, pubsub do not cache last items. On systems with not so many nodes,
caching last items speeds up pubsub and allows to raise user connection rate. The cost is memory
usage, as every item is stored in memory.
</DD><DT CLASS="dt-description"><B><TT>pep_mapping</TT></B></DT><DD CLASS="dd-description">
This allow to define a Key-Value list to choose defined node plugins on given PEP namespace.
The following example will use node_tune instead of node_pep for every PEP node with tune namespace:
<PRE CLASS="verbatim"> {mod_pubsub, [{pep_mapping, [{"http://jabber.org/protocol/tune", "tune"}]}]}
</PRE></DD></DL><P>Example:
</P><PRE CLASS="verbatim">{modules,
[
...

View File

@ -3132,12 +3132,35 @@ online again. Thus it is very similar to how email works. Note that
(see section~\ref{ejabberdctl}).
\begin{description}
\titem{user\_max\_messages}\ind{options!user\_max\_messages}This option
is use to set a max number of offline messages per user (quota). Its
value can be either \term{infinity} or a strictly positive
integer. The default value is \term{infinity}.
\titem{access\_max\_user\_messages}\ind{options!access\_max\_user\_messages}
This option defines which access rule will be enforced to limit
the maximum number of offline messages that a user can have (quota).
When a user has too many offline messages, any new messages that he receive are discarded,
and a resource-constraint error is returned to the sender.
The default value is \term{max\_user\_offline\_messages}.
Then you can define an access rule with a syntax similar to
\term{max\_user\_sessions} (see \ref{configmaxsessions}).
\end{description}
This example allows power users to have as much as 5000 offline messages,
administrators up to 2000,
and all the other users up to 100.
\begin{verbatim}
{acl, admin, {user, "admin1", "localhost"}}.
{acl, admin, {user, "admin2", "example.org"}}.
{acl, poweruser, {user, "bob", "example.org"}}.
{acl, poweruser, {user, "jane", "example.org"}}.
{access, max_user_offline_messages, [ {5000, poweruser}, {2000, admin}, {100, all} ]}.
{modules,
[
...
{mod_offline, [ {access_max_user_messages, max_user_offline_messages} ]},
...
]}.
\end{verbatim}
\makesubsection{modprivacy}{\modprivacy{}}
\ind{modules!\modprivacy{}}\ind{Blocking Communication}\ind{Privacy Rules}\ind{protocols!RFC 3921: XMPP IM}

View File

@ -379,6 +379,9 @@
%% Maximum number of simultaneous sessions allowed for a single user:
{access, max_user_sessions, [{10, all}]}.
%% Maximum number of offline messages that users can have:
{access, max_user_offline_messages, [{5000, admin}, {100, all}]},
%% This rule allows access only for local users:
{access, local, [{allow, local}]}.
@ -481,7 +484,7 @@
{access_admin, muc_admin}
]},
%%{mod_muc_log,[]},
{mod_offline, []},
{mod_offline, [{access_max_user_messages, max_user_offline_messages}]},
{mod_privacy, []},
{mod_private, []},
%%{mod_proxy65,[]},

View File

@ -30,7 +30,7 @@
-behaviour(gen_mod).
-export([start/2,
init/1,
loop/1,
stop/1,
store_packet/3,
resend_offline_messages/2,
@ -52,6 +52,9 @@
-define(PROCNAME, ejabberd_offline).
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
%% default value for the maximum number of user messages
-define(MAX_USER_MESSAGES, infinity).
start(Host, Opts) ->
mnesia:create_table(offline_msg,
[{disc_only_copies, [node()]},
@ -72,22 +75,18 @@ start(Host, Opts) ->
?MODULE, webadmin_user, 50),
ejabberd_hooks:add(webadmin_user_parse_query, Host,
?MODULE, webadmin_user_parse_query, 50),
MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, max_user_offline_messages),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [MaxOfflineMsgs])).
spawn(?MODULE, loop, [AccessMaxOfflineMsgs])).
%% MaxOfflineMsgs is either infinity of integer > 0
init(infinity) ->
loop(infinity);
init(MaxOfflineMsgs)
when is_integer(MaxOfflineMsgs), MaxOfflineMsgs > 0 ->
loop(MaxOfflineMsgs).
loop(MaxOfflineMsgs) ->
loop(AccessMaxOfflineMsgs) ->
receive
#offline_msg{us=US} = Msg ->
Msgs = receive_all(US, [Msg]),
Len = length(Msgs),
{User, Host} = US,
MaxOfflineMsgs = get_max_user_messages(AccessMaxOfflineMsgs,
User, Host),
F = fun() ->
%% Only count messages if needed:
Count = if MaxOfflineMsgs =/= infinity ->
@ -113,9 +112,18 @@ loop(MaxOfflineMsgs) ->
end
end,
mnesia:transaction(F),
loop(MaxOfflineMsgs);
loop(AccessMaxOfflineMsgs);
_ ->
loop(MaxOfflineMsgs)
loop(AccessMaxOfflineMsgs)
end.
%% Function copied from ejabberd_sm.erl:
get_max_user_messages(AccessRule, LUser, Host) ->
case acl:match_rule(
Host, AccessRule, jlib:make_jid(LUser, Host, "")) of
Max when is_integer(Max) -> Max;
infinity -> infinity;
_ -> ?MAX_USER_MESSAGES
end.
receive_all(US, Msgs) ->

View File

@ -32,7 +32,7 @@
-export([count_offline_messages/2]).
-export([start/2,
init/2,
loop/2,
stop/1,
store_packet/3,
pop_offline_messages/3,
@ -51,6 +51,9 @@
-define(PROCNAME, ejabberd_offline).
-define(OFFLINE_TABLE_LOCK_THRESHOLD, 1000).
%% default value for the maximum number of user messages
-define(MAX_USER_MESSAGES, infinity).
start(Host, Opts) ->
ejabberd_hooks:add(offline_message_hook, Host,
?MODULE, store_packet, 50),
@ -66,22 +69,17 @@ start(Host, Opts) ->
?MODULE, webadmin_user, 50),
ejabberd_hooks:add(webadmin_user_parse_query, Host,
?MODULE, webadmin_user_parse_query, 50),
MaxOfflineMsgs = gen_mod:get_opt(user_max_messages, Opts, infinity),
AccessMaxOfflineMsgs = gen_mod:get_opt(access_max_user_messages, Opts, max_user_offline_messages),
register(gen_mod:get_module_proc(Host, ?PROCNAME),
spawn(?MODULE, init, [Host, MaxOfflineMsgs])).
spawn(?MODULE, loop, [Host, AccessMaxOfflineMsgs])).
%% MaxOfflineMsgs is either infinity of integer > 0
init(Host, infinity) ->
loop(Host, infinity);
init(Host, MaxOfflineMsgs)
when is_integer(MaxOfflineMsgs), MaxOfflineMsgs > 0 ->
loop(Host, MaxOfflineMsgs).
loop(Host, MaxOfflineMsgs) ->
loop(Host, AccessMaxOfflineMsgs) ->
receive
#offline_msg{user = User} = Msg ->
Msgs = receive_all(User, [Msg]),
Len = length(Msgs),
MaxOfflineMsgs = get_max_user_messages(AccessMaxOfflineMsgs,
User, Host),
%% Only count existing messages if needed:
Count = if MaxOfflineMsgs =/= infinity ->
@ -125,9 +123,18 @@ loop(Host, MaxOfflineMsgs) ->
ok
end
end,
loop(Host, MaxOfflineMsgs);
loop(Host, AccessMaxOfflineMsgs);
_ ->
loop(Host, MaxOfflineMsgs)
loop(Host, AccessMaxOfflineMsgs)
end.
%% Function copied from ejabberd_sm.erl:
get_max_user_messages(AccessRule, LUser, Host) ->
case acl:match_rule(
Host, AccessRule, jlib:make_jid(LUser, Host, "")) of
Max when is_integer(Max) -> Max;
infinity -> infinity;
_ -> ?MAX_USER_MESSAGES
end.
receive_all(Username, Msgs) ->