]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5851 use user's permissions to display available actions
authorStas Vilchik <vilchiks@gmail.com>
Tue, 14 Apr 2015 15:21:56 +0000 (17:21 +0200)
committerStas Vilchik <vilchiks@gmail.com>
Tue, 14 Apr 2015 15:24:01 +0000 (17:24 +0200)
server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-actions.hbs
server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profile-details.hbs
server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profile-header.hbs
server/sonar-web/src/main/js/quality-profiles/actions-view.js
server/sonar-web/src/main/js/quality-profiles/app.js
server/sonar-web/src/main/js/quality-profiles/controller.js
server/sonar-web/src/main/js/quality-profiles/profile-details-view.js
server/sonar-web/src/main/js/quality-profiles/profile-header-view.js
server/sonar-web/src/test/js/quality-profiles.js
server/sonar-web/src/test/json/quality-profiles/user-admin.json [new file with mode: 0644]
server/sonar-web/src/test/json/quality-profiles/user.json [new file with mode: 0644]

index d78c76b513a9c06fbc9d7014217686a6c03264b2..b173c8ee77f2683eb7ea2ab99877f3351138c971 100644 (file)
@@ -1,19 +1,26 @@
 <h1 class="page-title">{{t 'quality_profiles.page'}}</h1>
 
+
 <div class="page-actions">
-  <div class="button-group dropdown">
-    <button id="quality-profiles-create">{{t 'create'}}</button>
-    <a class="button dropdown-toggle" href="#" data-toggle="dropdown"><i class="icon-dropdown"></i></a>
-    <ul class="dropdown-menu dropdown-menu-right">
-      <li>
-        <a href="#">{{t 'quality_profiles.compare_profiles'}}</a>
-      </li>
-      <li>
-        <a id="quality-profiles-restore" href="#">{{t 'quality_profiles.restore_profile'}}</a>
-      </li>
-      <li>
-        <a id="quality-profiles-restore-built-in" href="#">{{t 'quality_profiles.restore_built_in_profiles'}}</a>
-      </li>
-    </ul>
-  </div>
+  {{#if canWrite}}
+    <div class="button-group dropdown">
+      <button id="quality-profiles-create">{{t 'create'}}</button>
+      <a class="button dropdown-toggle" href="#" data-toggle="dropdown"><i class="icon-dropdown"></i></a>
+      <ul class="dropdown-menu dropdown-menu-right">
+        <li>
+          <a id="quality-profiles-compare" href="#">{{t 'quality_profiles.compare_profiles'}}</a>
+        </li>
+        <li>
+          <a id="quality-profiles-restore" href="#">{{t 'quality_profiles.restore_profile'}}</a>
+        </li>
+        <li>
+          <a id="quality-profiles-restore-built-in" href="#">{{t 'quality_profiles.restore_built_in_profiles'}}</a>
+        </li>
+      </ul>
+    </div>
+  {{else}}
+    <div class="button-group">
+      <button id="quality-profiles-compare">{{t 'quality_profiles.compare_profiles'}}</button>
+    </div>
+  {{/if}}
 </div>
index 502448d9f7a9d079999cc2c59f4c62e2ce61cf50..c40678d064de6c2770a1de9fdb4fde790aef6009 100644 (file)
     <h3 class="page-title">{{t 'projects'}}</h3>
   </header>
   {{#if isDefault}}
-    <p class="alert alert-info">{{t 'quality_profiles.projects_for_default.edit'}}</p>
+    {{#if canWrite}}
+      <p class="alert alert-info">{{t 'quality_profiles.projects_for_default.edit'}}</p>
+    {{else}}
+      <p class="alert alert-info">{{t 'quality_profiles.projects_for_default'}}</p>
+    {{/if}}
   {{else}}
     <div id="quality-profile-projects-list"></div>
   {{/if}}
 <div class="panel panel-vertical" id="quality-profile-inheritance">
   <header class="page-header">
     <h3 class="page-title">{{t 'quality_profiles.profile_inheritance'}}</h3>
-    <div class="page-actions">
-      <div class="button-group">
-        <button id="quality-profile-change-parent">{{t 'quality_profiles.change_parent'}}</button>
+    {{#if canWrite}}
+      <div class="page-actions">
+        <div class="button-group">
+          <button id="quality-profile-change-parent">{{t 'quality_profiles.change_parent'}}</button>
+        </div>
       </div>
-    </div>
+    {{/if}}
   </header>
   <div class="text-center">
     {{#notEmpty ancestors}}
index 00ba0b100def7e3b9901b8f5f717e2cfa44db674..141004e9fdba7ca03aa6713846b76b60f3b7c77a 100644 (file)
@@ -7,11 +7,13 @@
   <div class="button-group">
     <a class="button" href="{{link '/api/qualityprofiles/backup?profileKey=' encodedKey}}" target="_blank"
        id="quality-profile-backup">{{t 'backup_verb'}}</a>
-    <button id="quality-profile-rename">{{t 'rename'}}</button>
-    <button id="quality-profile-copy">{{t 'copy'}}</button>
-    {{#unless isDefault}}
-      <button id="quality-profile-set-as-default">{{t 'set_as_default'}}</button>
-      <button id="quality-profile-delete" class="button-red">{{t 'delete'}}</button>
-    {{/unless}}
+    {{#if canWrite}}
+      <button id="quality-profile-rename">{{t 'rename'}}</button>
+      <button id="quality-profile-copy">{{t 'copy'}}</button>
+      {{#unless isDefault}}
+        <button id="quality-profile-set-as-default">{{t 'set_as_default'}}</button>
+        <button id="quality-profile-delete" class="button-red">{{t 'delete'}}</button>
+      {{/unless}}
+    {{/if}}
   </div>
 </div>
index 67f4caceba9daf3b0b6d79cf9af7d79449777599..4d0653c3f57f50e563f4f83977fb3c93ccc386df 100644 (file)
@@ -79,6 +79,12 @@ define([
     requestLanguages: function () {
       var url = baseUrl + '/api/languages/list';
       return $.get(url);
+    },
+
+    serializeData: function () {
+      return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), {
+        canWrite: this.options.canWrite
+      });
     }
   });
 
index b3e2a269ea665ae13f41ba9678432dbdae7b8f5b..d139f2b17b55759c03d84caf8e12caa855a0ef15 100644 (file)
@@ -43,13 +43,15 @@ require([
 
     // Actions View
     this.actionsView = new ActionsView({
-      collection: this.profiles
+      collection: this.profiles,
+      canWrite: this.canWrite
     });
     this.layout.actionsRegion.show(this.actionsView);
 
     // Profiles View
     this.profilesView = new ProfilesView({
-      collection: this.profiles
+      collection: this.profiles,
+      canWrite: this.canWrite
     });
     this.layout.resultsRegion.show(this.profilesView);
 
@@ -62,7 +64,12 @@ require([
 
   });
 
-  window.requestMessages().done(function () {
+
+  var requestUser = $.get(baseUrl + '/api/users/current').done(function (r) {
+    App.canWrite = r.permissions.global.indexOf('profileadmin') !== -1;
+  });
+
+  $.when(window.requestMessages(), requestUser).done(function () {
     App.start();
   });
 
index 8219fa96e13efa20409e6cdc95b360a0adf9fdaf..906503b17c01ebf693eb09c8fae19a893d84fc99 100644 (file)
@@ -67,10 +67,16 @@ define([
       }
       this.options.app.profilesView.highlight(key);
       this.fetchProfile(profile).done(function () {
-        var profileHeaderView = new ProfileHeaderView({ model: profile });
+        var profileHeaderView = new ProfileHeaderView({
+          model: profile,
+          canWrite: that.options.app.canWrite
+        });
         that.options.app.layout.headerRegion.show(profileHeaderView);
 
-        var profileDetailsView = new ProfileDetailsView({ model: profile });
+        var profileDetailsView = new ProfileDetailsView({
+          model: profile,
+          canWrite: that.options.app.canWrite
+        });
         that.options.app.layout.detailsRegion.show(profileDetailsView);
       });
     },
index 8c26922ad85f43a09e093145478b1ace03cef920..87a13beb80e74ec49b3d0914d3666ee42382485d 100644 (file)
@@ -55,7 +55,7 @@ define([
       new window.SelectList({
         el: this.$('#quality-profile-projects-list'),
         width: '100%',
-        readOnly: false,
+        readOnly: !this.options.canWrite,
         focusSearch: false,
         format: function (item) {
           return item.name;
@@ -105,7 +105,8 @@ define([
       var key = this.model.get('key'),
           rulesSearchUrl = '/coding_rules#qprofile=' + encodeURIComponent(key) + '|activation=true';
       return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), {
-        rulesSearchUrl: rulesSearchUrl
+        rulesSearchUrl: rulesSearchUrl,
+        canWrite: this.options.canWrite
       });
     }
   });
index 0ea480936b84cf5475347e79453cd0c039ff25e0..7b55bfa3d2ef211a86b93327051a3e6f5e885ced 100644 (file)
@@ -84,7 +84,8 @@ define([
     serializeData: function () {
       var key = this.model.get('key');
       return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), {
-        encodedKey: encodeURIComponent(key)
+        encodedKey: encodeURIComponent(key),
+        canWrite: this.options.canWrite
       });
     }
   });
index c63fe829f431df21dfdfbe7c97f5eecb50ca84cd..60062524a224d05783fbac4bae062bd9782ae540 100644 (file)
@@ -32,6 +32,7 @@ casper.test.begin(testName('Should Show List'), 9, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
       })
 
@@ -69,11 +70,65 @@ casper.test.begin(testName('Should Show List'), 9, function (test) {
 });
 
 
-casper.test.begin(testName('Should Show Details'), 9, function (test) {
+casper.test.begin(testName('Should Show Details'), 10, function (test) {
   casper
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user.json');
+        lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+        lib.mockRequestFromFile('/api/rules/search', 'rules.json',
+            { data: { qprofile: 'java-sonar-way-67887', activation: 'true' }});
+        lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json', {
+          data: { profileKey: 'java-sonar-way-67887' }
+        });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['/js/quality-profiles/app.js']);
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('.js-list .list-group-item');
+      })
+
+      .then(function () {
+        casper.click('.js-list .list-group-item[data-key="java-sonar-way-67887"]');
+        casper.waitForSelector('.search-navigator-header-component');
+      })
+
+      .then(function () {
+        test.assertElementCount('.js-list .list-group-item.active', 1);
+        test.assertSelectorContains('.js-list .list-group-item.active', 'Sonar way');
+
+        test.assertSelectorContains('.search-navigator-workspace-header', 'Sonar way');
+        test.assertSelectorContains('.search-navigator-workspace-header', 'Java');
+        test.assertExists('#quality-profile-backup');
+        test.assertDoesntExist('#quality-profile-rename');
+        test.assertDoesntExist('#quality-profile-copy');
+        test.assertDoesntExist('#quality-profile-delete');
+        test.assertDoesntExist('#quality-profile-set-as-default');
+        test.assertDoesntExist('#quality-profile-change-parent');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Should Show Details', 'Admin'), 10, function (test) {
+  casper
+      .start(lib.buildUrl('profiles'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json',
             { data: { qprofile: 'java-sonar-way-67887', activation: 'true' }});
@@ -108,6 +163,7 @@ casper.test.begin(testName('Should Show Details'), 9, function (test) {
         test.assertExists('#quality-profile-copy');
         test.assertDoesntExist('#quality-profile-delete');
         test.assertDoesntExist('#quality-profile-set-as-default');
+        test.assertExists('#quality-profile-change-parent');
       })
 
       .then(function () {
@@ -125,6 +181,7 @@ casper.test.begin(testName('Should Show Inheritance Details'), 10, function (tes
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-inheritance.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance-plus.json', {
@@ -177,6 +234,7 @@ casper.test.begin(testName('Should Show Selected Projects'), 2, function (test)
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/projects?key=php-psr-2-46772', 'projects.json');
@@ -222,6 +280,7 @@ casper.test.begin(testName('Copy Profile'), 5, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -282,6 +341,7 @@ casper.test.begin(testName('Rename Profile'), 2, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -342,6 +402,7 @@ casper.test.begin(testName('Make Profile Default'), 4, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -396,6 +457,7 @@ casper.test.begin(testName('Delete Profile'), 2, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-with-copy.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -453,6 +515,7 @@ casper.test.begin(testName('Create Profile'), 2, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -510,6 +573,7 @@ casper.test.begin(testName('Restore Built-in Profiles'), 2, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-modified.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -566,6 +630,7 @@ casper.test.begin(testName('Change Parent'), 1, function (test) {
       .start(lib.buildUrl('profiles'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-change-parent.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         this.inheritanceMock = lib.mockRequestFromFile('/api/qualityprofiles/inheritance',
@@ -628,6 +693,7 @@ casper.test.begin(testName('Permalink'), 9, function (test) {
       .start(lib.buildUrl('profiles#show?key=java-sonar-way-67887'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -671,6 +737,7 @@ casper.test.begin(testName('Changelog'), 21, function (test) {
       .start(lib.buildUrl('profiles#show?key=java-sonar-way-67887'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -746,6 +813,7 @@ casper.test.begin(testName('Changelog Permalink'), 2, function (test) {
       .start(lib.buildUrl('profiles#changelog?since=2015-03-25&key=java-sonar-way-67887&to=2015-03-26'), function () {
         lib.setDefaultViewport();
 
+        lib.mockRequestFromFile('/api/users/current', 'user.json');
         lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
         lib.mockRequestFromFile('/api/rules/search', 'rules.json');
         lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
diff --git a/server/sonar-web/src/test/json/quality-profiles/user-admin.json b/server/sonar-web/src/test/json/quality-profiles/user-admin.json
new file mode 100644 (file)
index 0000000..d0d8417
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "isLoggedIn": true,
+  "login": "admin",
+  "name": "Administrator",
+  "permissions": {
+    "global": [
+      "provisioning",
+      "dryRunScan",
+      "shareDashboard",
+      "scan",
+      "profileadmin",
+      "admin"
+    ]
+  }
+}
diff --git a/server/sonar-web/src/test/json/quality-profiles/user.json b/server/sonar-web/src/test/json/quality-profiles/user.json
new file mode 100644 (file)
index 0000000..3d5f7c3
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "isLoggedIn": false,
+  "permissions": {
+    "global": [
+      "scan",
+      "dryRunScan"
+    ]
+  }
+}