I am making a simple chat, so when someone logs on I have this:
socket.broadcast.emit('logon', {
socketID: socket.id,
username: username
});
So if I login via chrome as "Bob", and then I log in via Edge as "Ted", I will see "Ted" when "Ted" logs in and I am looking at the chat with chrome.
But how do I get the list of current clients with usernames as soon as I log in?
So if "Ted" is already there, and I log in as "Bob" from a different browser, I want to see "Ted" in the list.
Is it possible to do without using a database to store each user that logs in, as that is the only way I can think of but would prefer not to use a database?
There is no need to use a database. The only thing you must have is an array of users that is connected to certain event listeners server side. Example:
var users = []; // Array of users online
io.on('connection', function(socket) {
var user = { // On connection, create an object for the user.
socket: socket,
username: null
}
socket.on("login",function(data) { // When the user logs in, set his username and add him to the users array.
user.username = data.username;
users.push(user);
});
socket.on("disconnect",function() { // When user disconnects, remove the object from the array.
var index = users.indexOf(user);
if (index !== -1) users.splice(index);
});
});
As you can see, there is now an array of all online users that you can access.
Related
Is it possible to call a cloud function that returns objects without having a current user? The iOS and Android SDKs support anonymous users but I'm asking specifically for JavaScript.
I'd like to allow it so that anyone who visits my web app can read objects without having to sign in. I'm using Back4App.
Yes. You can call a cloud code function no matter the user is logged in or not. Inside the cloud function you can check the user property of the request object to check if the user is either logged in or not. In the case that your user is not logged in and you want to query a class which requires user permission, you can use the useMasterKey option.
Parse.Cloud.define('myFunction', async req => {
const { user, isMaster } = req;
if (isMater) {
// the cloud code function was called using master key
} else if (user) {
// the cloud code function was called by an authenticated user
} else {
// the cloud code function was called without passing master key nor session token - not authenticated user
}
const obj = new Parse.Object('MyClass');
await obj.save(null, { useMasterKey: true }); // No matter if the user is authenticated or not, it bypasses all required permissions - you need to know what you are doing since anyone can fire this function
const query = new Parse.Query('MyClass');
return query.find({ useMasterKey: true }) // No matter if the user is authenticated or not, it bypasses all required permissions - you need to know what you are doing since anyone can fire this function
});
I am developing an application where users create custom playlists from youtube video urls and those playlist are shown at homepage. When a user click on playlist, it is redirected to a page showing videos in that particular playlist.
Technology stack: Laravel 5.8, Vue, MySql, Pusher
What I have tried so far:
Home Page Component (PublicPlaylist.vue) listens to a channel: live-playlist-playing on mounted() event
this.channel = window.Echo.channel(`live-playlist-playing`);
this.channel.listen("LivePlaylistPlaying", e => {
this.object_array.push(e);
var array = this.object_array;
var seenNames = {};
array = array.filter(function(currentObject) {
if (currentObject.playlist_id in seenNames) {
return false;
} else {
seenNames[currentObject.playlist_id] = true;
return true;
}
});
this.distinct_object = array;
})
whenever another user goes to a playlist page e.g. www.example.com/playlist/1 its component SinglePlaylist.vue calls api to fetch details:
mounted(){
window.axios
.get(
"/api/playlist/"+this.playlist_id,
{
headers: fetchAuthHeaders()
}
)
.then(response => {
this.playlist = response.data.data;
})
.catch(error => {
// if (false == isErrorHandled(error, this)) {
// consoleLog(error);
// }
});
}
Above API method broadcasts an event which is listened by the channel live-playlist-playing, as follows:
public function viewPlaylist($playlistId)
{
/**
some code
*/
broadcast(new LivePlaylistPlaying(Auth::user()->name, $playlist->playlist_name, $playlistId));
return response()->api(true, 'Playlist fetched successfully', $playlist);
}
I hope I have tried to disclose as much as details but you are free to ask for more information; coming back to question, Above code works fine for this case, steps to be taken in consideration.
suppose a user A is on home page and
now user B access the single playlist page
A will get to know a playlist is being accessed by another user.
But what if user B comes first i.e
User B accesses the single playlist page
User A comes on home page
A will not get any information about playlist being played until a user C comes in the picture.
It seems you could benefit from using Presence Channels:
This makes it extremely easy to build chat room and "who's online"
type functionality to your application. Think chat rooms,
collaborators on a document, people viewing the same web page,
competitors in a game, that kind of thing.
You will need to authorise your connections, then you can subscribe to a presence channel. Presence channels broadcast a member_removed or member_added event whenever someone joins or leaves the channel, which you can use to identify when users are on the page regardless of what order the users join the page.
I am trying to migrate users to Cognito when they sign in the first time. For this I wrote a lambda function that does call an API to check if the users exist in db or not ? if the user exists, it will be created in cognito but I am not sure how do I tell the application that user is created and it should allow the user to login .
Here is the code in c#:
public async Task<Stream> FunctionHandlerAsync(Stream stream, ILambdaContext context)
{
RootObject rootObj = DeserializeStream(stream);
User user = new User(rootObj.userName, rootObj.request.password);
ApiResponse apiResponse = await MobileAuthenticateAsync(user.UserName, user.Password);
// Considering apiResponse returns "user authenticated", we create the user in //cognito. This is working.
// How do I send response back to Application so it knows that user is // //created and authenticated and should be allowed to login.
//Before returning stream, I am setting following 2 status.
rootObj.response.finalUserStatus = "CONFIRMED"; // is this correct ?
rootObj.response.messageAction = "SUPPRESS";
return SerializeToStream(rootObj);;
}
You're pretty close.
You can see the full documentation on the Migrate User Lambda Trigger page, however in short you need your response to look like:
{
response: {
userAttributes: {
email: 'user#example.com',
email_verified: true,
custom:myAttribute: 123,
},
finalUserStatus: 'CONFIRMED',
messageAction: 'SUPPRESS',
forceAliasCreation: false,
}
}
Where:
userAttribute: this is a dictionary/map of the user's attributes keys in cognito (note that any custom attributes need to be prefixed with custom:), to the values from the system you're migrating from. You do not need to provide all of these, although if you're using an email alias you may want to set email_verified: true to prevent the user having to re-verify their e-mail address.
finalUserStatus: if you set this to CONFIRMED then the user will not have to re-confirm their email address/phone number, which is probably a sensible default. If you are concerned that the password is given as plain-text to cognito this first-time, you can instead use RESET_REQUIRED to force them to change their password on first sign-in.
messageAction: should probably be SUPPRESS unless you want to send them a welcome email on migration.
forceAliasCreation: is important only if you're using email aliases, as it stops users who manage to sign-up into cognito being replaced on migration.
If you respond with this (keeping the rest of the original rootObj is convenient but not required then the user will migrated with attributes as specified.
If you throw (or fail to respond with the correct event shape) then the migration lambda fails and the user is told that they couldn't migrated. For example, because they do not exist in your old user database, or they haven't provided the right credentials.
I am trying to access properties located on the User object for the current user in a cloud code function. The current user is passed to the cloud code function and available at request.user. The Cloud Code is deployed to Heroku using parse-cloud-express.
When the request first arrives, it does not contain the user data other than the id.
So I tried performing a fetch to get the latest data:
Parse.Cloud.define("functionName", function (request, response) {
request.user.fetch().then(function (user) {
console.log(util.inspect(user));
});
});
But it outputs the same data and does not seem to include the User object's properties.
2015-12-15T01:19:08.830880+00:00 app[web.1]: { _objCount: 1, className: '_User', id: 'dKqZMSRgDc' }
I also tried performing a query on the user id, but receive the same result.
var userQuery = new Parse.Query(Parse.User);
userQuery.get(request.user.id).then(function (user) {
console.log(util.inspect(user));
});
How do I get the properties of the User object?
The problem was not with getting data for the User object, but the way I was logging it. It seems that the data is not available from the object itself, so the output from util.inspect was correct, but does not include any properties. (I'm guessing the internals of the Parse framework manages this in another way.)
I replaced with console.log(user.toJSON()) and can now see the expected data for the user.
Due to a unprecedented flaw in the way I set up the system to login users, I would like to change passwords for multiple users based off of existing user data. (Users won't care since they are logging in through a one-click gateway).
Is there any way to do this in parse.com?
Create a background job for handling this maintenance:
Parse.Cloud.job('fixUserStuffs', function(request, status) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query(Parse.User);
query.each(function(user) {
var newPassword = // do something to generate password.
user.setPassword(newPassword);
return user.save();
}).then(function() {
status.success('All done!');
});
});
Then deploy and run this job ad-hoc through the dashboard. All users will have their passwords changed.