Role-based chat system in Nodejs - javascript

I've implemented a chat feature using socket.io and nodejs. But now I want to implement a role based chat application. For example, if someone wants to communicate with someone who is in a higher position, first needs to send a request. I've implemented a chat request system(similar to friend request). But I dont know how to make it role-based.
Can accesscontrol package be helpful in this case?
I've added a role property into the user model. I wanted to create a middleware to check what role has the user and to whom it wants to send the message. if its allowed it can continue with the 'chat', but if its not allowed I want it to redirect it to the request endpoint. I wanted to know if this logic is ok. If not, what could I do better.
EDIT: This solution with the middleware it seems to work :). If you have any better idea please answer my question

I don't have enough information to know exactly your case but it doesn't sound like you need access control. Here's my suggestion for you:
you need to store a role for each user.
when someone sends a message for the first time, you check if they can do it, doing something similar to this:
const senderRole = 'normal', receiverRole = 'extreme'; // YOU NEED TO FETCH THESE FROM YOUR DB
const roles = ['normal', 'better', 'extreme', 'best'];
if (roles.indexOf(senderRole) < roles.indexOf(receiverRole)) {
// need to ask for request
}
when they need to ask for request you would open a chat with the receiver but set in your database a special setting on the chat model: (access=false)
when the receiver goes in the app, they have a special section for chats filtered with the option (access=false), when they approve the chat, you change the setting and enable the chat to go back into the main queue and display messages

Related

Web push notification - Do I need to own a server?

I have achieved a simple push notification using source code from here: [https://itnext.io/an-introduction-to-web-push-notifications-a701783917ce][1]
But I want to do more advance by sending push notification remotely to another computer using Chrome like Facebook and some others do.
Now I am able to register subscription and get the endpoint link like this:
{
"endpoint": "https://fcm.googleapis.com/fcm/send/cThXDSA40Mo:APA91bE7lTJvxlF52GsX6huXPogc7C-nAcCrX6r9WrMSAwWToz7UDexDnLnAJJdoG-FSbQfquR8bjpd5Oc_CZQYTHU12gF_7_YmdK06CV77uXhSB6M-6LkmdjMazU5MQisXgjyUEICEd",
"keys": {
"p256dh":
"BGaCEBZSsJoqLU_l1hFWpFRwYMH8dHPkfPrPfyO2Sev_ilBYfFwJ7w4W-ppwKmxdhNTcACbi3sf7f0qerSNmQBI",
"auth":"FPssMOQPmLmXWmdSTdbKVw=="
}
}
But I don´t know how to go forward with this. Still wonder if I need to own a server or not ?
It helps if you have a server, so you can see every step of the process and understand what's happening, but if you strictly want to test your app you could use this companion site to send a notification.

How to establish a communication between two users, if the id generated by the socketIO are auto generated?

Hello I hope you are very well, I would like to ask you a question that I have not been able to deduce the answer to.
In a course I was seeing that to send a message to a specific user with socketIO.js the to () method is used and the id as a parameter, but I have a doubt, that id is auto generated by socketIO as far as I understand, so I would like to know How can the frontend know that id? The example that I saw in the course does it from the console and sends it directly to the method with the id that it already knows, then that example is not so real, what I would like to know in itself How is it that it performs a one-to-one chat if the id is autogenerated by the socket? I don't know if I understand.
For example, to start a conversation with another user, you can click on a button, trigger an event that makes emit, send the id of the user who writes, the event that should trigger the backend with socket, but my question is how does it taste like who send the message? How do you know the id of who is being sent to when establishing communication between 2 users for the first time? Obviously this must be sent by frontent as a parameter but also how does the frontend give this id of who will it be sent to? I don't know if you can store a fixed socket id for a user in a DB or Can you use your DB id to use with sockets? more than everything is what I can not deduce how it would be done?
I do not know if I understood with the question, more than everything is that, I do not know how it obtains or assigns the id for the target from where the message is sent and if this can be fixed and stored in db or is there any method to this.
I thank you in advance for your response, and any resources that you share with me about it or if you recommend a course with, I would greatly appreciate it.
as an example I have this method
io.on('connection', (client) => {
client.on('privateMessage', (data)=>{
const person = user.getPersona(client.id) //get this
client.broadcast.to(data.para).emit('privateMessage', createMsj( person.name, data.messages));
});
}
But where does the front-end of the person to receive the message to pass it to the method?
The front-end will not know the socket.io id of any other clients. This is where your server needs to be involved.
Each of your users presumably has some username that is displayed in the client UI and this is the name that other clients would know them by.
So, your server needs to keep a mapping between username and socket.io clientID. So, a user can send a request to your server to connect to BobS. Your server then needs to be able to look up BobS, find out if that user is currently connected and, if they are, then what is their socket.id value. That way, your server can facilitate connecting the two users.
This mapping would not typically be kept in a permanent store (such as a database) because the socket.id is a transient value and is only good for the duration of that client's socket.io connection. As such, it is more typically just kept in some sort of Javascript data structure (such as a Map object).

Should Token created when the user registers or login?

I have an API created by one of my team :),
And he made an endpoints "Register/Login"
his thought
When user create a user we save his data and the endpoint response it " without generating a Token"
so i can't navigate him to other screens cuz I make a request based on his Token,
So he wants me to navigate user after register to the login screen then Login endpoint will response the Token
But I think it's not a nice way and not improve UX.
So what you think we do?
generate Token in the register or log in?
The way I see this:
Solution 1:
You have him change the register API so that returns a token for you and you keep doing whatever you do with it.
Solution 2:
By registering, I'm assuming they type in a username/email, some personal details and a password!? So you have all the data to log the user in after registration. Upon successful registration, use the same username/email and password from memory (do not store them in browser storage) and call the login api to get the token (you only redirect after you've gotten the token) - so UX doesn't suffer here.
P.S. Instead of "fighting" one another over who's solution is better, try to work together in a solution. This is clearly an "I told you so" attempt - hence why I gave you two solution where both sides can do the work. Both of you can implement a solution without affecting UX, it's a matter of who's more stubborn :P

Is it possible to post to chat.postMessage as any user in a Slack team?

I'm building a Slack integration that is intended to modify some text and then post it to a Slack channel as though the user who triggered the command had said it.
e.g. /makeFace disapproval
#Ben 3:45pm
ಠ_ಠ
I ask for the client permission scope, which adds the chat:write:user permission. But when I hit the chat.postMessage endpoint, it only seems to allow you to post as the user who added the integration because the token it returns seems to be individuated for that user.
I know that giphy, for instance, sends its gif messages as though you are the originator, but I can't find out how they manage it. Is there any documentation for sending messages as other members of the team?
There are 2 ways to achieve this:
A. Overwriting username and icon
When you send a message with chat.postMessage it is possible to set a user name with the property username. The message will then appear as being send by that user (same for icon with icon_url).
However, this is not meant to impersonate real users, so even if you use the same username and icon as the real user the message will have the app tag, so that they can be distinguished from a real user.
Here is an example how it looks like (from a gamer Slack about flying and killing space ships):
But depending on what your requirements are that might work for you.
If you want to use it make sure to also set the as_user property to false (yes, really) and it will not work with a bot token, only with a user token.
See here for more details on how it works.
This also works for the legacy version of Incoming Webhooks, not with the current version of incoming webhooks though. (You can still get the legacy version, see this answer)
B. Having the user's token
Another approach is to always use the token from the respective user for sending the message. In combination with as_user = true messages sent by your app will look exactly as if they would come from the respective user (no APP tag).
To make that happen your app would need to collect tokens from all users on your workspace and store them for later use. This can be done by asking every user to install your app (called adding a "configuration") through the Oauth process (same you use to install your app to a workspace), which allows your app to collect and store those tokens for later use.
Update: This doesn't work. It impersonates the user who installed the app, so it merely seems to work... until another user tries to use it (and they end up impersonating you).
Go to your App's management page. Select "OAuth & Permissions".
Add the chat.write OAuth Scope to your app as a User Token Scope, not a Bot Token scope.
Take note of your User OAuth Token at the top of this page (not your But User OAuth Token).
Call chat.postMessage with
username = user id of the user you'd like to post on behalf of
token = the token from step 3. above
The resulting post will be 100% impersonated. Not just the name and icon as mentioned in other answers, but it'll 100% function as if it came from the user.
I hope this will help those who are still facing this issue.
First give the chat:write and chat:write.customize scope to your bot. The scope chat:write.customize Send messages as #your_slack_app with a customized username and avatar
From "OAuth & Permissions" settings get the bot OAuth token or even bot access token (both will work).
Then set the arguments like the following.
username to specify the username for the published message.
icon_url to specify a URL to an image to use as the profile photo alongside the message.
icon_emoji to specify an emoji (using colon shortcodes, eg. :white_check_mark:) to use as the profile photo alongside the message.
You can visit the docs from here

Protect PHP endpoints called by AJAX

My app consists of several PHP endpoints which are accessible via AJAX. The problem is they are also accessible via anyone who makes an HTTP request to the same endpoint. I can add checks for HTTP_X_REQUESTED_WITH and HTTP_REFERER as specified in this answer, but these can be spoofed. I could add a secret key that needs to be posted with the request, but anyone viewing the javascript and/or the console would be able to see this key. What is the solution here?
People often think that because they're using Ajax requests regular sessions don't work. They do.
If you have an endpoint to delete something from the database that's visible in the source code, such as:
example.com/user/1/delete
You can protect this request from non authenticated users the same way you would when using a non Ajax HTTP request in the browser. Using sessions. If the user has the privileges to remove users, this route will work, otherwise return an error (or do nothing).
You can also protect an API using OAuth. There's a great document here that explains how it works: http://tatiyants.com/using-oauth-to-protect-internal-rest-api/
Most of the answers are not helpful if you have your app and your api on separate domains for example app.example.com and api.example.com - in that case sessions won't work and you would have to turn to OAuth which is quite a big hammer for such a simple problem.
Here is what I would do:
I assume you have users in a database and a unique identifier like user_id=12345. I also assume that you have your Jobs in a Database and they also have unique ID's like job_id=6789.
First on app.example.com you encrypt both IDs with something fast and easy like Blowfish:
$secret_uid = mcrypt_encrypt(MCRYPT_BLOWFISH, "your_secret", strval($user_id));
$secret_jid = mcrypt_encrypt(MCRYPT_BLOWFISH, "your_secret", strval($job_id));
I assume your endpoint would work somewhat like this:
api.example.com/jobs/delete/<job_id>/<user_id>
so now from Ajax you call that endpoint, but instead of calling with plain IDs
api.example.com/jobs/delete/6789/12345
you call it with the encrypted IDs:
api.example.com/jobs/delete/6A73D5B557C622B3/57F064C07F83644F
On the API side of your software you decrypt the parameters:
$jid = mcrypt_decrypt(MCRYPT_BLOWFISH, "your_secret", <param_1>);
$uid = mcrypt_decrypt(MCRYPT_BLOWFISH, "your_secret", <param_2>);
Now you can search your db for uid and jid and perform whichever task you were planning to do. Make sure that a user can only delete his own jobs of course.
I admit this is not a 100% solution, but it leaves an attacker with a lot of guess work - he would have to guess the user_id and a matching job_id, the encryption algo and your secret. It does not protect against running millions of brute force attempts to guess a matching pair, but it put's the odds in your favor (and you should have some sort of quota limitation protection of your endpoints anyway).
Good luck!
There isn't one. If you give someone some data, then they can process it in whatever way they like. You can't control what happens to it after it leaves your server.
Likewise, you can't control what data they send to the endpoint.
it is very important for a developer to put authentication for API or web services. dchacke and BugHunterUK has given perfect answers, I just want show you simple code I use to make very simple and easy to use authentication.
Adding Session for the authentication
you can add session, and session timeout for your APIs so, only your app can use this, you can start session when front page of your app is loaded, you can set timeouts and also restrict the different service for different users by sessions.
General Idea how to do that
<?php
if(!empty($_SESSION['api_session']) && $_SESSION['api_session'] == 'usertype'){
//usertype comprise of what access you want to give
//guest, registered user, stack holder, admin etc.
...
header('Content-Type:application/json;');
echo json_encode($output);
}

Categories

Resources