Efficient way to change passwords for multiple users - parse-platform

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.

Related

Create user without populating session token

My question is very simple. Is it possible to create a user object without Parse-Server automatically creating a session token?
I have tried this code.
const myNewObject = new Parse.Object('_User');
myNewObject.set('username', 'myCustomKey1Value');
myNewObject.set('password', 'myCustomKey2Value');
let user = await myNewObject.save(null,{ useMasterKey: true });
Not working.
Any solution?

Call cloud code without logged in user Parse Server JS SDK

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
});

Migrating User to Cognito on Sign In

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.

Get a list of current clients with usernames

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.

Parse Server Access PFUser in BeforeSave Trigger

I need to check a property of my PFUser's in beforeSave triggers for each of my classes to determine if that user should be allowed to edit the piece of data they are attempting to edit.
For example, if a non-admin PFUser is attempting to edit or add to a class they shouldn't be allowed to, I want to prevent that in the beforeSave trigger. I access the keys being edited using dirtyKeys.
Parse-Server doesn't support .currentUser() like the old Parse server used to. How can I access the PFUser who is making the request? Is there a way to do it besides through session tokens?
Parse.Cloud.beforeSave("Class", function(request, response) {
//Get the keys that're being edited and iterate through them
var dirtyKeys = request.object.dirtyKeys();
for (var i = 0; i < dirtyKeys.length; ++i) {
var dirtyKey = dirtyKeys[i];
//Allow or don't allow editing of each key
if (userObject.get("<KEY>")) {
console.log('Class before save trigger IS key');
//ADD CLASS SPECIFIC FUNCTIONALITY HERE
} else {
console.log('Class before save trigger NOT key');
//ADD CLASS SPECIFIC FUNCTIONALITY HERE
}
}
});
Turns out the answer is much more obvious than I anticipated and was in the docs but I overlooked it despite my searching.
Since Parse.User.current() isn't working in Parse Server, the replacement is simply request.user. I was able to easily access all the data I needed from this and am good to go.
var user = request.user; // request.user replaces Parse.User.current()

Resources