mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-25 09:03:12 +03:00
✨ Contributor Role (#948)
refs https://github.com/TryGhost/Ghost/issues/9314 * added save button for contributor * hide tag filter & redirect to posts.index if post is published * update editor controller test to need session service
This commit is contained in:
parent
f0501e8997
commit
13ceee3e9f
@ -81,6 +81,7 @@ export default Controller.extend({
|
||||
notifications: service(),
|
||||
router: service(),
|
||||
slugGenerator: service(),
|
||||
session: service(),
|
||||
ui: service(),
|
||||
|
||||
/* public properties -----------------------------------------------------*/
|
||||
|
@ -58,7 +58,7 @@ export default Controller.extend({
|
||||
deleteUserActionIsVisible: computed('currentUser', 'canAssignRoles', 'user', function () {
|
||||
if ((this.get('canAssignRoles') && this.get('isNotOwnProfile') && !this.get('user.isOwner'))
|
||||
|| (this.get('currentUser.isEditor') && (this.get('isNotOwnProfile')
|
||||
|| this.get('user.isAuthor')))) {
|
||||
|| this.get('user.isAuthorOrContributor')))) {
|
||||
return true;
|
||||
}
|
||||
}),
|
||||
|
@ -3,7 +3,7 @@ import Mixin from '@ember/object/mixin';
|
||||
export default Mixin.create({
|
||||
transitionAuthor() {
|
||||
return (user) => {
|
||||
if (user.get('isAuthor')) {
|
||||
if (user.get('isAuthorOrContributor')) {
|
||||
return this.transitionTo('team.user', user);
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ import Model from 'ember-data/model';
|
||||
import ValidationEngine from 'ghost-admin/mixins/validation-engine';
|
||||
import attr from 'ember-data/attr';
|
||||
import {computed} from '@ember/object';
|
||||
import {equal} from '@ember/object/computed';
|
||||
import {equal, or} from '@ember/object/computed';
|
||||
import {hasMany} from 'ember-data/relationships';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {task} from 'ember-concurrency';
|
||||
@ -46,11 +46,15 @@ export default Model.extend(ValidationEngine, {
|
||||
|
||||
// TODO: Once client-side permissions are in place,
|
||||
// remove the hard role check.
|
||||
isContributor: equal('role.name', 'Contributor'),
|
||||
isAuthor: equal('role.name', 'Author'),
|
||||
isEditor: equal('role.name', 'Editor'),
|
||||
isAdmin: equal('role.name', 'Administrator'),
|
||||
isOwner: equal('role.name', 'Owner'),
|
||||
|
||||
// This is used in enough places that it's useful to throw it here
|
||||
isAuthorOrContributor: or('isAuthor', 'isContributor'),
|
||||
|
||||
isLoggedIn: computed('id', 'session.user.id', function () {
|
||||
return this.get('id') === this.get('session.user.id');
|
||||
}),
|
||||
|
@ -119,7 +119,7 @@ export default Route.extend(ApplicationRouteMixin, ShortcutsRoute, {
|
||||
loadServerNotifications(isDelayed) {
|
||||
if (this.get('session.isAuthenticated')) {
|
||||
this.get('session.user').then((user) => {
|
||||
if (!user.get('isAuthor') && !user.get('isEditor')) {
|
||||
if (!user.get('isAuthorOrContributor') && !user.get('isEditor')) {
|
||||
this.store.findAll('notification', {reload: true}).then((serverNotifications) => {
|
||||
serverNotifications.forEach((notification) => {
|
||||
if (notification.get('top') || notification.get('custom')) {
|
||||
|
@ -20,7 +20,12 @@ export default AuthenticatedRoute.extend({
|
||||
this._super(...arguments);
|
||||
|
||||
return this.get('session.user').then((user) => {
|
||||
if (user.get('isAuthor') && !post.isAuthoredByUser(user)) {
|
||||
if (user.get('isAuthorOrContributor') && !post.isAuthoredByUser(user)) {
|
||||
return this.replaceWith('posts.index');
|
||||
}
|
||||
|
||||
// If the post is not a draft and user is contributor, redirect to index
|
||||
if (user.get('isContributor') && !post.get('isDraft')) {
|
||||
return this.replaceWith('posts.index');
|
||||
}
|
||||
});
|
||||
|
@ -45,6 +45,10 @@ export default AuthenticatedRoute.extend(InfinityRoute, {
|
||||
if (user.get('isAuthor')) {
|
||||
// authors can only view their own posts
|
||||
filterParams.author = user.get('slug');
|
||||
} else if (user.get('isContributor')) {
|
||||
// Contributors can only view their own draft posts
|
||||
filterParams.author = user.get('slug');
|
||||
queryParams.status = 'draft';
|
||||
} else if (params.author) {
|
||||
filterParams.author = params.author;
|
||||
}
|
||||
@ -78,7 +82,7 @@ export default AuthenticatedRoute.extend(InfinityRoute, {
|
||||
}
|
||||
|
||||
this.get('session.user').then((user) => {
|
||||
if (!user.get('isAuthor') && !controller._hasLoadedAuthors) {
|
||||
if (!user.get('isAuthorOrContributor') && !controller._hasLoadedAuthors) {
|
||||
this.get('store').query('user', {limit: 'all'}).then(() => {
|
||||
controller._hasLoadedAuthors = true;
|
||||
});
|
||||
|
@ -29,7 +29,7 @@ export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, Infinit
|
||||
};
|
||||
|
||||
// authors do not have permission to hit the invites or suspended users endpoint
|
||||
if (!user.get('isAuthor')) {
|
||||
if (!user.get('isAuthorOrContributor')) {
|
||||
modelPromises.invites = this.store.query('invite', {limit: 'all'})
|
||||
.then(() => this.store.filter('invite', invite => !invite.get('isNew')));
|
||||
|
||||
|
@ -17,12 +17,12 @@ export default AuthenticatedRoute.extend(styleBody, CurrentUserSettings, {
|
||||
|
||||
return this.get('session.user').then((currentUser) => {
|
||||
let isOwnProfile = user.get('id') === currentUser.get('id');
|
||||
let isAuthor = currentUser.get('isAuthor');
|
||||
let isAuthorOrContributor = currentUser.get('isAuthorOrContributor');
|
||||
let isEditor = currentUser.get('isEditor');
|
||||
|
||||
if (isAuthor && !isOwnProfile) {
|
||||
if (isAuthorOrContributor && !isOwnProfile) {
|
||||
this.transitionTo('team.user', currentUser);
|
||||
} else if (isEditor && !isOwnProfile && !user.get('isAuthor')) {
|
||||
} else if (isEditor && !isOwnProfile && !user.get('isAuthorOrContributor')) {
|
||||
this.transitionTo('team');
|
||||
}
|
||||
});
|
||||
|
@ -55,6 +55,11 @@
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.contributor-save-button {
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.post-settings {
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
|
@ -65,10 +65,12 @@
|
||||
}}
|
||||
</div>
|
||||
|
||||
{{#unless session.user.isContributor}}
|
||||
<div class="form-group">
|
||||
<label for="tag-input">Tags</label>
|
||||
{{gh-psm-tags-input post=post triggerId="tag-input"}}
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
{{#gh-form-group errors=post.errors hasValidated=post.hasValidated property="customExcerpt"}}
|
||||
<label for="custom-excerpt">Excerpt</label>
|
||||
@ -83,7 +85,7 @@
|
||||
{{gh-error-message errors=post.errors property="customExcerpt" data-test-error="custom-excerpt"}}
|
||||
{{/gh-form-group}}
|
||||
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
<div class="form-group for-select">
|
||||
<label for="author-list">Author</label>
|
||||
<span class="gh-input-icon gh-icon-user">
|
||||
|
@ -44,6 +44,7 @@
|
||||
triggerComponent=triggerComponent
|
||||
triggerId=triggerId
|
||||
verticalPosition=verticalPosition
|
||||
data-test-token-input=true
|
||||
as |option term|
|
||||
}}
|
||||
{{#if option.__isSuggestion__}}
|
||||
|
@ -15,7 +15,7 @@
|
||||
{{#if user.isLocked}}
|
||||
<span class="gh-badge author">Locked</span>
|
||||
{{/if}}
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
{{#each user.roles as |role|}}
|
||||
<span class="gh-badge {{role.lowerCaseName}}" data-test-role-name>{{role.name}}</span>
|
||||
{{/each}}
|
||||
|
@ -19,11 +19,19 @@
|
||||
{{/gh-scheduled-post-countdown}}
|
||||
<section class="view-actions">
|
||||
{{#unless post.isNew}}
|
||||
{{gh-publishmenu
|
||||
post=post
|
||||
saveTask=save
|
||||
setSaveType=(action "setSaveType")
|
||||
onOpen=(action "cancelAutosave")}}
|
||||
{{#if session.user.isContributor}}
|
||||
{{gh-task-button "Save"
|
||||
task=save
|
||||
runningText="Saving"
|
||||
class="gh-btn gh-btn-blue gh-btn-icon contributor-save-button"
|
||||
data-test-contributor-save=true}}
|
||||
{{else}}
|
||||
{{gh-publishmenu
|
||||
post=post
|
||||
saveTask=save
|
||||
setSaveType=(action "setSaveType")
|
||||
onOpen=(action "cancelAutosave")}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
<button type="button" class="post-settings" title="Settings" {{action "openSettingsMenu" target=ui}} data-test-psm-trigger>
|
||||
|
@ -25,7 +25,7 @@
|
||||
{{type.name}}
|
||||
{{/power-select}}
|
||||
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
{{#power-select
|
||||
placeholder="All authors"
|
||||
selected=selectedAuthor
|
||||
|
@ -7,6 +7,7 @@
|
||||
</header>
|
||||
<div class="gh-contentfilter">
|
||||
<div class="gh-contentfilter-left">
|
||||
{{#unless session.user.isContributor}}
|
||||
{{#power-select
|
||||
selected=selectedType
|
||||
options=availableTypes
|
||||
@ -22,8 +23,9 @@
|
||||
}}
|
||||
{{type.name}}
|
||||
{{/power-select}}
|
||||
{{/unless}}
|
||||
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
{{#power-select
|
||||
selected=selectedAuthor
|
||||
options=availableAuthors
|
||||
@ -42,6 +44,7 @@
|
||||
{{/power-select}}
|
||||
{{/unless}}
|
||||
|
||||
{{#unless session.user.isContributor}}
|
||||
{{#power-select
|
||||
selected=selectedTag
|
||||
options=availableTags
|
||||
@ -59,6 +62,7 @@
|
||||
}}
|
||||
{{tag.name}}
|
||||
{{/power-select}}
|
||||
{{/unless}}
|
||||
</div>
|
||||
|
||||
<div class="gh-contentfilter-right">
|
||||
|
@ -2,7 +2,7 @@
|
||||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>Team members</h2>
|
||||
{{!-- Do not show Invite user button to authors --}}
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
<section class="view-actions">
|
||||
<button class="gh-btn gh-btn-green" {{action "toggleInviteUserModal"}} ><span>Invite People</span></button>
|
||||
</section>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<header class="gh-canvas-header">
|
||||
<h2 class="gh-canvas-title" data-test-screen-title>Team members</h2>
|
||||
{{!-- Do not show Invite user button to authors --}}
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
<section class="view-actions">
|
||||
<button class="gh-btn gh-btn-green" {{action "toggleInviteUserModal"}} ><span>Invite People</span></button>
|
||||
</section>
|
||||
@ -18,7 +18,7 @@
|
||||
<section class="gh-team">
|
||||
|
||||
{{!-- Show invited users to everyone except authors --}}
|
||||
{{#unless session.user.isAuthor}}
|
||||
{{#unless session.user.isAuthorOrContributor}}
|
||||
{{#if invites}}
|
||||
<section class="apps-grid-container gh-invited-users" data-test-invited-users>
|
||||
<span class="apps-grid-title">Invited users</span>
|
||||
@ -75,8 +75,8 @@
|
||||
<section class="apps-grid-container gh-active-users" data-test-active-users>
|
||||
<span class="apps-grid-title">Active users</span>
|
||||
<div class="apps-grid">
|
||||
{{!-- For authors only show their own user --}}
|
||||
{{#if session.user.isAuthor}}
|
||||
{{!-- For authors/contributors only show their own user --}}
|
||||
{{#if session.user.isAuthorOrContributor}}
|
||||
{{#with session.user as |user|}}
|
||||
{{#gh-user-active user=user as |component|}}
|
||||
{{gh-user-list-item user=user component=component}}
|
||||
@ -100,7 +100,7 @@
|
||||
</section>
|
||||
|
||||
{{!-- Don't show if we have no suspended users or logged in as an author --}}
|
||||
{{#if (and suspendedUsers (not session.user.isAuthor))}}
|
||||
{{#if (and suspendedUsers (not session.user.isAuthorOrContributor))}}
|
||||
<section class="apps-grid-container gh-active-users" data-test-suspended-users>
|
||||
<span class="apps-grid-title">Suspended users</span>
|
||||
<div class="apps-grid">
|
||||
|
@ -158,4 +158,42 @@ describe('Acceptance: Content', function () {
|
||||
expect(find(`[data-test-post-id="${authorPost.id}"]`), 'author post').to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
describe('as contributor', function () {
|
||||
let contributor, contributorPost;
|
||||
|
||||
beforeEach(function () {
|
||||
let contributorRole = server.create('role', {name: 'Contributor'});
|
||||
contributor = server.create('user', {roles: [contributorRole]});
|
||||
let adminRole = server.create('role', {name: 'Administrator'});
|
||||
let admin = server.create('user', {roles: [adminRole]});
|
||||
|
||||
// Create posts
|
||||
contributorPost = server.create('post', {authorId: contributor.id, status: 'draft', title: 'Contributor Post Draft'});
|
||||
server.create('post', {authorId: contributor.id, status: 'published', title: 'Contributor Published Post'});
|
||||
server.create('post', {authorId: admin.id, status: 'scheduled', title: 'Admin Post'});
|
||||
|
||||
return authenticateSession(application);
|
||||
});
|
||||
|
||||
it('only fetches the contributor\'s draft posts', async function () {
|
||||
await visit('/');
|
||||
|
||||
// Ensure the type, tag, and author selectors don't exist
|
||||
expect(find('[data-test-type-select]'), 'type selector').to.not.exist;
|
||||
expect(find('[data-test-tag-select]'), 'tag selector').to.not.exist;
|
||||
expect(find('[data-test-author-select]'), 'author selector').to.not.exist;
|
||||
|
||||
// Trigger a sort request
|
||||
await selectChoose('[data-test-order-select]', 'Oldest');
|
||||
|
||||
// API request includes author filter
|
||||
let [lastRequest] = server.pretender.handledRequests.slice(-1);
|
||||
expect(lastRequest.queryParams.filter).to.equal(`author:${contributor.slug}`);
|
||||
|
||||
// only contributor's post is shown
|
||||
expect(find('[data-test-post-id]').length, 'post count').to.equal(1);
|
||||
expect(find(`[data-test-post-id="${contributorPost.id}"]`), 'author post').to.exist;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -28,6 +28,17 @@ describe('Acceptance: Editor', function () {
|
||||
expect(currentURL(), 'currentURL').to.equal('/signin');
|
||||
});
|
||||
|
||||
it('does not redirect to team page when authenticated as contributor', async function () {
|
||||
let role = server.create('role', {name: 'Contributor'});
|
||||
server.create('user', {roles: [role], slug: 'test-user'});
|
||||
server.create('post');
|
||||
|
||||
authenticateSession(application);
|
||||
await visit('/editor/1');
|
||||
|
||||
expect(currentURL(), 'currentURL').to.equal('/editor/1');
|
||||
});
|
||||
|
||||
it('does not redirect to team page when authenticated as author', async function () {
|
||||
let role = server.create('role', {name: 'Author'});
|
||||
server.create('user', {roles: [role], slug: 'test-user'});
|
||||
@ -61,6 +72,45 @@ describe('Acceptance: Editor', function () {
|
||||
expect(currentURL()).to.equal('/editor/1');
|
||||
});
|
||||
|
||||
describe('when logged in as contributor', function () {
|
||||
beforeEach(function () {
|
||||
let role = server.create('role', {name: 'Contributor'});
|
||||
server.create('user', {roles: [role]});
|
||||
server.loadFixtures('settings');
|
||||
|
||||
return authenticateSession(application);
|
||||
});
|
||||
|
||||
it('renders a save button instead of a publish menu & hides tags input', async function () {
|
||||
server.createList('post', 2);
|
||||
|
||||
// post id 1 is a draft, checking for draft behaviour now
|
||||
await visit('/editor/1');
|
||||
|
||||
expect(currentURL(), 'currentURL').to.equal('/editor/1');
|
||||
|
||||
// Expect publish menu to not exist
|
||||
expect(
|
||||
find('[data-test-publishmenu-trigger]'),
|
||||
'publish menu trigger'
|
||||
).to.not.exist;
|
||||
|
||||
// Open post settings menu
|
||||
await click('[data-test-psm-trigger]');
|
||||
|
||||
// Check to make sure that tags input doesn't exist
|
||||
expect(
|
||||
find('[data-test-token-input]'),
|
||||
'tags input'
|
||||
).to.not.exist;
|
||||
|
||||
// post id 2 is published, we should be redirected to index
|
||||
await visit('/editor/2');
|
||||
|
||||
expect(currentURL(), 'currentURL').to.equal('/');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when logged in', function () {
|
||||
beforeEach(function () {
|
||||
let role = server.create('role', {name: 'Administrator'});
|
||||
|
@ -28,6 +28,16 @@ describe('Acceptance: Settings - Apps - AMP', function () {
|
||||
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/apps/amp');
|
||||
|
||||
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'});
|
||||
|
@ -27,6 +27,16 @@ describe('Acceptance: Settings - Apps', function () {
|
||||
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/apps');
|
||||
|
||||
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'});
|
||||
|
@ -29,6 +29,16 @@ describe('Acceptance: Settings - Code-Injection', function () {
|
||||
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/code-injection');
|
||||
|
||||
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'});
|
||||
|
@ -26,6 +26,16 @@ describe('Acceptance: Settings - Design', function () {
|
||||
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/design');
|
||||
|
||||
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'});
|
||||
|
@ -27,6 +27,16 @@ describe('Acceptance: Settings - General', function () {
|
||||
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/general');
|
||||
|
||||
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'});
|
||||
|
@ -25,6 +25,16 @@ describe('Acceptance: Settings - Labs', function () {
|
||||
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/labs');
|
||||
|
||||
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'});
|
||||
|
@ -24,6 +24,16 @@ describe('Acceptance: Settings - Apps - Slack', function () {
|
||||
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/apps/slack');
|
||||
|
||||
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'});
|
||||
|
@ -56,6 +56,16 @@ describe('Acceptance: Settings - Tags', function () {
|
||||
expect(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/design');
|
||||
|
||||
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'});
|
||||
|
@ -23,6 +23,16 @@ describe('Acceptance: Settings - Apps - Unsplash', function () {
|
||||
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/apps/unsplash');
|
||||
|
||||
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'});
|
||||
|
@ -46,6 +46,18 @@ describe('Acceptance: Subscribers', function () {
|
||||
.to.equal(0);
|
||||
});
|
||||
|
||||
it('redirects contributors to posts', async function () {
|
||||
let role = server.create('role', {name: 'Contributor'});
|
||||
server.create('user', {roles: [role]});
|
||||
|
||||
authenticateSession(application);
|
||||
await visit('/subscribers');
|
||||
|
||||
expect(currentURL()).to.equal('/');
|
||||
expect(find('.gh-nav-main a:contains("Subscribers")').length, 'sidebar link is visible')
|
||||
.to.equal(0);
|
||||
});
|
||||
|
||||
describe('an admin', function () {
|
||||
beforeEach(function () {
|
||||
let role = server.create('role', {name: 'Administrator'});
|
||||
|
@ -27,6 +27,18 @@ describe('Acceptance: Team', function () {
|
||||
expect(currentURL()).to.equal('/signin');
|
||||
});
|
||||
|
||||
it('redirects correctly when authenticated as contributor', async function () {
|
||||
let role = server.create('role', {name: 'Contributor'});
|
||||
server.create('user', {roles: [role], slug: 'test-user'});
|
||||
|
||||
server.create('user', {slug: 'no-access'});
|
||||
|
||||
authenticateSession(application);
|
||||
await visit('/team/no-access');
|
||||
|
||||
expect(currentURL(), 'currentURL').to.equal('/team/test-user');
|
||||
});
|
||||
|
||||
it('redirects correctly when authenticated as author', async function () {
|
||||
let role = server.create('role', {name: 'Author'});
|
||||
server.create('user', {roles: [role], slug: 'test-user'});
|
||||
|
@ -15,6 +15,7 @@ describe('Unit: Controller: editor', function () {
|
||||
'service:notifications',
|
||||
// 'service:router',
|
||||
'service:slugGenerator',
|
||||
'service:session',
|
||||
'service:ui'
|
||||
]
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ describe('Unit: Helper: gh-user-can-admin', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Editor and Author roles', function () {
|
||||
describe('Editor, Author & Contributor roles', function () {
|
||||
let user = {
|
||||
get(role) {
|
||||
if (role === 'isOwner') {
|
||||
|
@ -61,6 +61,21 @@ describe('Unit: Model: user', function () {
|
||||
expect(model.get('role.name')).to.equal('Editor');
|
||||
});
|
||||
|
||||
it('isContributor property is correct', function () {
|
||||
let model = this.subject();
|
||||
|
||||
run(() => {
|
||||
let role = this.store().push({data: {id: 1, type: 'role', attributes: {name: 'Contributor'}}});
|
||||
model.set('role', role);
|
||||
});
|
||||
expect(model.get('isContributor')).to.be.ok;
|
||||
expect(model.get('isAuthorOrContributor')).to.be.ok;
|
||||
expect(model.get('isAuthor')).to.not.be.ok;
|
||||
expect(model.get('isEditor')).to.not.be.ok;
|
||||
expect(model.get('isAdmin')).to.not.be.ok;
|
||||
expect(model.get('isOwner')).to.not.be.ok;
|
||||
});
|
||||
|
||||
it('isAuthor property is correct', function () {
|
||||
let model = this.subject();
|
||||
|
||||
@ -69,6 +84,8 @@ describe('Unit: Model: user', function () {
|
||||
model.set('role', role);
|
||||
});
|
||||
expect(model.get('isAuthor')).to.be.ok;
|
||||
expect(model.get('isContributor')).to.not.be.ok;
|
||||
expect(model.get('isAuthorOrContributor')).to.be.ok;
|
||||
expect(model.get('isEditor')).to.not.be.ok;
|
||||
expect(model.get('isAdmin')).to.not.be.ok;
|
||||
expect(model.get('isOwner')).to.not.be.ok;
|
||||
@ -83,6 +100,8 @@ describe('Unit: Model: user', function () {
|
||||
});
|
||||
expect(model.get('isEditor')).to.be.ok;
|
||||
expect(model.get('isAuthor')).to.not.be.ok;
|
||||
expect(model.get('isContributor')).to.not.be.ok;
|
||||
expect(model.get('isAuthorOrContributor')).to.not.be.ok;
|
||||
expect(model.get('isAdmin')).to.not.be.ok;
|
||||
expect(model.get('isOwner')).to.not.be.ok;
|
||||
});
|
||||
@ -96,6 +115,8 @@ describe('Unit: Model: user', function () {
|
||||
});
|
||||
expect(model.get('isAdmin')).to.be.ok;
|
||||
expect(model.get('isAuthor')).to.not.be.ok;
|
||||
expect(model.get('isContributor')).to.not.be.ok;
|
||||
expect(model.get('isAuthorOrContributor')).to.not.be.ok;
|
||||
expect(model.get('isEditor')).to.not.be.ok;
|
||||
expect(model.get('isOwner')).to.not.be.ok;
|
||||
});
|
||||
@ -109,6 +130,8 @@ describe('Unit: Model: user', function () {
|
||||
});
|
||||
expect(model.get('isOwner')).to.be.ok;
|
||||
expect(model.get('isAuthor')).to.not.be.ok;
|
||||
expect(model.get('isContributor')).to.not.be.ok;
|
||||
expect(model.get('isAuthorOrContributor')).to.not.be.ok;
|
||||
expect(model.get('isAdmin')).to.not.be.ok;
|
||||
expect(model.get('isEditor')).to.not.be.ok;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user