Commit 0055350dc62b0a178fc896d6ccdedcf6cd3923ea

Authored by Victor Costa
1 parent 0456e67c

Hide action buttons related to articles when user doesn't have permission to execute it

src/app/article/article-default-view-component.spec.ts
1 import {Input, provide, Component} from 'ng-forward'; 1 import {Input, provide, Component} from 'ng-forward';
2 import {ArticleViewComponent, ArticleDefaultViewComponent} from './article-default-view.component'; 2 import {ArticleViewComponent, ArticleDefaultViewComponent} from './article-default-view.component';
3 import {ComponentTestHelper, createClass} from './../../spec/component-test-helper'; 3 import {ComponentTestHelper, createClass} from './../../spec/component-test-helper';
  4 +import {PermissionDirective} from '../shared/components/permission/permission.directive';
4 5
5 import * as helpers from "../../spec/helpers"; 6 import * as helpers from "../../spec/helpers";
6 7
@@ -45,7 +46,7 @@ describe("Components", () => { @@ -45,7 +46,7 @@ describe("Components", () => {
45 // in each test if one needs customization of these parameters per test 46 // in each test if one needs customization of these parameters per test
46 let cls = createClass({ 47 let cls = createClass({
47 template: defaultViewTemplate, 48 template: defaultViewTemplate,
48 - directives: [ArticleDefaultViewComponent], 49 + directives: [ArticleDefaultViewComponent, PermissionDirective],
49 providers: providers, 50 providers: providers,
50 properties: { 51 properties: {
51 article: article 52 article: article
@@ -65,16 +66,24 @@ describe("Components", () => { @@ -65,16 +66,24 @@ describe("Components", () => {
65 expect(state.transitionTo).toHaveBeenCalled(); 66 expect(state.transitionTo).toHaveBeenCalled();
66 }); 67 });
67 68
  69 + it("hide delete article button when user doesn't have permission", () => {
  70 + expect(helper.find(".article-toolbar .delete-article").attr('style')).toEqual("display: none; ");
  71 + });
  72 +
  73 + it("hide edit article button when user doesn't have permission", () => {
  74 + expect(helper.find(".article-toolbar .edit-article").attr('style')).toEqual("display: none; ");
  75 + });
  76 +
68 /** 77 /**
69 * Execute the delete method on the target component 78 * Execute the delete method on the target component
70 */ 79 */
71 function doDeleteArticle() { 80 function doDeleteArticle() {
72 // Create a mock for the notification service confirmation 81 // Create a mock for the notification service confirmation
73 - spyOn(helper.component.notificationService, 'confirmation').and.callFake(function (params: Function) { 82 + spyOn(helper.component.notificationService, 'confirmation').and.callFake(function(params: Function) {
74 83
75 }); 84 });
76 // Create a mock for the ArticleService removeArticle method 85 // Create a mock for the ArticleService removeArticle method
77 - spyOn(helper.component.articleService, 'remove').and.callFake(function (param: noosfero.Article) { 86 + spyOn(helper.component.articleService, 'remove').and.callFake(function(param: noosfero.Article) {
78 87
79 return { 88 return {
80 catch: () => { } 89 catch: () => { }
src/app/article/article.html
@@ -4,13 +4,15 @@ @@ -4,13 +4,15 @@
4 </div> 4 </div>
5 5
6 <div class="sub-header clearfix"> 6 <div class="sub-header clearfix">
7 - <a href="#" class="btn btn-default btn-xs" ui-sref="main.cmsEdit({profile: ctrl.profile.identifier, id: ctrl.article.id})">  
8 - <i class="fa fa-pencil-square-o fa-fw fa-lg"></i> {{"article.actions.edit" | translate}}  
9 - </a>  
10 - <a href="#" class="btn btn-default btn-xs" ng-click="ctrl.delete()">  
11 - <i class="fa fa-trash-o fa-fw fa-lg" ng-click="ctrl.delete()"></i> {{"article.actions.delete" | translate}}  
12 - </a>  
13 - <noosfero-hotspot-article-toolbar [article]="ctrl.article"></noosfero-hotspot-article-toolbar> 7 + <div class="article-toolbar">
  8 + <a href="#" permission="ctrl.article.permissions" permission-action="allow_edit" class="btn btn-default btn-xs edit-article" ui-sref="main.cmsEdit({profile: ctrl.profile.identifier, id: ctrl.article.id})">
  9 + <i class="fa fa-pencil-square-o fa-fw fa-lg"></i> {{"article.actions.edit" | translate}}
  10 + </a>
  11 + <a href="#" permission="ctrl.article.permissions" permission-action="allow_delete" class="btn btn-default btn-xs delete-article" ng-click="ctrl.delete()">
  12 + <i class="fa fa-trash-o fa-fw fa-lg" ng-click="ctrl.delete()"></i> {{"article.actions.delete" | translate}}
  13 + </a>
  14 + <noosfero-hotspot-article-toolbar [article]="ctrl.article"></noosfero-hotspot-article-toolbar>
  15 + </div>
14 <div class="page-info pull-right small text-muted"> 16 <div class="page-info pull-right small text-muted">
15 <span class="time"> 17 <span class="time">
16 <i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.article.created_at | dateFormat"></span> 18 <i class="fa fa-clock-o"></i> <span am-time-ago="ctrl.article.created_at | dateFormat"></span>
src/app/article/content-viewer/navbar-actions.html
1 -<ul class="nav navbar-nav"> 1 +<ul class="nav navbar-nav" permission="vm.profile.permissions" permission-action="allow_edit">
2 <li class="dropdown profile-menu" uib-dropdown> 2 <li class="dropdown profile-menu" uib-dropdown>
3 <a class="btn dropdown-toggle" data-toggle="dropdown" uib-dropdown-toggle> 3 <a class="btn dropdown-toggle" data-toggle="dropdown" uib-dropdown-toggle>
4 {{"navbar.content_viewer_actions.new_item" | translate}} 4 {{"navbar.content_viewer_actions.new_item" | translate}}
@@ -19,4 +19,3 @@ @@ -19,4 +19,3 @@
19 </li> 19 </li>
20 20
21 </ul> 21 </ul>
22 -  
src/app/main/main.component.ts
@@ -39,7 +39,7 @@ import {SidebarComponent} from &quot;../layout/sidebar/sidebar.component&quot;; @@ -39,7 +39,7 @@ import {SidebarComponent} from &quot;../layout/sidebar/sidebar.component&quot;;
39 39
40 import {MainBlockComponent} from "../layout/blocks/main/main-block.component"; 40 import {MainBlockComponent} from "../layout/blocks/main/main-block.component";
41 import {HtmlEditorComponent} from "../shared/components/html-editor/html-editor.component"; 41 import {HtmlEditorComponent} from "../shared/components/html-editor/html-editor.component";
42 - 42 +import {PermissionDirective} from "../shared/components/permission/permission.directive";
43 43
44 /** 44 /**
45 * @ngdoc controller 45 * @ngdoc controller
@@ -100,7 +100,7 @@ export class EnvironmentContent { @@ -100,7 +100,7 @@ export class EnvironmentContent {
100 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent, 100 LinkListBlockComponent, CommunitiesBlockComponent, HtmlEditorComponent,
101 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent, 101 MainBlockComponent, RecentDocumentsBlockComponent, Navbar, SidebarComponent, ProfileImageBlockComponent,
102 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent, 102 MembersBlockComponent, NoosferoTemplate, DateFormat, RawHTMLBlockComponent, StatisticsBlockComponent,
103 - LoginBlockComponent, CustomContentComponent 103 + LoginBlockComponent, CustomContentComponent, PermissionDirective
104 ].concat(plugins.mainComponents).concat(plugins.hotspots), 104 ].concat(plugins.mainComponents).concat(plugins.hotspots),
105 105
106 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService] 106 providers: [AuthService, SessionService, NotificationService, BodyStateClassesService]
src/app/profile/custom-content/custom-content.html
1 <div class="custom-content"> 1 <div class="custom-content">
2 - <div class="actions"> 2 + <div class="actions" permission="ctrl.profiles.permissions" permission-action="allow_edit">
3 <button type="submit" class="btn btn-xs btn-default" ng-click="ctrl.openEdit()"><i class="fa fa-edit fa-fw"></i> {{ctrl.label | translate}}</button> 3 <button type="submit" class="btn btn-xs btn-default" ng-click="ctrl.openEdit()"><i class="fa fa-edit fa-fw"></i> {{ctrl.label | translate}}</button>
4 </div> 4 </div>
5 <div class="content" ng-bind-html="ctrl.content"></div> 5 <div class="content" ng-bind-html="ctrl.content"></div>
src/app/shared/components/permission/permission.directive.spec.ts 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +import {Input, provide, Component} from 'ng-forward';
  2 +import {PermissionDirective} from "./permission.directive";
  3 +import * as helpers from "../../../../spec/helpers";
  4 +
  5 +const htmlTemplate: string = '<div permission="ctrl.permissions" permission-action="action"></div>';
  6 +
  7 +describe("Permission directive", () => {
  8 +
  9 + let element = jasmine.createSpyObj("$element", ["css"]);
  10 + let scope = jasmine.createSpyObj("$scope", ["$watch", "$eval"]);
  11 + scope.$watch = (param: string, f: Function) => { f(); };
  12 + scope.$eval = (param: any) => { return param; };
  13 +
  14 + it("hide element when there is no permission action in the permissions array", (done: Function) => {
  15 + let attrs: any = { permission: [], permissionAction: 'action' };
  16 + let directive = new PermissionDirective(<any>attrs, scope, element);
  17 + expect(element.css).toHaveBeenCalledWith('display', 'none');
  18 + done();
  19 + });
  20 +
  21 + it("show element when the permission action exists in the permissions array", (done: Function) => {
  22 + let attrs = { permission: ['action'], permissionAction: 'action' };
  23 + let directive = new PermissionDirective(<any>attrs, scope, element);
  24 + expect(element.css).toHaveBeenCalledWith('display', '');
  25 + done();
  26 + });
  27 +});
src/app/shared/components/permission/permission.directive.ts 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +import {Directive, Inject, Input} from "ng-forward";
  2 +
  3 +@Directive({
  4 + selector: '[permission]'
  5 +})
  6 +@Inject('$attrs', '$scope', '$element')
  7 +export class PermissionDirective {
  8 +
  9 + constructor($attrs: ng.IAttributes, $scope: ng.IScope, $element: any) {
  10 + $scope.$watch($attrs['permission'], () => {
  11 + let permissions = $scope.$eval($attrs['permission']);
  12 + let permissionAction = $attrs['permissionAction'];
  13 + if (!permissions || permissions.indexOf(permissionAction) < 0) {
  14 + $element.css("display", "none");
  15 + } else {
  16 + $element.css("display", "");
  17 + }
  18 + });
  19 + }
  20 +}