1
0
Fork 0
mirror of https://github.com/TryGhost/Ghost-Admin.git synced 2023-12-14 02:33:04 +01:00

Improve signin

Ref #2413

- Remove fixture and use actual API
- Store and send down actual logged in user data
- Refactor isLoggedIn to use computed property on application
- After signin, update user data in dependency container
- Add CSRF to all routes and controllers via initializer
- Update authenticated route to check for user.isLoggedIn
- Add notifications for signin error
- Add notifications.showAPIError helper
- Add plumbing for refreshless signup to doSignUp in admin controller
This commit is contained in:
Jacob Gable 2014-05-14 18:36:13 -05:00
parent d55b0ceae7
commit 4f0aeca359
12 changed files with 80 additions and 37 deletions

5
app.js
View file

@ -1,6 +1,7 @@
import Resolver from 'ember/resolver';
import initFixtures from 'ghost/fixtures/init';
import {currentUser, injectCurrentUser} from 'ghost/initializers/current-user';
import injectCurrentUser from 'ghost/initializers/current-user';
import injectCsrf from 'ghost/initializers/csrf';
import {registerNotifications, injectNotifications} from 'ghost/initializers/notifications';
import 'ghost/utils/link-view';
import 'ghost/utils/text-field';
@ -20,8 +21,8 @@ var App = Ember.Application.extend({
initFixtures();
App.initializer(currentUser);
App.initializer(injectCurrentUser);
App.initializer(injectCsrf);
App.initializer(registerNotifications);
App.initializer(injectNotifications);

View file

@ -1,5 +1,6 @@
var ApplicationController = Ember.Controller.extend({
isLoggedOut: Ember.computed.match('currentPath', /(signin|signup|forgotten|reset)/),
isSignedIn: Ember.computed.bool('user.isSignedIn'),
actions: {
toggleMenu: function () {
this.toggleProperty('showMenu');

View file

@ -43,7 +43,6 @@ var defineFixtures = function (status) {
ic.ajax.defineFixture('/ghost/api/v0.1/posts/4', post(4, status));
ic.ajax.defineFixture('/ghost/api/v0.1/posts/slug/test%20title/', response('generated-slug', status));
ic.ajax.defineFixture('/ghost/api/v0.1/signin', user(status));
ic.ajax.defineFixture('/ghost/api/v0.1/users/me/', user(status));
ic.ajax.defineFixture('/ghost/changepw/', response({
msg: 'Password changed successfully'

10
initializers/csrf.js Normal file
View file

@ -0,0 +1,10 @@
export default {
name: 'csrf',
initialize: function (container) {
container.register('csrf:current', $('meta[name="csrf-param"]').attr('content'), { instantiate: false });
container.injection('route', 'csrf', 'csrf:current');
container.injection('controller', 'csrf', 'csrf:current');
}
};

View file

@ -1,26 +1,14 @@
import User from 'ghost/models/user';
import userFixtures from 'ghost/fixtures/users';
var currentUser = {
export default {
name: 'currentUser',
initialize: function (container) {
container.register('user:current', User);
initialize: function (container, application) {
var user = User.create(application.get('user') || {});
container.register('user:current', user, { instantiate: false });
container.injection('route', 'user', 'user:current');
container.injection('controller', 'user', 'user:current');
}
};
var injectCurrentUser = {
name: 'injectCurrentUser',
initialize: function (container) {
if (container.lookup('user:current')) {
// @TODO: remove userFixture
container.lookup('user:current').setProperties(userFixtures.findBy('id', 1));
container.injection('route', 'user', 'user:current');
container.injection('controller', 'user', 'user:current');
}
}
};
export {currentUser, injectCurrentUser};
};

View file

@ -1,6 +1,12 @@
import BaseModel from 'ghost/models/base';
var UserModel = BaseModel.extend({
id: null,
name: null,
image: null,
isSignedIn: Ember.computed.bool('id'),
url: BaseModel.apiRoot + '/users/me/',
forgottenUrl: BaseModel.apiRoot + '/forgotten/',
resetUrl: BaseModel.apiRoot + '/reset/',

View file

@ -1,5 +1,17 @@
var ApplicationRoute = Ember.Route.extend({
actions: {
signedIn: function (user) {
this.container.lookup('user:current').setProperties(user);
},
signedOut: function () {
this.container.lookup('user:current').setProperties({
id: null,
name: null,
image: null
});
},
openModal: function (modalName, model) {
modalName = 'modals/' + modalName;
// We don't always require a modal to have a controller

View file

@ -1,4 +1,12 @@
var AuthenticatedRoute = Ember.Route.extend({
beforeModel: function () {
if (!this.get('user.isSignedIn')) {
this.notifications.showError('Please sign in');
this.transitionTo('signin');
}
},
actions: {
error: function (error) {
if (error.jqXHR.status === 401) {

View file

@ -14,12 +14,23 @@ var SigninRoute = Ember.Route.extend(styleBody, {
if (!isEmpty(data.email) && !isEmpty(data.password)) {
ajax('/ghost/api/v0.1/signin', data).then(
ajax({
url: '/ghost/signin/',
type: 'POST',
headers: {
"X-CSRF-Token": this.get('csrf')
},
data: data
}).then(
function (response) {
self.set('user', response);
self.send('signedIn', response.userData);
self.notifications.clear();
self.transitionTo('posts');
}, function () {
window.alert('Error'); // Todo Show notification
}, function (resp) {
// This path is ridiculous, should be a helper in notifications; e.g. notifications.showAPIError
self.notifications.showAPIError(resp, 'There was a problem logging in, please try again.');
}
);
} else {

View file

@ -1,6 +1,6 @@
<header id="global-header" class="navbar">
<a class="ghost-logo" href="/" data-off-canvas="left" title="/">
<span class="hidden">Ghost </span>
<span class="hidden">Ghost</span>
</a>
<nav id="global-nav" role="navigation">
<ul id="main-menu" >
@ -9,11 +9,9 @@
{{activating-list-item route="settings" title="Settings" classNames="settings"}}
<li id="usermenu" class="usermenu subnav">
<a href="" {{action 'toggleMenu'}} class="dropdown">
{{!-- @TODO: show avatar of logged in user --}}
<img class="avatar" src="/shared/img/user-image.png" alt="Avatar" />
{{!-- @TODO: show logged in user name or email --}}
<span class="name">Fake Ghost</span>
<a href="javascript:void(0);" {{action 'toggleMenu'}} class="dropdown">
<img class="avatar" {{bind-attr src="user.image"}} alt="Avatar" />
<span class="name">{{user.name}}</span>
</a>
{{!-- @TODO: add functionality to allow for dropdown to work --}}
{{#ghost-popover open=showMenu}}

View file

@ -1,6 +1,6 @@
{{#unless isLoggedOut}}
{{#if isSignedIn}}
{{partial "navbar"}}
{{/unless}}
{{/if}}
<main role="main" id="main">
{{ghost-notifications}}

View file

@ -20,6 +20,15 @@ var Notifications = Ember.ArrayProxy.extend({
this.showError(errors[i].message || errors[i]);
}
},
showAPIError: function (resp, defaultErrorText) {
defaultErrorText = defaultErrorText || 'There was a problem on the server, please try again.';
if (resp && resp.jqXHR && resp.jqXHR.responseJSON && resp.jqXHR.responseJSON.error) {
this.showError(resp.jqXHR.responseJSON.error);
} else {
this.showError(defaultErrorText);
}
},
showInfo: function (message) {
this.pushObject({
type: 'info',