I am running an ejabberd XMPP server with a requirement for all MultiUserChat rooms to be configured as private by default. Only an admin user will be able to create multi user chat groups, and users will only be permitted to join if membership is granted by the admin.
ejabberd.yml configuration of MUC as per below:
#Access Rules
access_rules:
local:
allow: local
c2s:
deny: blocked
allow: all
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: admin
pubsub_createnode:
allow: admin
trusted_network:
allow: loopback
register:
allow:
user: admin
#Modules
modules:
mod_muc:
access:
- allow
access_admin:
- allow: admin
access_create: muc_create
access_persistent: muc_create
access_mam:
- allow
default_room_options:
allow_change_subj: false
allow_private_messages: false
allow_private_messages_from_visitors: nobody
allow_query_users: false
allow_subscription: false
allow_user_invites: false
allow_visitor_nickchange: false
allow_visitor_status: false
anonymous: false
captcha_protected: false
logging: false
mam: false
members_by_default: true
members_only: true
moderated: true
password_protected: false
persistent: true
presence_broadcast:
- moderator
- participant
- visitor
public: false
public_list: false
The backend application uses Smack v4.4.6 client for the admin user to connect to the server and grant membership of existing users to MUC channels as required. Demo of the admin client granting room membership:
package com.example.xmpp;
import java.io.IOException;
import java.net.InetAddress;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.MultiUserChatManager;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;
public class AdminClient {
public static void main(String[] args){
String username = "admin";
String password = "password";
String resource = "local";
String host = "example.com";
int port = 5222;
String domain = "example.com";
String channelName = "exampleChannel";
try {
XMPPTCPConnectionConfiguration.Builder builder = XMPPTCPConnectionConfiguration.builder()
.setHostAddress(InetAddress.getByName(host))
.setPort(port)
.setUsernameAndPassword(username, password)
.setXmppDomain(JidCreate.domainBareFrom(domain))
.setCompressionEnabled(true)
.setSecurityMode(ConnectionConfiguration.SecurityMode.required)
;
XMPPTCPConnectionConfiguration conf = builder.build();
XMPPTCPConnection connection = new XMPPTCPConnection(conf);
connection.connect().login();
//MUC Manager
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
//Create MUC room object
EntityBareJid jid = JidCreate.entityBareFrom(channelName); //Room JID
Resourcepart resourcePart = Resourcepart.from(resource); //Admin user resource part
MultiUserChat muc = manager.getMultiUserChat(jid); //MUC object for room
//Add member to room
String memberUsername = "user1";
EntityBareJid memberJid = JidCreate.entityBareFrom(memberUsername);
muc.grantMembership(memberJid);
//Disconnect
connection.disconnect();
} catch(IOException | XMPPException | SmackException | InterruptedException e) {
e.printStackTrace();
}
}
}
The client application will also be built using Smack 4.4.6 for android, and has a requirement to monitor which rooms the user has been granted membership of. Currently I have no way of knowing what multi user chat rooms are available on the server, nor whether membership has been granted (without actively attempting to join).
For now, I have implemented a REST API service to return a list of channel names the backend application is storing as available to the user which is called when the app is started. To avoid having to regularly call this API, I also have firebase notifications sent out when a new membership is granted so that the affected client knows to add this to their list and join. However, I would prefer to achieve this by querying the XMPPServer directly if possible.
Are there methods available to Smack client to:
- Pull a list of all multi user chat rooms (including private as all are configured this way)
- Pull a list of all room membership allocations for the currently connected user?
(Strictly speaking 1. is not required if 2. can be fulfilled by itself)