Parse.com procedure for validating password requirements in Parse.Cloud.beforeSave(Parse.User - passwords

I am trying to find the best procedure for adding password requirements with Parse.com. It appears the easiest way would be to use a cloud function to execute right before user data is saved. My only caveat is that I want to validate user passwords only when the password is different from what is stored in the db or if the user does not exist in the db.
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
...
}
Couple of questions:
Does request.object.existed() work in beforeSave functions as it does with afterSave?
Can I access the user's password (using Parse.Cloud.useMasterKey()) via the request.object in the beforeSave functions? Or do I need to query the user's object inside the function.
In the log the input to the beforeSave function appears to have original and updated keys similar to the json below. However, I was not able to access the original and update json through the request.object. How would I access this data? It would be nice if the only check needed to be performed to verify whether a user's password as changed if a comparison between request.object.original.password !== request.object.updated.password
Sample cloudcode log output:
Input: {"original":{"email":"blah",
"firstname" : "blah",
"emailVerified":true,
"username":"blah",
"createdAt":"2014-04-28T23:05:47.452Z",
"updatedAt":"2014-0716T01:55:52.907Z",
"objectId":"blah",
"sessionToken":"blah"},
"update":{"firstname":"blah2"}}

Try something like this:
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
if (request.object.isNew()) {
// new object..
response.success();
} else {
if (request.object.dirtyKeys().indexOf("password") > -1) {
// Attempted to change the password.
response.error('No.');
}
}
});

Related

Accessing information of authenticated user in request scope using express

I'm using Express with TypeORM and currently I got stuck in the following situation:
Before inserting or updating a record, I always want to set the username to the current record to persist the information who last updated this record.
With TypeORM, this can easily be done by using subscribers:
#EventSubscriber()
export class Subscriber implements EntitySubscriberInterface {
beforeUpdate(event: UpdateEvent<any>) {
const entity = event.entity;
if(entity instanceof Base) {
entity.lastUpdatedBy = 'username'; // TODO
}
}
}
The user is known after he was successfully authenticated:
#Put('/entity')
public updateEntity(#CurrentUser({required: true}) user: User, #Body enity: Entity): Promise<Entity> {
Log.info('User successfully authenticated: ' + user)
return this.manager.update(entity);
}
My question is: What is the simpliest way to store and access user information in a request scope?
What I found out so far:
The following stackoverflow-post seems to be related, but the
solutions sounds like a overhead for me (GLOBAL data per HTTP/Session request?)
I also could append the user information in the updateEntity method, but then I have to explicitly all the time.
Is there any other option?
You can use the atttribute data of type any of the SaveOptions.
#Put('/entity')
public updateEntity(#CurrentUser({required: true}) user: User, #Body enity: Entity): Promise<Entity> {
Log.info('User successfully authenticated: ' + user)
return this.manager.update(entity, {data: user});
}
And then, you can use the data in Subscriber with:
event.queryRunner.data
I used the following npm package to save the user in my request scope: https://www.npmjs.com/package/cls-hooked.
This package did not work for me since async/await seems not to be supported: continuation-local-storage.

Parse Server Dashboard Column validation like User class username

I just want to know if there's a way to make the columns for a class when creating from Parse Dashboard mandatory. Just like _User class has Username, password and email required.
I suggest you use Cloud Code's beforeSave triggers for this. These beforeSave triggers are similar to validators in Mongoose: they are automatically executed before any document of that specific type is saved.
On top of checking that some fields are required, you can use it to set default values, etc.
If the trigger returns an error, the document will not be saved. If it returns a success, the flow continues and the document is saved.
Here's a quick sample to create a beforeSave on the User class:
Parse.Cloud.beforeSave(Parse.User, function (request, response) {
if (request.object.get('favouriteAnimals') === undefined) {
request.object.set('favouriteAnimals', []);
}
if (!request.object.get('firstName') || !request.object.get('lastName')) {
response.error('Full name is required.');
}
else {
response.success();
}
});

viaRemember not work - laravel

Auth :: attempt works perfect, but when you pass the second parameter "true" apparently does not care or does not recover with viaRemember
viaRemember fails to work, check this
controller User
`$`userdata = array(
'email' => trim(Input::get('username')),
'password' => trim(Input::get('password'))
);
if(Auth::attempt(`$`userdata, true)){
return Redirect::to('/dashboard');
}
view 'dashboard', always show 777
#if (Auth::viaRemember())
{{666}}
#else
{{777}}
#endif
I have hit the same obstacle, so looking into the code one can see that viaRemember is not meant to be used as a function to check if the user was logged into the system in one of all the ways a user can be logged in.
'viaRemember' is meant to check if a user was logged into the system specifically via the `viaRemember' cookie.
From what I gather, authentication of user is remembered in two ways:
a via remember cookie.
The cookie value is compared to the via remember field in the users table.
a session cookie.
The cookie value is used in the server to get the session from the
session store. On the session object from the store there is data attached. One of the
data items is the user id connected to the session. The first time
the session was created, the system attached the user id to the data
of the season.
In Illuminate\Auth\Guard class:
public function user()
{
if ($this->loggedOut) return;
// If we have already retrieved the user for the current request we can just
// return it back immediately. We do not want to pull the user data every
// request into the method because that would tremendously slow an app.
if ( ! is_null($this->user))
{
return $this->user;
}
$id = $this->session->get($this->getName());
// First we will try to load the user using the identifier in the session if
// one exists. Otherwise we will check for a "remember me" cookie in this
// request, and if one exists, attempt to retrieve the user using that.
$user = null;
if ( ! is_null($id))
{
$user = $this->provider->retrieveByID($id);
}
// If the user is null, but we decrypt a "recaller" cookie we can attempt to
// pull the user data on that cookie which serves as a remember cookie on
// the application. Once we have a user we can return it to the caller.
$recaller = $this->getRecaller();
if (is_null($user) && ! is_null($recaller))
{
$user = $this->getUserByRecaller($recaller);
}
return $this->user = $user;
}
The getUserByRecaller function is called only if the session cookie authentication did not work.
The viaRemember flag is only set in the getUserByRecaller function. The viaRemember method is only a simple getter method.
public function viaRemember()
{
return $this->viaRemember;
}
So in the end, we can use Auth::check() that does make all the checks including the viaRemember check. It calls the user() function in the Guard class.
It seems also the viaRemember is only an indicator. You need to do a type of Auth::check() the will get the process of authentication started and so the user() function will be called.
It seems that your project is on Laravel 4.0 but viaRemember() is added in Laravel 4.1! So that's expected.
in config\session.php file change the 'expire_on_close' = false to true and once you close restart your browser, it must be ok.

Meteor.loginWithPassword callback doesn't provide custom object in User accounts doc

Meteors loginWithPassword() function doesn't provide me the object systemData, which I adding to user doc (not to profile obj) during registration. The thing is, that if I look into console after logging in, I can see that object systemData (that means probably it's not publish issue), but not in callback of loginWithPassword() function, where I need them (to dynamically redirect user to proper page). Is there way to get this object, without any ugly things like timers?
Meteor.loginWithPassword(email, password, function(errorObject) {
if (errorObject) {
...
} else {
// returns true
if (Meteor.userId()) {
// returns false
if (Meteor.user().systemData) {
...
}
// user doc without systemData object
console.log(JSON.stringify(Meteor.user());
}
}
I've adding object systemData on creating user:
Accounts.onCreateUser(function(options, user) {
if (options.profile) {
user.profile = options.profile;
}
...
user.systemData = systemDataRegularUser;
return user;
});
Are you sure publish data to Client ?
I get User Info Using loginWithPassword in callback function.
Meteor.loginWithPassword username,password,(error,result1)->
options =
username: username
password: password
email: result['data']['email']
profile:
name: result['data']['display-name']
roles: result.roles
console.log Meteor.user(), result1
I Create user flowing code: (options contains systemData)
Accounts.createUser option
The first problem is that you want a custom field on a user document published to the client. This is a common question - see the answer here.
The next problem is that even after you add something like:
Meteor.publish("userData", function () {
return Meteor.users.find(this.userId, {fields: {systemData: 1}});
});
I think you still have a race condition. When you call loginWithPassword, the server will publish your user document, but it will also publish another version of the same document with the systemData field. You are hoping that both events have completed by the time Meteor.user() is called. In practice this may just work, but I'm not sure there is any guarantee that it always will. As you suggested, if you added a slight delay with a timer that would probably work but it's an ugly hack.
Alternatively, can you just add systemData to the user's profile so it will always be published?
I didn't find exact way how to solve this, but found easy workaround.
To make some action right after user logged in (eg. dynamically redirect user to proper page), you can hook on your home page with Iron router.(If you using it.) :
this.route('UsersListingHome', {
path: '/',
template: 'UsersListing',
data: function() { ... },
before: function() {
if (isCurrentUserAdmin() && Session.get('adminJustLogged') !== 'loggedIn') {
Router.go('/page-to-redirect');
Session.set('adminJustLogged','loggedIn');
}
}
});
After click on logout of course if (isCurrentUserAdmin()) { Session.set('adminJustLogged', null); }
I've further thought about calling Meteor.call('someMethod') to fetch userData object in Method callback, but now I'm satisfied.
PS: I know that it's not recommended to have plenty session variables or other reactive data source for speeding-up my app, but I believe, that one is not tragedy :)
PS2: Anyway, thanks for your answers.

How should I persist CredentialPickerResults.Credential for CredentialPickerOptions.PreviousCredential?

I am wanting to use a CredentialPicker to prompt for a username and password. When I configure an instance of this class, I can set CredentialPickerOptions.PreviousCredential to a value previously obtained by CredentialPickerResults.Credential. I believe this causes the dialog to prepopulate the credentials.
However, persisting this value appears to be non-trivial; it's an IBuffer, whose members don't appear to contain the relevant credentials. Programming Windows 8 Apps with HTML, CSS, and JavaScript, page 657, implies that this should be possible:
An IBuffer containing the credential as an opaque byte array. This is what you can
save in your own persistent state if needs be and passed back to the picker at a later time; we’ll
see how shortly.
Unfortunately, the we'll see how shortly appears to only refer to the fact that the value can be passed back from memory into PreviousCredential; I didn't find any mention of how it's persisted.
Also, I want to persist the credentials using the recommended approach, which I believe is to use PasswordVault, however, this appears to only allow me to save the credentials as username and password strings rather than an IBuffer.
Thanks for taking the time to ask, and I certainly agree that I could've been more clear in that part of the book. Admittedly, I spent less time on Chapter 14 than I would have liked, but I'll try to remedy that in the next edition. Feedback like yours is extremely valuable in knowing where I need to make improvements, so I appreciate it.
Anyway, writing a buffer to a file is something that was mentioned back in Chapter 8 (and could've been mentioned again here...page 325, though it doesn't mention IBuffer explicitly). It's a straightforward job using the Windows.Storage.FileIO class as shown below (promise!).
First, a clarification. You have two ways to save the entered credentials. If you want to save the plain-text credentials, then absolutely use the Credential Locker. The benefit here is that those credentials can roam automatically with the user if that roaming passwords is enabled in PC Settings (it is by default). Otherwise, you can save the opaque CredentialPickerResults.credential property directly to a file. It's already encrypted and scrambled, so you don't need to use the credential locker in that case.
Now for saving/loading the credential property, which is an IBuffer. For this you use FileIO.writeBufferAsync to save and FileIO.readBufferAsync to reload.
I modified the Credential Picker sample, scenario 3 to demonstrate this. To save the credential property, I added this code at the end of the completed handler for pickAsync:
//results.credential will be null if the user cancels
if (results.credential != null) {
//Having retrieved a credential, write the opaque buffer to a file
var option = Windows.Storage.CreationCollisionOption.replaceExisting;
Windows.Storage.ApplicationData.current.localFolder.createFileAsync("credbuffer.dat", option).then(function (file) {
return Windows.Storage.FileIO.writeBufferAsync(file, results.credential);
}).done(function () {
//No results for this operation
console.log("credbuffer.dat written.");
}, function (e) {
console.log("Could not create credbuffer.dat file.");
});
}
Then I created a new function to load that credential, if possible. This is called on the Launch button click instead of launchCredPicker:
//In the page ready method:
document.getElementById("button1").addEventListener("click", readPrevCredentialAndLaunch, false);
//Added
function readPrevCredentialAndLaunch() {
Windows.Storage.ApplicationData.current.localFolder.getFileAsync("credbuffer.dat").then(function (file) {
return Windows.Storage.FileIO.readBufferAsync(file);
}).done(function (buffer) {
console.log("Read from credbuffer.dat");
launchCredPicker(buffer);
}, function (e) {
console.log("Could not reopen credbuffer.dat; launching default");
launchCredPicker(null);
});
}
//Modified to take a buffer
function launchCredPicker(prevCredBuffer) {
try {
var options = new Windows.Security.Credentials.UI.CredentialPickerOptions();
//Other options omitted
if (prevCredBuffer != null) {
options.previousCredential = prevCredBuffer;
}
//...
That's it. I put the modified JS sample on http://www.kraigbrockschmidt.com/src/CredentialPickerJS_modified.zip.
.Kraig
Author, Programming Windows 8 Apps in HTML, CSS, and JavaScript (free ebook)