mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
Merge pull request #3051 from jgable/loginValidation
Add validation for signin/signup
This commit is contained in:
commit
38fa7c42f1
13 changed files with 218 additions and 112 deletions
|
@ -1,19 +1,32 @@
|
||||||
/*global console, alert */
|
import ValidationEngine from 'ghost/mixins/validation-engine';
|
||||||
|
|
||||||
var ForgottenController = Ember.Controller.extend({
|
var ForgottenController = Ember.Controller.extend(ValidationEngine, {
|
||||||
email: '',
|
email: '',
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
|
// ValidationEngine settings
|
||||||
|
validationType: 'forgotten',
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
submit: function () {
|
submit: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.user.fetchForgottenPasswordFor(this.email)
|
|
||||||
.then(function () {
|
this.toggleProperty('submitting');
|
||||||
alert('@TODO Notification: Success');
|
this.validate({ format: false }).then(function () {
|
||||||
self.transitionToRoute('signin');
|
self.user.fetchForgottenPasswordFor(this.email)
|
||||||
})
|
.then(function () {
|
||||||
.catch(function (response) {
|
self.toggleProperty('submitting');
|
||||||
alert('@TODO');
|
self.notifications.showSuccess('Please check your email for instructions.');
|
||||||
console.log(response);
|
self.transitionToRoute('signin');
|
||||||
});
|
})
|
||||||
|
.catch(function (resp) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
|
||||||
|
});
|
||||||
|
}).catch(function (errors) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
62
ghost/admin/controllers/signin.js
Normal file
62
ghost/admin/controllers/signin.js
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import ajax from 'ghost/utils/ajax';
|
||||||
|
import ValidationEngine from 'ghost/mixins/validation-engine';
|
||||||
|
|
||||||
|
var SigninController = Ember.ObjectController.extend(ValidationEngine, {
|
||||||
|
needs: 'application',
|
||||||
|
email: null,
|
||||||
|
password: null,
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
|
// ValidationEngine settings
|
||||||
|
validationType: 'signin',
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
login: function () {
|
||||||
|
var self = this,
|
||||||
|
data = this.getProperties('email', 'password'),
|
||||||
|
//Data to check if user came in somewhere besides index
|
||||||
|
appController = this.get('controllers.application'),
|
||||||
|
loginTransition = appController.get('loginTransition');
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
this.validate({ format: false }).then(function () {
|
||||||
|
ajax({
|
||||||
|
url: self.get('ghostPaths').adminUrl('signin'),
|
||||||
|
type: 'POST',
|
||||||
|
headers: {'X-CSRF-Token': self.get('csrf')},
|
||||||
|
data: data
|
||||||
|
}).then(function (response) {
|
||||||
|
// once the email and password are pulled from the controller
|
||||||
|
// they need to be cleared, or they will reappear next time the signin
|
||||||
|
// page is visited
|
||||||
|
self.setProperties({
|
||||||
|
email: '',
|
||||||
|
password: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
self.store.pushPayload({users: [response.userData]});
|
||||||
|
return self.store.find('user', response.userData.id);
|
||||||
|
}).then(function (user) {
|
||||||
|
self.send('signedIn', user);
|
||||||
|
self.notifications.clear();
|
||||||
|
if (loginTransition) {
|
||||||
|
appController.set('loginTransition', null);
|
||||||
|
loginTransition.retry();
|
||||||
|
} else {
|
||||||
|
self.transitionTo('posts');
|
||||||
|
}
|
||||||
|
}).catch(function (resp) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
|
||||||
|
});
|
||||||
|
}).catch(function (errors) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
self.notifications.clear();
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SigninController;
|
50
ghost/admin/controllers/signup.js
Normal file
50
ghost/admin/controllers/signup.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import ajax from 'ghost/utils/ajax';
|
||||||
|
import ValidationEngine from 'ghost/mixins/validation-engine';
|
||||||
|
|
||||||
|
var SignupController = Ember.ObjectController.extend(ValidationEngine, {
|
||||||
|
name: null,
|
||||||
|
email: null,
|
||||||
|
password: null,
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
|
// ValidationEngine settings
|
||||||
|
validationType: 'signup',
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
signup: function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.toggleProperty('submitting');
|
||||||
|
this.validate({ format: false }).then(function () {
|
||||||
|
ajax({
|
||||||
|
url: self.get('ghostPaths').adminUrl('signup'),
|
||||||
|
type: 'POST',
|
||||||
|
headers: {
|
||||||
|
'X-CSRF-Token': self.get('csrf')
|
||||||
|
},
|
||||||
|
data: self.getProperties('name', 'email', 'password')
|
||||||
|
}).then(function (resp) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
if (resp && resp.userData) {
|
||||||
|
self.store.pushPayload({ users: [resp.userData]});
|
||||||
|
self.store.find('user', resp.userData.id).then(function (user) {
|
||||||
|
self.send('signedIn', user);
|
||||||
|
self.notifications.clear();
|
||||||
|
self.transitionTo('posts');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.transitionTo('signin');
|
||||||
|
}
|
||||||
|
}, function (resp) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
self.notifications.showAPIError(resp);
|
||||||
|
});
|
||||||
|
}, function (errors) {
|
||||||
|
self.toggleProperty('submitting');
|
||||||
|
self.notifications.showErrors(errors);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SignupController;
|
|
@ -2,15 +2,23 @@ import { getRequestErrorMessage } from 'ghost/utils/ajax';
|
||||||
|
|
||||||
import ValidatorExtensions from 'ghost/utils/validator-extensions';
|
import ValidatorExtensions from 'ghost/utils/validator-extensions';
|
||||||
import PostValidator from 'ghost/validators/post';
|
import PostValidator from 'ghost/validators/post';
|
||||||
|
import SignupValidator from 'ghost/validators/signup';
|
||||||
|
import SigninValidator from 'ghost/validators/signin';
|
||||||
|
import ForgotValidator from 'ghost/validators/forgotten';
|
||||||
|
|
||||||
ValidatorExtensions.init();
|
ValidatorExtensions.init();
|
||||||
|
|
||||||
var ValidationEngine = Ember.Mixin.create({
|
var ValidationEngine = Ember.Mixin.create({
|
||||||
validators: {
|
validators: {
|
||||||
post: PostValidator
|
post: PostValidator,
|
||||||
|
signup: SignupValidator,
|
||||||
|
signin: SigninValidator,
|
||||||
|
forgotten: ForgotValidator
|
||||||
},
|
},
|
||||||
|
|
||||||
validate: function () {
|
validate: function (opts) {
|
||||||
|
opts = opts || {};
|
||||||
|
|
||||||
var self = this,
|
var self = this,
|
||||||
type = this.get('validationType'),
|
type = this.get('validationType'),
|
||||||
validator = this.get('validators.' + type);
|
validator = this.get('validators.' + type);
|
||||||
|
@ -26,7 +34,11 @@ var ValidationEngine = Ember.Mixin.create({
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return reject(self.formatErrors(validationErrors));
|
if (opts.format !== false) {
|
||||||
|
validationErrors = self.formatErrors(validationErrors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reject(validationErrors);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,58 +1,8 @@
|
||||||
import ajax from 'ghost/utils/ajax';
|
|
||||||
import styleBody from 'ghost/mixins/style-body';
|
import styleBody from 'ghost/mixins/style-body';
|
||||||
import loadingIndicator from 'ghost/mixins/loading-indicator';
|
import loadingIndicator from 'ghost/mixins/loading-indicator';
|
||||||
|
|
||||||
var isEmpty = Ember.isEmpty;
|
|
||||||
|
|
||||||
var SigninRoute = Ember.Route.extend(styleBody, loadingIndicator, {
|
var SigninRoute = Ember.Route.extend(styleBody, loadingIndicator, {
|
||||||
classNames: ['ghost-login'],
|
classNames: ['ghost-login']
|
||||||
|
|
||||||
actions: {
|
|
||||||
login: function () {
|
|
||||||
var self = this,
|
|
||||||
controller = this.get('controller'),
|
|
||||||
data = controller.getProperties('email', 'password'),
|
|
||||||
//Data to check if user came in somewhere besides index
|
|
||||||
appController = this.controllerFor('application'),
|
|
||||||
loginTransition = appController.get('loginTransition');
|
|
||||||
|
|
||||||
if (!isEmpty(data.email) && !isEmpty(data.password)) {
|
|
||||||
|
|
||||||
ajax({
|
|
||||||
url: this.get('ghostPaths').adminUrl('signin'),
|
|
||||||
type: 'POST',
|
|
||||||
headers: {'X-CSRF-Token': this.get('csrf')},
|
|
||||||
data: data
|
|
||||||
}).then(function (response) {
|
|
||||||
// once the email and password are pulled from the controller
|
|
||||||
// they need to be cleared, or they will reappear next time the signin
|
|
||||||
// page is visited
|
|
||||||
controller.setProperties({
|
|
||||||
email: '',
|
|
||||||
password: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
self.store.pushPayload({users: [response.userData]});
|
|
||||||
return self.store.find('user', response.userData.id);
|
|
||||||
}).then(function (user) {
|
|
||||||
self.send('signedIn', user);
|
|
||||||
self.notifications.clear();
|
|
||||||
if (loginTransition) {
|
|
||||||
appController.set('loginTransition', null);
|
|
||||||
loginTransition.retry();
|
|
||||||
} else {
|
|
||||||
self.transitionTo('posts');
|
|
||||||
}
|
|
||||||
}).catch(function (resp) {
|
|
||||||
self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.notifications.clear();
|
|
||||||
|
|
||||||
this.notifications.showError('Must enter email + password');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default SigninRoute;
|
export default SigninRoute;
|
|
@ -1,49 +1,8 @@
|
||||||
import ajax from 'ghost/utils/ajax';
|
|
||||||
import styleBody from 'ghost/mixins/style-body';
|
import styleBody from 'ghost/mixins/style-body';
|
||||||
import loadingIndicator from 'ghost/mixins/loading-indicator';
|
import loadingIndicator from 'ghost/mixins/loading-indicator';
|
||||||
|
|
||||||
var SignupRoute = Ember.Route.extend(styleBody, loadingIndicator, {
|
var SignupRoute = Ember.Route.extend(styleBody, loadingIndicator, {
|
||||||
classNames: ['ghost-signup'],
|
classNames: ['ghost-signup']
|
||||||
|
|
||||||
name: null,
|
|
||||||
email: null,
|
|
||||||
password: null,
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
signup: function () {
|
|
||||||
var self = this,
|
|
||||||
controller = this.get('controller'),
|
|
||||||
data = controller.getProperties('name', 'email', 'password');
|
|
||||||
|
|
||||||
// TODO: Validate data
|
|
||||||
|
|
||||||
if (data.name && data.email && data.password) {
|
|
||||||
ajax({
|
|
||||||
url: '/ghost/signup/',
|
|
||||||
type: 'POST',
|
|
||||||
headers: {
|
|
||||||
'X-CSRF-Token': this.get('csrf')
|
|
||||||
},
|
|
||||||
data: data
|
|
||||||
}).then(function (resp) {
|
|
||||||
if (resp && resp.userData) {
|
|
||||||
self.store.pushPayload({ users: [resp.userData]});
|
|
||||||
self.store.find('user', resp.userData.id).then(function (user) {
|
|
||||||
self.send('signedIn', user);
|
|
||||||
self.notifications.clear();
|
|
||||||
self.transitionTo('posts');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
self.transitionTo('signin');
|
|
||||||
}
|
|
||||||
}, function (resp) {
|
|
||||||
self.notifications.showAPIError(resp);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.notifications.showError('Must provide name, email and password');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default SignupRoute;
|
export default SignupRoute;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<section class="forgotten-box js-forgotten-box fade-in">
|
<section class="forgotten-box js-forgotten-box fade-in">
|
||||||
<form id="forgotten" class="forgotten-form" method="post" novalidate="novalidate" {{action "submit" on="submit"}}>
|
<form id="forgotten" class="forgotten-form" method="post" novalidate="novalidate">
|
||||||
<div class="email-wrap">
|
<div class="email-wrap">
|
||||||
{{input value=email class="email" type="email" placeholder="Email Address" name="email" autofocus="autofocus" autocapitalize="off" autocorrect="off"}}
|
{{input value=email class="email" type="email" placeholder="Email Address" name="email" autofocus="autofocus" autocapitalize="off" autocorrect="off"}}
|
||||||
</div>
|
</div>
|
||||||
<button class="button-save" type="submit">Send new password</button>
|
<button class="button-save" type="submit" {{action "submit"}} {{bind-attr disabled=submitting}}>Send new password</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<div class="password-wrap">
|
<div class="password-wrap">
|
||||||
{{input class="password" type="password" placeholder="Password" name="password" value=password}}
|
{{input class="password" type="password" placeholder="Password" name="password" value=password}}
|
||||||
</div>
|
</div>
|
||||||
<button class="button-save" type="submit" {{action "login"}}>Log in</button>
|
<button class="button-save" type="submit" {{action "login"}} {{bind-attr disabled=submitting}}>Log in</button>
|
||||||
<section class="meta">
|
<section class="meta">
|
||||||
{{#link-to 'forgotten' class="forgotten-password"}}Forgotten password?{{/link-to}}
|
{{#link-to 'forgotten' class="forgotten-password"}}Forgotten password?{{/link-to}}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
<div class="password-wrap">
|
<div class="password-wrap">
|
||||||
{{input class="password" type="password" placeholder="Password" name="password" value=password }}
|
{{input class="password" type="password" placeholder="Password" name="password" value=password }}
|
||||||
</div>
|
</div>
|
||||||
<button class="button-save" type="submit" {{action "signup"}}>Sign Up</button>
|
<button class="button-save" type="submit" {{action "signup"}} {{bind-attr disabled=submitting}}>Sign Up</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -48,7 +48,7 @@ var Notifications = Ember.ArrayProxy.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
closeAll: function () {
|
closeAll: function () {
|
||||||
window.alert('@TODO implement closeALl notifications');
|
this.clear();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
14
ghost/admin/validators/forgotten.js
Normal file
14
ghost/admin/validators/forgotten.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
var ForgotValidator = Ember.Object.create({
|
||||||
|
validate: function (model) {
|
||||||
|
var data = model.getProperties('email'),
|
||||||
|
validationErrors = [];
|
||||||
|
|
||||||
|
if (!validator.isEmail(data.email)) {
|
||||||
|
validationErrors.push('Invalid Email');
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationErrors;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ForgotValidator;
|
18
ghost/admin/validators/signin.js
Normal file
18
ghost/admin/validators/signin.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
var SigninValidator = Ember.Object.create({
|
||||||
|
validate: function (model) {
|
||||||
|
var data = model.getProperties('email', 'password'),
|
||||||
|
validationErrors = [];
|
||||||
|
|
||||||
|
if (!validator.isEmail(data.email)) {
|
||||||
|
validationErrors.push('Invalid Email');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validator.isLength(data.password || '', 1)) {
|
||||||
|
validationErrors.push('Please enter a password');
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationErrors;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SigninValidator;
|
28
ghost/admin/validators/signup.js
Normal file
28
ghost/admin/validators/signup.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
var SignupValidator = Ember.Object.create({
|
||||||
|
validate: function (model) {
|
||||||
|
var data = model.getProperties('name', 'email', 'password'),
|
||||||
|
validationErrors = [];
|
||||||
|
|
||||||
|
if (!validator.isLength(data.name || '', 1)) {
|
||||||
|
validationErrors.push({
|
||||||
|
message: 'Please enter a name.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validator.isEmail(data.email)) {
|
||||||
|
validationErrors.push({
|
||||||
|
message: 'Invalid Email.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validator.isLength(data.password || '', 1)) {
|
||||||
|
validationErrors.push({
|
||||||
|
message: 'Please enter a password.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationErrors;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default SignupValidator;
|
Loading…
Add table
Reference in a new issue