Fixed non-admin redirects on integration routes

no issue
- after un-nesting the built-in integration routes they no longer had the automatic redirect for non-admins
- added our non-admin redirect behaviour to all of the integration routes
- added our non-admin redirect behaviour to the Zapier route which didn't even have an authenticated redirect previously
- added acceptance test for Zapier route so verify the new behaviour
- wrapped the Zapier widget `<script>` tag in an "is testing" conditional so that the external script doesn't get loaded during tests
This commit is contained in:
Kevin Ansfield 2018-10-04 12:16:41 +01:00
parent a23bbf2368
commit 656a20272a
7 changed files with 132 additions and 23 deletions

View File

@ -1,5 +1,14 @@
/* eslint-disable ghost/ember/alias-model-in-controller */ /* eslint-disable ghost/ember/alias-model-in-controller */
import Controller from '@ember/controller'; import Controller from '@ember/controller';
import config from 'ghost-admin/config/environment';
export default Controller.extend({ export default Controller.extend({
isTesting: undefined,
init() {
this._super(...arguments);
if (this.isTesting === undefined) {
this.isTesting = config.environment === 'test';
}
}
}); });

View File

@ -1,15 +1,20 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated'; import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import CurrentUserSettings from 'ghost-admin/mixins/current-user-settings';
import styleBody from 'ghost-admin/mixins/style-body'; import styleBody from 'ghost-admin/mixins/style-body';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
export default AuthenticatedRoute.extend(styleBody, { export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
settings: service(), settings: service(),
titleToken: 'AMP', titleToken: 'AMP',
classNames: ['settings-view-integrations-amp'], classNames: ['settings-view-integrations-amp'],
beforeModel() { beforeModel() {
return this.settings.reload(); this._super(...arguments);
return this.get('session.user')
.then(this.transitionAuthor())
.then(this.transitionEditor())
.then(this.settings.reload());
}, },
actions: { actions: {
@ -19,8 +24,7 @@ export default AuthenticatedRoute.extend(styleBody, {
willTransition(transition) { willTransition(transition) {
let controller = this.get('controller'); let controller = this.get('controller');
let settings = controller.get('settings'); let modelIsDirty = this.settings.get('hasDirtyAttributes');
let modelIsDirty = settings.get('hasDirtyAttributes');
if (modelIsDirty) { if (modelIsDirty) {
transition.abort(); transition.abort();

View File

@ -1,15 +1,20 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated'; import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import CurrentUserSettings from '../../../mixins/current-user-settings';
import styleBody from 'ghost-admin/mixins/style-body'; import styleBody from 'ghost-admin/mixins/style-body';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
export default AuthenticatedRoute.extend(styleBody, { export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
settings: service(), settings: service(),
titleToken: 'Slack', titleToken: 'Slack',
classNames: ['settings-view-integrations-slack'], classNames: ['settings-view-integrations-slack'],
beforeModel() { beforeModel() {
return this.settings.reload(); this._super(...arguments);
return this.get('session.user')
.then(this.transitionAuthor())
.then(this.transitionEditor())
.then(this.settings.reload());
}, },
actions: { actions: {

View File

@ -1,9 +1,10 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated'; import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import CurrentUserSettings from '../../../mixins/current-user-settings';
import UnsplashObject from 'ghost-admin/models/unsplash-integration'; import UnsplashObject from 'ghost-admin/models/unsplash-integration';
import styleBody from 'ghost-admin/mixins/style-body'; import styleBody from 'ghost-admin/mixins/style-body';
import {inject as service} from '@ember/service'; import {inject as service} from '@ember/service';
export default AuthenticatedRoute.extend(styleBody, { export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
config: service(), config: service(),
settings: service(), settings: service(),
@ -13,23 +14,28 @@ export default AuthenticatedRoute.extend(styleBody, {
// reload settings to ensure we have latest values and pre-configure // reload settings to ensure we have latest values and pre-configure
// Unsplash to be active if the server doesn't have any unsplash setting // Unsplash to be active if the server doesn't have any unsplash setting
beforeModel() { beforeModel() {
this._super(...arguments);
let {settings} = this; let {settings} = this;
return settings.reload().then(() => { return this.get('session.user')
if (settings.get('unsplash')) { .then(this.transitionAuthor())
return; .then(this.transitionEditor())
} .then(this.settings.reload())
.then(() => {
if (settings.get('unsplash')) {
return;
}
// server doesn't have any unsplash settings by default but it can provide // server doesn't have any unsplash settings by default but it can provide
// overrides via config: // overrides via config:
// - isActive: use as default but allow settings override // - isActive: use as default but allow settings override
// - applicationId: total override, no field is shown if present // - applicationId: total override, no field is shown if present
let unsplash = UnsplashObject.create({ let unsplash = UnsplashObject.create({
isActive: true isActive: true
});
settings.set('unsplash', unsplash);
}); });
settings.set('unsplash', unsplash);
});
}, },
actions: { actions: {

View File

@ -1,4 +1,11 @@
import Route from '@ember/routing/route'; import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
import CurrentUserSettings from '../../../mixins/current-user-settings';
export default Route.extend({ export default AuthenticatedRoute.extend(CurrentUserSettings, {
beforeModel() {
this._super(...arguments);
return this.get('session.user')
.then(this.transitionAuthor())
.then(this.transitionEditor());
}
}); });

View File

@ -26,7 +26,10 @@
<div class="gh-setting-desc">Explore pre-built templates for common automation tasks</div> <div class="gh-setting-desc">Explore pre-built templates for common automation tasks</div>
<div class="gh-setting-content-extended"> <div class="gh-setting-content-extended">
<div id="zapier-templates"> <div id="zapier-templates">
<script src="https://zapier.com/apps/embed/widget.js?services=ghost&container=true&limit=10&html_id=zapier-templates"></script> {{!-- we don't want the script loading during tests because it errors --}}
{{#unless isTesting}}
<script src="https://zapier.com/apps/embed/widget.js?services=ghost&container=true&limit=10&html_id=zapier-templates"></script>
{{/unless}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,75 @@
import destroyApp from '../../helpers/destroy-app';
import startApp from '../../helpers/start-app';
import {
afterEach,
beforeEach,
describe,
it
} from 'mocha';
import {authenticateSession, invalidateSession} from 'ghost-admin/tests/helpers/ember-simple-auth';
import {expect} from 'chai';
describe('Acceptance: Settings - Integrations - Zapier', function () {
let application;
beforeEach(function () {
application = startApp();
});
afterEach(function () {
destroyApp(application);
});
it('redirects to signin when not authenticated', async function () {
invalidateSession(application);
await visit('/settings/integrations/zapier');
expect(currentURL(), 'currentURL').to.equal('/signin');
});
it('redirects to team page when authenticated as contributor', async function () {
let role = server.create('role', {name: 'Contributor'});
server.create('user', {roles: [role], slug: 'test-user'});
authenticateSession(application);
await visit('/settings/integrations/zapier');
expect(currentURL(), 'currentURL').to.equal('/team/test-user');
});
it('redirects to team page when authenticated as author', async function () {
let role = server.create('role', {name: 'Author'});
server.create('user', {roles: [role], slug: 'test-user'});
authenticateSession(application);
await visit('/settings/integrations/zapier');
expect(currentURL(), 'currentURL').to.equal('/team/test-user');
});
it('redirects to team page when authenticated as editor', async function () {
let role = server.create('role', {name: 'Editor'});
server.create('user', {roles: [role], slug: 'test-user'});
authenticateSession(application);
await visit('/settings/integrations/zapier');
expect(currentURL(), 'currentURL').to.equal('/team');
});
describe('when logged in', function () {
beforeEach(function () {
let role = server.create('role', {name: 'Administrator'});
server.create('user', {roles: [role]});
return authenticateSession(application);
});
it('it loads', async function () {
await visit('/settings/integrations/zapier');
// has correct url
expect(currentURL(), 'currentURL').to.equal('/settings/integrations/zapier');
});
});
});