Просмотр исходного кода

dashfolders: validation for duplicates in acl modal

Daniel Lee 8 лет назад
Родитель
Сommit
97ff245ad0

+ 22 - 15
public/app/features/dashboard/acl/acl.html

@@ -39,22 +39,30 @@
       </tr>
       </tr>
     </table>
     </table>
 
 
-    <form name="addPermission" class="gf-form-group">
-      <h6 class="muted">Add Permission For</h6>
-      <div class="gf-form-inline">
-        <div class="gf-form">
-          <div class="gf-form-select-wrapper">
-            <select class="gf-form-input gf-size-auto" ng-model="ctrl.newType" ng-options="p.value as p.text for p in ctrl.aclTypes"  ng-change="ctrl.typeChanged()"></select>
+    <div class="gf-form-inline">
+      <form name="addPermission" class="gf-form-group">
+        <h6 class="muted">Add Permission For</h6>
+        <div class="gf-form-inline">
+          <div class="gf-form">
+            <div class="gf-form-select-wrapper">
+              <select class="gf-form-input gf-size-auto" ng-model="ctrl.newType" ng-options="p.value as p.text for p in ctrl.aclTypes"  ng-change="ctrl.typeChanged()"></select>
+            </div>
+          </div>
+          <div class="gf-form" ng-show="ctrl.newType === 'User'">
+            <user-picker user-picked="ctrl.userPicked($user)"></user-picker>
+          </div>
+          <div class="gf-form" ng-show="ctrl.newType === 'Group'">
+            <user-group-picker user-group-picked="ctrl.groupPicked($group)"></user-group-picker>
           </div>
           </div>
         </div>
         </div>
-        <div class="gf-form" ng-show="ctrl.newType === 'User'">
-          <user-picker user-picked="ctrl.userPicked($user)"></user-picker>
-        </div>
-        <div class="gf-form" ng-show="ctrl.newType === 'Group'">
-          <user-group-picker user-group-picked="ctrl.groupPicked($group)"></user-group-picker>
-        </div>
+      </form>
+      <div class="gf-form width-17">
+        <span ng-if="ctrl.error" class="text-error p-l-1">
+          <i class="fa fa-warning"></i>
+          {{ctrl.error}}
+        </span>
       </div>
       </div>
-    </form>
+    </div>
 
 
     <div class="gf-form-button-row text-center">
     <div class="gf-form-button-row text-center">
       <button type="button" class="btn btn-danger" ng-disabled="!ctrl.canUpdate" ng-click="ctrl.update()">
       <button type="button" class="btn btn-danger" ng-disabled="!ctrl.canUpdate" ng-click="ctrl.update()">
@@ -62,9 +70,8 @@
       </button>
       </button>
       <a class="btn-text" ng-click="ctrl.dismiss();">Close</a>
       <a class="btn-text" ng-click="ctrl.dismiss();">Close</a>
     </div>
     </div>
-
-    </div>
   </div>
   </div>
+</div>
 
 
   <!-- <br> -->
   <!-- <br> -->
   <!-- <br> -->
   <!-- <br> -->

+ 24 - 0
public/app/features/dashboard/acl/acl.ts

@@ -22,6 +22,8 @@ export class AclCtrl {
   dismiss: () => void;
   dismiss: () => void;
   newType: string;
   newType: string;
   canUpdate: boolean;
   canUpdate: boolean;
+  error: string;
+  readonly duplicateError = 'This permission exists already.';
 
 
   /** @ngInject */
   /** @ngInject */
   constructor(private backendSrv, private dashboardSrv, private $sce, private $scope) {
   constructor(private backendSrv, private dashboardSrv, private $sce, private $scope) {
@@ -111,6 +113,11 @@ export class AclCtrl {
   }
   }
 
 
   addNewItem(item) {
   addNewItem(item) {
+    if (!this.isValid(item)) {
+      return;
+    }
+    this.error = '';
+
     item.dashboardId = this.dashboard.id;
     item.dashboardId = this.dashboard.id;
 
 
     this.items.push(this.prepareViewModel(item));
     this.items.push(this.prepareViewModel(item));
@@ -119,6 +126,23 @@ export class AclCtrl {
     this.canUpdate = true;
     this.canUpdate = true;
   }
   }
 
 
+  isValid(item) {
+    const dupe = _.find(this.items, (it) => { return this.isDuplicate(it, item); });
+
+    if (dupe) {
+      this.error = this.duplicateError;
+      return false;
+    }
+
+    return true;
+  }
+
+  isDuplicate(origItem, newItem) {
+    return (origItem.role && newItem.role && origItem.role === newItem.role) ||
+    (origItem.userId && newItem.userId && origItem.userId === newItem.userId) ||
+    (origItem.userGroupId && newItem.userGroupId && origItem.userGroupId === newItem.userGroupId);
+  }
+
   userPicked(user) {
   userPicked(user) {
     this.addNewItem({userId: user.id, userLogin: user.login, permission: 1,});
     this.addNewItem({userId: user.id, userLogin: user.login, permission: 1,});
     this.$scope.$broadcast('user-picker-reset');
     this.$scope.$broadcast('user-picker-reset');

+ 70 - 0
public/app/features/dashboard/acl/specs/acl_specs.ts

@@ -77,4 +77,74 @@ describe('AclCtrl', () => {
       expect(backendSrv.post.getCall(0).args[1].items[3].permission).to.eql(1);
       expect(backendSrv.post.getCall(0).args[1].items[3].permission).to.eql(1);
     });
     });
   });
   });
+
+  describe('when duplicate role permissions are added', () => {
+    beforeEach(() => {
+      backendSrv.get.reset();
+      backendSrv.post.reset();
+      ctx.ctrl.items = [];
+
+      ctx.ctrl.newType = 'Editor';
+      ctx.ctrl.typeChanged();
+
+      ctx.ctrl.newType = 'Editor';
+      ctx.ctrl.typeChanged();
+    });
+
+    it('should throw a validation error', () => {
+      expect(ctx.ctrl.error).to.eql(ctx.ctrl.duplicateError);
+    });
+
+    it('should not add the duplicate permission', () => {
+      expect(ctx.ctrl.items.length).to.eql(1);
+    });
+  });
+
+  describe('when duplicate user permissions are added', () => {
+    beforeEach(() => {
+      backendSrv.get.reset();
+      backendSrv.post.reset();
+      ctx.ctrl.items = [];
+
+      const userItem = {
+        id: 2,
+        login: 'user2',
+      };
+
+      ctx.ctrl.userPicked(userItem);
+      ctx.ctrl.userPicked(userItem);
+    });
+
+    it('should throw a validation error', () => {
+      expect(ctx.ctrl.error).to.eql(ctx.ctrl.duplicateError);
+    });
+
+    it('should not add the duplicate permission', () => {
+      expect(ctx.ctrl.items.length).to.eql(1);
+    });
+  });
+
+  describe('when duplicate user group permissions are added', () => {
+    beforeEach(() => {
+      backendSrv.get.reset();
+      backendSrv.post.reset();
+      ctx.ctrl.items = [];
+
+     const userGroupItem = {
+        id: 2,
+        name: 'ug1',
+      };
+
+      ctx.ctrl.groupPicked(userGroupItem);
+      ctx.ctrl.groupPicked(userGroupItem);
+    });
+
+    it('should throw a validation error', () => {
+      expect(ctx.ctrl.error).to.eql(ctx.ctrl.duplicateError);
+    });
+
+    it('should not add the duplicate permission', () => {
+      expect(ctx.ctrl.items.length).to.eql(1);
+    });
+  });
 });
 });