Create Multi User Group with Prosody Server on Android (aSmack) failes with "Missing acknowledge of room creation" - xmpp

i am working on XMPP chat app in android, using Prosody as XMPP server.
i have written code for create Multi User Chat room and its working fine when i am using Openfire as server, but when i use Prosody as server it gives me error, as
Creation failed - Missing acknowledge of room creation.:
i.e group is already exist. but it throws same error for any name(New Group Name).
if i replace muc.create(name); with muc.join(name); it creates group. but then i am unable to configure group/room properties.
below is my Prosody Config File:-
modules_enabled = {
-- Generally required
"roster"; -- Allow users to have a roster. Recommended ;)
"saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
--"tls"; -- Add support for secure TLS on c2s/s2s connections
"dialback"; -- s2s dialback support
"disco"; -- Service discovery
-- Not essential, but recommended
"private"; -- Private XML storage (for room bookmarks, etc.)
"vcard"; -- Allow users to set vCards
-- These are commented by default as they have a performance impact
--"privacy"; -- Support privacy lists
--"compression"; -- Stream compression
-- Nice to have
"version"; -- Replies to server version requests
"uptime"; -- Report how long server has been running
"time"; -- Let others know the time here on this server
"ping"; -- Replies to XMPP pings with pongs
"pep"; -- Enables users to publish their mood, activity, playing music and more
"register"; -- Allow users to register on this server using a client and change passwords
-- Admin interfaces
"admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
--"admin_telnet"; -- Opens telnet console interface on localhost port 5582
-- HTTP modules
"bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
"http_files"; -- Serve static files from a directory over HTTP
-- Other specific functionality
"groups"; -- Shared roster support
--"announce"; -- Send announcement to all online users
--"welcome"; -- Welcome users who register accounts
--"watchregistrations"; -- Alert admins of registrations
--"motd"; -- Send a message to users when they log in
--"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
};
allow_registration = true -- Allow users to register new accounts
VirtualHost "localhost"
---Set up a MUC (multi-user chat) room server on conference.example.com:
Component "conference.localhost" "muc"
My Group Create Code is:-
MultiUserChat muc = new MultiUserChat(xmppConnection, room);
// Create the room
SmackConfiguration.setPacketReplyTimeout(2000);
String name = xmppConnection.getUser();
System.out.println("name:- " + name);
String name1 = name.substring(0, name.lastIndexOf("#"));
System.out.println("name1:- " + name1);
System.out.println("group name:- " + grpName);
muc.create(name1);
// Get the the room's configuration form
Form form = muc.getConfigurationForm();
// Create a new form to submit based on the original form
Form submitForm = form.createAnswerForm();
// Add default answers to the form to submit
for (Iterator<FormField> fields = form.getFields(); fields.hasNext();) {
FormField field = (FormField) fields.next();
if (!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) {
// Sets the default value as the answer
submitForm.setDefaultAnswer(field.getVariable());
}
}
// muc.sendConfigurationForm(submitForm);
Form f = new Form(Form.TYPE_SUBMIT);
try {
muc.sendConfigurationForm(f);
} catch (XMPPException xe) {
System.out.println( "Error on sendConfigurationForm:- " + xe);
}
// Sets the new owner of the room
List<String> owners = new ArrayList<String>();
owners.add(xmppConnection.getUser());
submitForm.setAnswer("muc#roomconfig_roomowners", owners);
submitForm.setAnswer("muc#roomconfig_persistentroom", true);
muc.sendConfigurationForm(submitForm);
where i am going wrong?

This is caused by non-standard behavior of prosody's MUC plugin. Basically it behaves like a MUC room already exists, even if it's not the case.
You have to possibilites:
Using Smack's (since 4.0) MultiUserChat.createOrJoin(String), will succeed in this case. See also SMACK-557
Setting prosody's mod MUC property restrict_room_creation to true, will make prosody behaves as specified in XEP-45
Since you want to configure the room, the only option is changing prosody's restrict_room_creation setting.
Note that there is another issue in Smack's MUC code, that will be fixed in Smack 4.1 and likely there will also be a workaround implemented in prosody. But I don't think that this issue is related here, the info is just for completeness.

Related

How to make Keycloak 20.0.1 send an e-mail when a user is blocked due to too many failed login attempts?

I want Keycloak to send an e-mail to a user whenever a user is blocked due to too many failed login attempts (see section Realm Settings -> Security defenses -> Brute force detection).
The event in question has the following properties:
Error (org.keycloak.events.Event#getError) = user_temporarily_disabled
Type (org.keycloak.events.Event#getType) = LOGIN_ERROR
How can I do that, i. e. make Keycloak send an e-mail to the user when such event occurs?
Known ways to implement it
One obvious way to do it is to write a class that implements the org.keycloak.events.EventListenerProvider interface, detect the event in its onEvent method and trigger sending of the e-mail at some custom server (i. e. send a request to that server and it will contact an SMTP server).
Second is a variation: Detect the event in the same method and somehow make Keycloak send the e-mail using Keycloak SMTP settings ("Realm settings -> Email -> Connection & Authentication").
The screenshot in this answer made met think (possibly wrongly) that there may be a way to make Keycloak send emails upon the occurrence of certain events "out of the box," i. e. without writing custom event listeners.
Update 1: If someone else wants to do this, I recommend to look at this answer. The code below worked for me.
RealmModel realm = this.model.getRealm(event.getRealmId());
UserModel user = this.session.users().getUserById(event.getUserId(), realm);
if (user != null && user.getEmail() != null) {
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>" + user.getEmail());
org.keycloak.email.DefaultEmailSenderProvider senderProvider = new org.keycloak.email.DefaultEmailSenderProvider(session);
try {
senderProvider.send(session.getContext().getRealm().getSmtpConfig(), user, "test", "body test",
"html test");
} catch (EmailException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Keycloak does indeed support sending emails for events out of the box. However, it can only be configured by event (LOGIN_ERROR), and not by further filtered types (user_temporarily_disabled).
For this, you will need to implement your own EventListener, but it should be easy to heavily copy code from Keycloak's existing EmailEventListener, which you can find here: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/events/email/EmailEventListenerProvider.java
In there, you'd change the implementation of L59 in onEvent(Event event) to check your two conditions (event type and error), rather than checking against some list of configured fixed events. Your event will be added to the currently running transaction, and when the transaction ends (in success or error), Keycloak will send an email via the SMTP settings that are configured in the realm.
If you want to customize the template and subject lines of the email, you'll have to provide your own freemarker templates in src/main/resources/theme-resources/templates/{html,text}. Both the html and text folder need to contain an .ftl file of the same name. Message keys for use in the template and the subject go in src/main/resources/messages/messages_{en,fr,de,...}.properties files.
With the template and messages configured, you can use one of the 2 send(...) methods available in the EmailTemplateProvider class

Get triggered rule names which is executing on decision server from client side (Redhat Decision Manager)

I am using the REST api for executing rules on Decision Server (Redhat Decision Manager 7.2) using a stateless kie session. I'm currently getting the number of triggered rules, but I also want to get the names of those rules. Is this possible?
KieServicesConfiguration conf = KieServicesFactory.newRestConfiguration(URL, USER, PASSWORD);
List<GenericCommand<?>> commands = new ArrayList<GenericCommand<?>>();
commands.add((GenericCommand<?>)
KieServices.Factory.get().getCommands().newInsert(applicant, "applicant"));
commands.add((GenericCommand<?>)
KieServices.Factory.get().getCommands().newInsert(loan, "loan"));
commands.add((GenericCommand<?>)KieServices.Factory.get().getCommands().newFireAllRules("numberOfFiredRules"));
KieCommands kieCommands = KieServices.Factory.get().getCommands();
BatchExecutionCommand batchCommand = kieCommands.newBatchExecution(commands, "default-stateless-ksession");
ServiceResponse<ExecutionResults> executeResponse = ruleServicesClient
.executeCommandsWithResults("loan-application_1.2.0", batchCommand);
System.out.println("Number of fired rules:" executeResponse.getResult().getValue("numberOfFiredRules"));
You have to use an AgendaEventListener to keep track of rules exectioned. By implemnting org.kie.api.event.rule.AgendaEventListener interface you can capture these detials.
To know which rules are triggered I added an action column with custom code (Action BRL fragment) that writes the rule name in one of the field of my fact. You can get it from rule.name.
Example:myFact.logMyRuleName(rule.name)

Is there a way to fetch latest email from "Mail reader sampler" or "Beanshell Sampler"

I am able to fetch email from my email account using POP3 via "Mail Reader Sampler" listener. But its not retrieving latest email.
Is it possible to extract the latest email using Beanshell Sampler. If yes, can you please share the code if this is achievable.
As per below discussion - looks like it is not doable. But, wanted to check if this is achievable using any means?
Stackoverflow Discussion on how to fetch required email
You can do this programmatically, check out the following methods:
Folder.getMessageCount() - Get total number of messages in this Folder
Folder.getMessage(int msgnum) - Get the Message object corresponding to the given message number
According to the JavaDoc
Messages are numbered starting at 1 through the total number of message in the folder.
So the number of the last message will always be the same as the total number of messages in the given folder.
Example code which reads last email using POP3 protocol
import javax.mail.Folder
import javax.mail.Message
import javax.mail.Session
import javax.mail.Store
String host = "host"
String user = "username"
String password = "password"
Properties properties = System.getProperties();
Session session = Session.getDefaultInstance(properties)
Store store = session.getStore("pop3")
store.connect(host, user, password)
Folder inbox = store.getFolder("Inbox")
inbox.open(Folder.READ_ONLY)
int msgCount = inbox.getMessageCount()
Message last = inbox.getMessage(msgCount)
//do what you need with the "last" message
inbox.close(true)
store.close()
I would also recommend forgetting about Beanshell, whenever you need to perform scripting - use JSR223 Elements and Groovy language as Groovy has much better performance, it is more Java-compliant and it has some nice language features. See Apache Groovy - Why and How You Should Use It guide for more details.

Does IMAP search work on outlook.com

I'm new to IMAP.
I'm trying to fetch mails from outlook.com, I have configured outlook.com IMAP settings in my email client. I'm able to connect and get messages from outlook.com.
But when I'm trying to get messages by using search term like
I'm using Java mail packages.
IMAPStore store = getStore(serverName, userName, password, port);
IMAPFolder inboxFolder = (IMAPFolder) store.getFolder("INBOX");
SearchTerm[] searchTerms = new SearchTerm[4];
Address address = new InternetAddress("search_email_address");
SearchTerm toTerm = new RecipientTerm(Message.RecipientType.TO, address);
SearchTerm ccTerm = new RecipientTerm(Message.RecipientType.CC, address);
SearchTerm bccTerm = new RecipientTerm(Message.RecipientType.BCC, address);
SearchTerm fromStringTerm = new FromStringTerm(searchEmail);
searchTerms[0] = toTerm;
searchTerms[1] = ccTerm;
searchTerms[2] = bccTerm;
searchTerms[3] = fromStringTerm;
OrTerm orTerms = new OrTerm(searchTerms);
inboxFolder.search(orTerms);
I'm trying to search mails using like above search terms in a IMAP folder, but I'm getting zero mails.
Any API limitations in this or any problems in code, please guide me
Thanks
Ramesh
Looking at the question "Does IMAP search work on outlook.com" I can say: Yes.
I'm using imapsync to sync from outlook.com to other mailboxes and it works. Behind the scenes imapsync uses IMAP searches.
The IMAP capabilities announced by outlook.com are:
IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CLIENTACCESSRULES CLIENTNETWORKPRESENCELOCATION BACKENDAUTHENTICATE CHILDREN IDLE NAMESPACE LITERAL+ AUTH
Maybe this helps somebody. This could also explain why certain search keywords might or might not work.

Smack service discovery without login gives bad-request(400)

I am trying to discover items that a pubsub service provides. When I log into the target server, I can get the response successfully. But when I connect bu do not login, it gives a bad request error.
This is the code:
ConnectionConfiguration config = new ConnectionConfiguration(serverAddress, 5222);
config.setServiceName(serviceName);
connection = new XMPPConnection(config);
connection.connect();
connection.login(userName, password); //!!!when I remove this line, bad request error is received
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
DiscoverItems items;
try {
items = discoManager.discoverItems("pubsubservice." + serverName);
} catch (XMPPException e) {
e.printStackTrace();
}
Is there a way to discover items when the user is not logged in, but the connection is established?
No, you must authenticate to send stanzas to any JID in XMPP (otherwise they would not be able to reply to you, since they wouldn't know your address).
Perhaps one option for you is anonymous authentication. Most servers support it, and it creates a temporary account on the server for you, with a temporary JID. You don't need a password, and login time is quick.
#MattJ is correct and you could try using anon login. That will get you part way there.
Your current request will only get you the nodes though, after which you will have to get the items for each node. It would be simpler to use PubsubManager to get the information you want since it provides convenience methods for accessing/using all things pubsub.
Try the documentation here, the getAffiliations() method is what you are looking for.
BTW, I believe the typical default service name for pubsub is pubsub not pubsubservice. At least this is the case for Openfire.