diff --git a/ghost/admin/controllers/debug.js b/ghost/admin/controllers/debug.js index 5b4117933d..79119b2cb6 100644 --- a/ghost/admin/controllers/debug.js +++ b/ghost/admin/controllers/debug.js @@ -2,7 +2,7 @@ var DebugController = Ember.Controller.extend(Ember.Evented, { uploadButtonText: 'Import', exportPath: function () { - return this.get('ghostPaths').apiUrl('db') + + return this.get('ghostPaths.url').api('db') + '?access_token=' + this.get('session.access_token'); }.property(), @@ -15,7 +15,7 @@ var DebugController = Ember.Controller.extend(Ember.Evented, { formData.append('importfile', file); - ic.ajax.request(this.get('ghostPaths').apiUrl('db'), { + ic.ajax.request(this.get('ghostPaths.url').api('db'), { type: 'POST', data: formData, dataType: 'json', @@ -35,7 +35,7 @@ var DebugController = Ember.Controller.extend(Ember.Evented, { exportData: function () { var self = this; - ic.ajax.request(this.get('ghostPaths').apiUrl('db'), { + ic.ajax.request(this.get('ghostPaths.url').api('db'), { type: 'GET' }).then(function () { self.notifications.showSuccess('Data exported successfully.'); @@ -47,7 +47,7 @@ var DebugController = Ember.Controller.extend(Ember.Evented, { sendTestEmail: function () { var self = this; - ic.ajax.request(this.get('ghostPaths').apiUrl('mail', 'test'), { + ic.ajax.request(this.get('ghostPaths.url').api('mail', 'test'), { type: 'POST' }).then(function () { self.notifications.showSuccess('Check your email for the test message:'); diff --git a/ghost/admin/controllers/forgotten.js b/ghost/admin/controllers/forgotten.js index b390d51b28..df5e1ff86d 100644 --- a/ghost/admin/controllers/forgotten.js +++ b/ghost/admin/controllers/forgotten.js @@ -17,7 +17,7 @@ var ForgottenController = Ember.Controller.extend(ValidationEngine, { this.toggleProperty('submitting'); this.validate({ format: false }).then(function () { ajax({ - url: self.get('ghostPaths').apiUrl('authentication', 'passwordreset'), + url: self.get('ghostPaths.url').api('authentication', 'passwordreset'), type: 'POST', data: { passwordreset: [{ diff --git a/ghost/admin/controllers/modals/delete-all.js b/ghost/admin/controllers/modals/delete-all.js index 3f7089c196..0de46c387e 100644 --- a/ghost/admin/controllers/modals/delete-all.js +++ b/ghost/admin/controllers/modals/delete-all.js @@ -3,7 +3,7 @@ var DeleteAllController = Ember.Controller.extend({ confirmAccept: function () { var self = this; - ic.ajax.request(this.get('ghostPaths').apiUrl('db'), { + ic.ajax.request(this.get('ghostPaths.url').api('db'), { type: 'DELETE' }).then(function () { self.notifications.showSuccess('All content deleted from database.'); diff --git a/ghost/admin/controllers/reset.js b/ghost/admin/controllers/reset.js index f97e4f4e16..f6c5422be3 100644 --- a/ghost/admin/controllers/reset.js +++ b/ghost/admin/controllers/reset.js @@ -21,7 +21,7 @@ var ResetController = Ember.Controller.extend(ValidationEngine, { this.toggleProperty('submitting'); this.validate({format: false}).then(function () { ajax({ - url: self.get('ghostPaths').apiUrl('authentication', 'passwordreset'), + url: self.get('ghostPaths.url').api('authentication', 'passwordreset'), type: 'PUT', data: { passwordreset: [{ diff --git a/ghost/admin/controllers/settings/users/user.js b/ghost/admin/controllers/settings/users/user.js index 7a572aa8b1..47b824afda 100644 --- a/ghost/admin/controllers/settings/users/user.js +++ b/ghost/admin/controllers/settings/users/user.js @@ -1,14 +1,18 @@ -/*global alert */ var SettingsUserController = Ember.ObjectController.extend({ user: Ember.computed.alias('model'), email: Ember.computed.readOnly('user.email'), - coverDefault: '/shared/img/user-cover.png', + coverDefault: function () { + return this.get('ghostPaths.url').asset('/shared/img/user-cover.png'); + }.property('ghostPaths'), + + userDefault: function () { + return this.get('ghostPaths.url').asset('/shared/img/user-image.png'); + }.property('ghostPaths'), cover: function () { - // @TODO: add {{asset}} subdir path var cover = this.get('user.cover'); if (typeof cover !== 'string') { cover = this.get('coverDefault'); @@ -21,13 +25,11 @@ var SettingsUserController = Ember.ObjectController.extend({ }.property('user.name'), image: function () { - // @TODO: add {{asset}} subdir path - return 'background-image: url(' + this.getWithDefault('user.image', '/shared/img/user-image.png') + ')'; - }.property('user.image'), + return 'background-image: url(' + this.get('imageUrl') + ')'; + }.property('imageUrl'), imageUrl: function () { - // @TODO: add {{asset}} subdir path - return this.getWithDefault('user.image', '/shared/img/user-image.png'); + return this.get('user.image') || this.get('userDefault'); }.property('user.image'), last_login: function () { @@ -70,38 +72,45 @@ var SettingsUserController = Ember.ObjectController.extend({ self.notifications.closePassive(); - alert('@TODO: Saving user...'); + user.validate({format: false}).then(function () { + user.save().then(function (model) { + self.notifications.closePassive(); + self.notifications.showSuccess('Settings successfully saved.'); - if (user.validate().get('isValid')) { - user.save().then(function (response) { - alert('Done saving' + JSON.stringify(response)); - }, function () { - alert('Error saving.'); + return model; + }).catch(function (errors) { + self.notifications.closePassive(); + self.notifications.showErrors(errors); }); - } else { - alert('Errors found! ' + JSON.stringify(user.get('errors'))); - } + }, function (errors) { + self.notifications.showErrors(errors); + }); }, password: function () { - alert('@TODO: Changing password...'); var user = this.get('user'), - passwordProperties = this.getProperties('password', 'newPassword', 'ne2Password'); + self = this; + + if (user.get('isPasswordValid')) { + user.saveNewPassword().then(function (model) { - if (user.validatePassword(passwordProperties).get('passwordIsValid')) { - user.saveNewPassword(passwordProperties).then(function () { - alert('Success!'); // Clear properties from view - this.setProperties({ + user.setProperties({ 'password': '', - 'newpassword': '', - 'ne2password': '' + 'newPassword': '', + 'ne2Password': '' }); - }.bind(this), function (errors) { - alert('Errors ' + JSON.stringify(errors)); + + self.notifications.closePassive(); + self.notifications.showSuccess('Password updated.'); + + return model; + }).catch(function (errors) { + self.notifications.closePassive(); + self.notifications.showAPIError(errors); }); } else { - alert('Errors found! ' + JSON.stringify(user.get('passwordErrors'))); + self.notifications.showErrors(user.get('passwordValidationErrors')); } } } diff --git a/ghost/admin/controllers/setup.js b/ghost/admin/controllers/setup.js index 523dc75a8c..4e49f20ed0 100644 --- a/ghost/admin/controllers/setup.js +++ b/ghost/admin/controllers/setup.js @@ -21,7 +21,7 @@ var SetupController = Ember.ObjectController.extend(ValidationEngine, { this.toggleProperty('submitting'); this.validate({ format: false }).then(function () { ajax({ - url: self.get('ghostPaths').apiUrl('authentication', 'setup'), + url: self.get('ghostPaths.url').api('authentication', 'setup'), type: 'POST', data: { setup: [{ diff --git a/ghost/admin/controllers/signup.js b/ghost/admin/controllers/signup.js index f8b983fcb3..e87ecc71eb 100644 --- a/ghost/admin/controllers/signup.js +++ b/ghost/admin/controllers/signup.js @@ -21,7 +21,7 @@ var SignupController = Ember.ObjectController.extend(ValidationEngine, { this.toggleProperty('submitting'); this.validate({ format: false }).then(function () { ajax({ - url: self.get('ghostPaths').apiUrl('authentication', 'invitation'), + url: self.get('ghostPaths.url').api('authentication', 'invitation'), type: 'POST', dataType: 'json', data: { diff --git a/ghost/admin/models/slug-generator.js b/ghost/admin/models/slug-generator.js index ba7806d407..1059a3691a 100644 --- a/ghost/admin/models/slug-generator.js +++ b/ghost/admin/models/slug-generator.js @@ -12,7 +12,7 @@ var SlugGenerator = Ember.Object.extend({ return Ember.RSVP.resolve(''); } - url = this.get('ghostPaths').apiUrl('slugs', 'post', encodeURIComponent(textToSlugify)); + url = this.get('ghostPaths.url').api('slugs', 'post', encodeURIComponent(textToSlugify)); return ic.ajax.request(url, { type: 'GET' diff --git a/ghost/admin/models/user.js b/ghost/admin/models/user.js index 6b4ee8967a..55a5814e9a 100644 --- a/ghost/admin/models/user.js +++ b/ghost/admin/models/user.js @@ -6,7 +6,6 @@ var User = DS.Model.extend(NProgressSaveMixin, ValidationEngine, { uuid: DS.attr('string'), name: DS.attr('string'), slug: DS.attr('string'), - password: DS.attr('string'), email: DS.attr('string'), image: DS.attr('string'), cover: DS.attr('string'), @@ -24,11 +23,17 @@ var User = DS.Model.extend(NProgressSaveMixin, ValidationEngine, { updated_at: DS.attr('moment-date'), updated_by: DS.attr('number'), - saveNewPassword: function (password) { - var url = this.get('ghostPaths').adminUrl('changepw'); + saveNewPassword: function () { + var url = this.get('ghostPaths.url').api('users', 'password'); return ic.ajax.request(url, { - type: 'POST', - data: password + type: 'PUT', + data: { + password: [{ + 'oldPassword': this.get('password'), + 'newPassword': this.get('newPassword'), + 'ne2Password': this.get('ne2Password') + }] + } }); }, @@ -37,26 +42,28 @@ var User = DS.Model.extend(NProgressSaveMixin, ValidationEngine, { userData.email = this.get('email'); - return ic.ajax.request(this.get('ghostPaths').apiUrl('users'), { + return ic.ajax.request(this.get('ghostPaths.url').api('users'), { type: 'POST', data: JSON.stringify({users: [userData]}), contentType: 'application/json' }); }, - passwordValidationErrors: function (password) { + passwordValidationErrors: function () { var validationErrors = []; - if (!validator.equals(password.newPassword, password.ne2Password)) { - validationErrors.push('Your new passwords do not match'); + if (!validator.equals(this.get('newPassword'), this.get('ne2Password'))) { + validationErrors.push({message: 'Your new passwords do not match'}); } - if (!validator.isLength(password.newPassword, 8)) { - validationErrors.push('Your password is not long enough. It must be at least 8 characters long.'); + if (!validator.isLength(this.get('newPassword'), 8)) { + validationErrors.push({message: 'Your password is not long enough. It must be at least 8 characters long.'}); } return validationErrors; - } + }.property('password', 'newPassword', 'ne2Password'), + + isPasswordValid: Ember.computed.empty('passwordValidationErrors.[]') }); diff --git a/ghost/admin/templates/settings/users/user.hbs b/ghost/admin/templates/settings/users/user.hbs index bb8b67b5b8..890f71c8ed 100644 --- a/ghost/admin/templates/settings/users/user.hbs +++ b/ghost/admin/templates/settings/users/user.hbs @@ -3,14 +3,15 @@
- - + + +
{{#link-to "settings.users" class="button has-icon users-back" tagName="button"}}Users{{/link-to}}
- + {{!-- {{#gh-popover-button popoverName="user-actions-menu" tagName="a" classNames="button only-has-icon user-actions-cog" title="User Actions"}} @@ -108,17 +109,17 @@
- {{input value=password type="password" id="user-password-old"}} + {{input value=user.password type="password" id="user-password-old"}}
- {{input value=newPassword type="password" id="user-password-new"}} + {{input value=user.newPassword type="password" id="user-password-new"}}
- {{input value=ne2Password type="password" id="user-new-password-verification"}} + {{input value=user.ne2Password type="password" id="user-new-password-verification"}}
diff --git a/ghost/admin/utils/ghost-paths.js b/ghost/admin/utils/ghost-paths.js index 64a032ae69..0271dfb0a0 100644 --- a/ghost/admin/utils/ghost-paths.js +++ b/ghost/admin/utils/ghost-paths.js @@ -9,25 +9,37 @@ var makeRoute = function (root, args) { return route; }; + function ghostPaths() { var path = window.location.pathname, - subdir = path.substr(0, path.search('/ghost/')); + subdir = path.substr(0, path.search('/ghost/')), + adminRoot = subdir + '/ghost', + apiRoot = subdir + '/ghost/api/v0.1'; + + function assetUrl(src) { + return subdir + src; + } return { subdir: subdir, blogRoot: subdir + '/', - adminRoot: subdir + '/ghost', - apiRoot: subdir + '/ghost/api/v0.1', - userImage: subdir + '/assets/img/user-image.png', - errorImageSrc: subdir + '/ghost/img/404-ghost@2x.png', - errorImageSrcSet: subdir + '/ghost/img/404-ghost.png 1x, ' + subdir + '/ghost/img/404-ghost@2x.png 2x', + adminRoot: adminRoot, + apiRoot: apiRoot, + userImage: assetUrl('/assets/img/user-image.png'), + errorImageSrc: assetUrl('/ghost/img/404-ghost@2x.png'), + errorImageSrcSet: assetUrl('/ghost/img/404-ghost.png') + ' 1x, ' + + assetUrl('/ghost/img/404-ghost@2x.png') + ' 2x', - adminUrl: function () { - return makeRoute(this.adminRoot, arguments); - }, + url: { + admin: function () { + return makeRoute(adminRoot, arguments); + }, - apiUrl: function () { - return makeRoute(this.apiRoot, arguments); + api: function () { + return makeRoute(apiRoot, arguments); + }, + + asset: assetUrl } }; }