mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-24 23:48:13 -05:00
Fixed "Authorization Failed" error screens when not logged in
no issue - `/config/` can only be requested when authenticated - updated `/config/` mock to look for an Authentication header and return a 403 if it's missing - updated `ajax` service to add an `Authentication` header when authenticated in testing env (cookies are not present when testing) - updated `config` service to add `fetchUnauthenticated()` and `fetchAuthenticated()` methods in addition to `.fetch()` - updated `application` route to only fetch authenticated config when authenticated - updated `signin` controller to correctly fetch config after sign-in
This commit is contained in:
parent
ef857d25ba
commit
738823d8f8
5 changed files with 59 additions and 18 deletions
|
@ -45,7 +45,7 @@ export default Controller.extend(ValidationEngine, {
|
|||
let promises = [];
|
||||
|
||||
promises.pushObject(this.get('settings').fetch());
|
||||
promises.pushObject(this.get('config').fetchPrivate());
|
||||
promises.pushObject(this.get('config').fetchAuthenticated());
|
||||
|
||||
// fetch settings and private config for synchronous access
|
||||
yield RSVP.all(promises);
|
||||
|
|
|
@ -43,7 +43,7 @@ export default Route.extend(ApplicationRouteMixin, ShortcutsRoute, {
|
|||
routeAfterAuthentication: 'posts',
|
||||
|
||||
beforeModel() {
|
||||
return this.get('config').fetch();
|
||||
return this.get('config').fetchUnauthenticated();
|
||||
},
|
||||
|
||||
afterModel(model, transition) {
|
||||
|
@ -53,6 +53,7 @@ export default Route.extend(ApplicationRouteMixin, ShortcutsRoute, {
|
|||
this.set('appLoadTransition', transition);
|
||||
transition.send('loadServerNotifications');
|
||||
|
||||
let configPromise = this.get('config').fetchAuthenticated();
|
||||
let featurePromise = this.get('feature').fetch();
|
||||
let settingsPromise = this.get('settings').fetch();
|
||||
let tourPromise = this.get('tour').fetchViewed();
|
||||
|
@ -60,6 +61,7 @@ export default Route.extend(ApplicationRouteMixin, ShortcutsRoute, {
|
|||
// return the feature/settings load promises so that we block until
|
||||
// they are loaded to enable synchronous access everywhere
|
||||
return RSVP.all([
|
||||
configPromise,
|
||||
featurePromise,
|
||||
settingsPromise,
|
||||
tourPromise
|
||||
|
|
|
@ -118,6 +118,8 @@ export function isThemeValidationError(errorOrStatus, payload) {
|
|||
let ajaxService = AjaxService.extend({
|
||||
session: service(),
|
||||
|
||||
isTesting: undefined,
|
||||
|
||||
// flag to tell our ESA authenticator not to try an invalidate DELETE request
|
||||
// because it's been triggered by this service's 401 handling which means the
|
||||
// DELETE would fail and get stuck in an infinite loop
|
||||
|
@ -130,9 +132,20 @@ let ajaxService = AjaxService.extend({
|
|||
headers['X-Ghost-Version'] = config.APP.version;
|
||||
headers['App-Pragma'] = 'no-cache';
|
||||
|
||||
if (this.session.isAuthenticated && this.isTesting) {
|
||||
headers.Authorization = 'Test';
|
||||
}
|
||||
|
||||
return headers;
|
||||
}).volatile(),
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
if (this.isTesting === undefined) {
|
||||
this.isTesting = config.environment === 'test';
|
||||
}
|
||||
},
|
||||
|
||||
// ember-ajax recognises `application/vnd.api+json` as a JSON-API request
|
||||
// and formats appropriately, we want to handle `application/json` the same
|
||||
_makeRequest(hash) {
|
||||
|
|
|
@ -9,6 +9,7 @@ const {_ProxyMixin} = Ember;
|
|||
export default Service.extend(_ProxyMixin, {
|
||||
ajax: service(),
|
||||
ghostPaths: service(),
|
||||
session: service(),
|
||||
|
||||
content: null,
|
||||
|
||||
|
@ -18,23 +19,37 @@ export default Service.extend(_ProxyMixin, {
|
|||
},
|
||||
|
||||
fetch() {
|
||||
let promises = [];
|
||||
|
||||
promises.push(this.fetchUnauthenticated());
|
||||
|
||||
if (this.session.isAuthenticated) {
|
||||
promises.push(this.fetchAuthenticated());
|
||||
}
|
||||
|
||||
return RSVP.all(promises);
|
||||
},
|
||||
|
||||
fetchUnauthenticated() {
|
||||
let siteUrl = this.ghostPaths.url.api('site');
|
||||
return this.ajax.request(siteUrl).then(({site}) => {
|
||||
// normalize url to non-trailing-slash
|
||||
site.blogUrl = site.url.replace(/\/$/, '');
|
||||
site.blogTitle = site.title;
|
||||
delete site.url;
|
||||
delete site.title;
|
||||
|
||||
Object.assign(this.content, site);
|
||||
}).then(() => {
|
||||
this.notifyPropertyChange('content');
|
||||
});
|
||||
},
|
||||
|
||||
fetchAuthenticated() {
|
||||
let configUrl = this.ghostPaths.url.api('config');
|
||||
|
||||
return RSVP.all([
|
||||
this.ajax.request(siteUrl).then(({site}) => {
|
||||
// normalize url to non-trailing-slash
|
||||
site.blogUrl = site.url.replace(/\/$/, '');
|
||||
site.blogTitle = site.title;
|
||||
delete site.url;
|
||||
delete site.title;
|
||||
|
||||
Object.assign(this.content, site);
|
||||
}),
|
||||
this.ajax.request(configUrl).then(({config}) => {
|
||||
Object.assign(this.content, config);
|
||||
})
|
||||
]).then(() => {
|
||||
return this.ajax.request(configUrl).then(({config}) => {
|
||||
Object.assign(this.content, config);
|
||||
}).then(() => {
|
||||
this.notifyPropertyChange('content');
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,7 +1,18 @@
|
|||
import {Response} from 'ember-cli-mirage';
|
||||
import {isEmpty} from '@ember/utils';
|
||||
|
||||
export default function mockConfig(server) {
|
||||
server.get('/config/', function ({db}) {
|
||||
server.get('/config/', function ({db}, request) {
|
||||
if (!request.requestHeaders.Authorization) {
|
||||
return new Response(403, {}, {
|
||||
errors: [{
|
||||
type: 'NoPermissionError',
|
||||
message: 'Authorization failed',
|
||||
context: 'Unable to determine the authenticated user or integration. Check that cookies are being passed through if using session authentication.'
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
if (isEmpty(db.configs)) {
|
||||
server.loadFixtures('configs');
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue