Last activity for all users on ejabberd - ejabberd

We have ejabberd installed on our server.
I am using asmack 4.0.7 to interact with the ejabberd server.
I wish to know last activity (XEP-0012) of all the users.
I have 10 user accounts on our server. viz john#myserver.in, mike#myserver.in, jerry#myserver.in etc.
The behaviour of ejabberd is that to find last activity of a user, that user has to log in. I mean to check last activity of john#myserver.in, he will have to log in.
If i log in as john#myserver.in, then i successfully get last activity for john#myserver.in. With john logged in, if i retrieve last activities for mike#myserver.in, jerry#myserver.in or any other user, i get service-unavailable response for ejabberd server.
<iq from='mike#myserver.in/Smack' to='john#myserver.in/Smack' type='error' id='uHn-5'>
<query xmlns='jabber:iq:last'/><error code='503' type='cancel'>
<service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error></iq>
My requirement is that to retrieve last activity without making logins for all users.
Is that possible ?
Please let me know if any other information is required for this query.
thanks

If you want last activity of all users, this is probably for backend tasks. You should not do that using the XMPP client protocol, but with backend module (ejabberd plugin or read from last database).

Related

how to delete post using socket.io mysql nodejs express

I'm learning to do simple messaging app which allows user to add the status and in real time update it to feeds of everyone.
I am using socket.io, mysql, nodejs and express.
User can send message in real time.
In browser startup, it load all data in database.
I'd like to ask how could I delete message based in ID ?
Thanks.
Without knowing how you currently pull the post cant give as detailed of a response, but lets assume you emit that from your socket as well..
The websockets are a persistent connection to the users, because of that both client and server can emit or receive commands. With that knowledge we can now just 'emit' from the 'client' to the 'server' a command that the post has been 'deleted' when the 'client' emits to the 'server' the socket server can then delete the post from the DB, after the deletion has been completed it will then 'emit' to the 'client' who has a listener for 'postDelete' (or whatever you want to call it) that may contain the updated post list OR it could have another call that runs an update post function etc.
** Edit **
To add a bit more to this.
It's important to remember that socket.io is really just a message broker of sorts. It can GET and EMIT messages, you tell it how and what to do for each.
So to the question as to how you would go about 'deleting' the message is really no different then how you would go about it normally
(client) user clicks delete, 'emits' to server
Server is 'listening' for the 'emit' on X command to delete
Server gets command, inside of '.on' for delete is your 'delete' code (will probably be SQL to remove from DB)
After command is run and successful you will then 'emit' from server with the new payload of 'posts'
Client has a ".on" to listen for new or updated 'posts' server 'emits' to this
Client get new 'emits' from server with the updated JSON and updates the screen.

NATS - just one subscriber to take action for published event in a microservicearchitecture

I'm new to NATS and have read all the examples for:
https://nats.io/documentation/concepts/nats-messaging/
I'm in Microservciearchitecture where in microservice-Y (MSY) need to store some information published from other microservice-X (MSX) I have 2-10 instances of MSY so when changes are made in MSX and MSX-instance publishes event I want that only 1 instance of MSY should save information so not all of them save the same data.
I have read Request-Repy:
https://nats.io/documentation/concepts/nats-req-rep/
but there seems that all of instances receives message (and will handle it) even if it is point-to-point and reply is handled just for the one instance that is quickest to reply
Is this correct or have I missunderstood example?
If I only need that 1 instance of MSY should handle given message (store data in db) what can I do to acheve this?
Use queue groups. If you have multiple subscriptions on the same subject with the same queue group, only one of the members of the group will receive the message.
Check this out: https://nats.io/documentation/concepts/nats-queueing/

Sending messages to unknown users in XMPP MultiUserChat with OMEMO encryption

I'm trying to build a MUC platform with OMEMO encryption to be used on an Android app. I'm using Ejabberd (v17.11) and Smack library (v4.2.1).
MUC rooms are persistent and they allow_subscription for Muc/Sub support, for offline messages.
When a client starts a new room as 'owner' and adds 'member's from his roster; all the clients join the room and everything seem fine.
The owner can send messages to the group and it is delivered to every member.
But when a group member tries to send a message, if he doesn't 'know' all the members of the group (if they are not in his roster) he cannot send message!
I found out that, when sending OMEMO message to the group, it is necessary to encrypt the message separately for every member and this necessitates getting every members' devicelist!
On this step:
mOmemoManager.encrypt(muc, msgBody);
It tries to encrypt for all recipients but fetching an unknown user's device list causes crash.
SENT:
<iq to='unknownuser#server.com' id='141' type='get'><query xmlns='http://jabber.org/protocol/disco#info' node='eu.siacs.conversations.axolotl.devicelist'></query></iq>
RECV:
<iq xml:lang='en' to='myuser#server.com/mobile' from='unknownuser#server.com' type='error' id='141'><query node='eu.siacs.conversations.axolotl.devicelist' xmlns='http://jabber.org/protocol/disco#info'/><error code='407' type='auth'><subscription-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Not subscribed</text></error></iq>
Smack's error:
Could not fetch device list of unknownuser#server.com: .....
XMPPError: subscription-required - auth
So, how I can solve this?
In chat groups every user don't have to meet each other. Should I add everyone to everyone's roster when they come together on a group?
Or is this something about room affiliations or roles?
Or something about Ejabberd configuration?
[{title,<<"groupName">>},
{allow_query_users,true},
{allow_private_messages,true},
{allow_private_messages_from_visitors,anyone},
{allow_visitor_status,true},
{allow_visitor_nickchange,true},
{public,false},
{public_list,false},
{persistent,true},
{moderated,true},
{members_by_default,true},
{members_only,true},
{allow_user_invites,true},
{anonymous,false},
{logging,false},
{allow_voice_requests,true},
{allow_subscription,true},
{mam,true},
{presence_broadcast,[moderator,participant,visitor]},
{voice_request_min_interval,1800},
{vcard,<<>>},
{captcha_whitelist,[]},
{affiliations,[{{<<"user1">>,<<"server.com">>,<<>>},{member,<<>>}}, {{<<"user2">>,<<"server.com">>,<<>>},{owner,<<>>}}, {{<<"user3">>,<<"server.com">>,<<>>},{member,<<>>}}]},
{subject,[]},
{subject_author,<<>>}]
OMEMO requires the sender to be able to read the recipients OMEMO pubsub node. This is necessary to fetch the recipients preKey bundle to build a session.
Modern implementations configure the OMEMO pubsub node to be public - there is also an ejabberd config to force this for legacy clients.
Most client implementations of OMEMO therefore restrict the encryption feature to be available in private group chats only. In this scenario all contacts are in each others rosters and have access to each others OMEMO nodes. Encrypting publicly available group chats doesn't make sense anyways as an attacker could simply join the chat in order to read messages.
If you want to configure your OMEMO pubsub nodes to be public from within your client, take a look at how smack-openpgp does change to access model.

Spring Security Authenticates User with old credentials until Web App Restart

Hi there I am developing a web app and I am using Spring Security. In the app the user can change his/her details (username, password and some other fields). I am using a custom User Details Class for this and my Spring Security configuration is the default (keep in mind no cache method is declared, so I suppose NullUserCache is used). All the user records come from DataBase using JDBC Connector (MySQL).
Now when a user changes his/her info or/and username-password those changes update the corresponding columns in DataBase. So now the DB is updated. Because I have not implemented setters in my Custom User Details Class, I force the user to logout log out automatically. But now he/she can login using both the new username and the old one.
Suppose now that the user changed something on the other fields (for example if the age was changed from 20 to 21). When user logins using the new username I can see 21. If user logins using the old username I can see 20!.
I guess Spring Security now creates a new User (during login) which didn't exist and the old one is never removed!
So after reading many posts in the web and trying the corresponding solutions I 'm still unable to fix that.
What I have used (in the controller that is responsible for account editing):
if (authenticate != null){
new SecurityContextLogoutHandler().logout(request, response, authenticate);
}
SecurityContextHolder.getContext().setAuthentication(null);
SecurityContextHolder.clearContext();
What I understand and believe is that Spring Security holds somewhere (I thought User Cache) the username, maybe along with the password and now it sees the old username as a different User. The only way to prevent this from happening is to restart the app. After restarting the user only logins using the new username.
Is there any way I can remove that "user"-username? Any suggestion would be usefull, I am really confused and the only case close to mine was this but his problem was with the oracle connector using connection cache..
UPDATE problem tracked down to a problem inside loadbyusername method..read more on the 14th comment below :)
Happy coding!
I finally found the source of that problem..black hole closed. Credits #Jebil and #Robin Winch for their help!
Well everything worked as it should except the fact that the HashMap on the rensposible for the login DAO, was never cleared..so after every successful login attempt the HashMap returned was appended and so after every username update, it contained both old and new values..solution was simple..before accessing the DB HashMap should be cleared!
Happy dividing by 0 :P

Spring3, Security3, Hibernate, MYSQL - How to install user tracking into database

First Project: Spring3, Security3, Hibernate, MYSQL - How to install user tracking into database
I am working on my first project with Spring3, Security3, Hibernate, MYSQL.
I have the system working great I use Spring3 and Security3 goign to MySQL for the login and
using Spring3 MVC, Hibernate and MYSQL for system data.
I have a number of questions. Once I login does Spring Security save the user object somewhere that I can have
Hibrernate access it. I want Hibernate to put the user name or role into each insert to the database so as
I do my searches the system knows to only show data for that user and only that user?
this somes like it should be easy. Spring should be saving the user somewhere the hibernate can access.
please help me out
Once the user is authenticated, you can access the user's authentication session details:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
SecurityContext will allow you to grab the Authentication object, and from that you can retrieve the principal (an object representing the authenticated user), roles, etc. You could inspect this information and determine what data should be stored/displayed for each user.
If you can add a request filter or interceptor (the vocabulary may vary between frameworks), you could probably make these security checks abstract/generic enough to be applied across your entire web app (instead of adding a few lines of code to every resource method you're attempting to secure). Either way, SecurityContext should get you closer to what you want.