]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8581 WS api/navigation/component use the new PagesDefinition API
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 6 Jan 2017 16:57:51 +0000 (17:57 +0100)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 13 Jan 2017 16:58:12 +0000 (17:58 +0100)
server/sonar-server/src/main/java/org/sonar/server/ui/ws/ComponentAction.java
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/component-example.json
server/sonar-server/src/test/java/org/sonar/server/ui/ws/ComponentActionTest.java
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_configuration_for_admin.json
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions.json
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/ComponentActionTest/return_extensions_for_admin.json

index 41503bd01410a50199d6f9549a42cf671910b70d..ffdb67f07349571779ac93071363debd5c825afe 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 package org.sonar.server.ui.ws;
 
 import com.google.common.collect.Lists;
@@ -25,9 +26,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import java.util.function.Predicate;
 import java.util.stream.Stream;
 import javax.annotation.Nullable;
-import org.sonar.api.i18n.I18n;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypes;
@@ -37,8 +38,8 @@ import org.sonar.api.server.ws.WebService.NewAction;
 import org.sonar.api.server.ws.WebService.NewController;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
+import org.sonar.api.web.UserRole;
+import org.sonar.api.web.page.Page;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
@@ -54,11 +55,9 @@ import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonar.server.qualityprofile.QPMeasureData;
 import org.sonar.server.qualityprofile.QualityProfile;
-import org.sonar.server.ui.ViewProxy;
-import org.sonar.server.ui.Views;
+import org.sonar.server.ui.PageRepository;
 import org.sonar.server.user.UserSession;
 
-import static java.util.Locale.ENGLISH;
 import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
 import static org.sonar.api.web.UserRole.ADMIN;
 import static org.sonar.api.web.UserRole.USER;
@@ -75,24 +74,41 @@ public class ComponentAction implements NavigationWsAction {
   private static final String PROPERTY_UPDATABLE_KEY = "updatable_key";
 
   private final DbClient dbClient;
-  private final Views views;
-  private final I18n i18n;
+  private final PageRepository pageRepository;
   private final ResourceTypes resourceTypes;
   private final UserSession userSession;
   private final ComponentFinder componentFinder;
   private final QualityGateFinder qualityGateFinder;
 
-  public ComponentAction(DbClient dbClient, Views views, I18n i18n, ResourceTypes resourceTypes, UserSession userSession,
-                         ComponentFinder componentFinder, QualityGateFinder qualityGateFinder) {
+  public ComponentAction(DbClient dbClient, PageRepository pageRepository, ResourceTypes resourceTypes, UserSession userSession,
+    ComponentFinder componentFinder, QualityGateFinder qualityGateFinder) {
     this.dbClient = dbClient;
-    this.views = views;
-    this.i18n = i18n;
+    this.pageRepository = pageRepository;
     this.resourceTypes = resourceTypes;
     this.userSession = userSession;
     this.componentFinder = componentFinder;
     this.qualityGateFinder = qualityGateFinder;
   }
 
+  private static Consumer<QualityProfile> writeToJson(JsonWriter json) {
+    return profile -> json.beginObject()
+      .prop("key", profile.getQpKey())
+      .prop("name", profile.getQpName())
+      .prop("language", profile.getLanguageKey())
+      .endObject();
+  }
+
+  private static Function<MeasureDto, Stream<QualityProfile>> toQualityProfiles() {
+    return dbMeasure -> QPMeasureData.fromJson(dbMeasure.getData()).getProfiles().stream();
+  }
+
+  private static void writePage(JsonWriter json, Page page) {
+    json.beginObject()
+      .prop("key", page.getKey())
+      .prop("name", page.getName())
+      .endObject();
+  }
+
   @Override
   public void define(NewController context) {
     NewAction projectNavigation = context.createAction("component")
@@ -141,7 +157,7 @@ public class ComponentAction implements NavigationWsAction {
     if (analysis != null) {
       json.prop("version", analysis.getVersion())
         .prop("snapshotDate", DateUtils.formatDateTime(new Date(analysis.getCreatedAt())));
-      List<ViewProxy<Page>> pages = views.getPages(NavigationSection.RESOURCE, component.scope(), component.qualifier(), component.language());
+      List<Page> pages = pageRepository.getComponentPages(false, component.qualifier());
       writeExtensions(json, component, pages);
     }
   }
@@ -165,18 +181,6 @@ public class ComponentAction implements NavigationWsAction {
     json.endArray();
   }
 
-  private static Consumer<QualityProfile> writeToJson(JsonWriter json) {
-    return profile -> json.beginObject()
-      .prop("key", profile.getQpKey())
-      .prop("name", profile.getQpName())
-      .prop("language", profile.getLanguageKey())
-      .endObject();
-  }
-
-  private static Function<MeasureDto, Stream<QualityProfile>> toQualityProfiles() {
-    return dbMeasure -> QPMeasureData.fromJson(dbMeasure.getData()).getProfiles().stream();
-  }
-
   private void writeQualityGate(JsonWriter json, DbSession session, ComponentDto component) {
     Optional<QualityGateFinder.QualityGateData> qualityGateData = qualityGateFinder.getQualityGate(session, component.getId());
     if (!qualityGateData.isPresent()) {
@@ -190,11 +194,15 @@ public class ComponentAction implements NavigationWsAction {
       .endObject();
   }
 
-  private void writeExtensions(JsonWriter json, ComponentDto component, List<ViewProxy<Page>> pages) {
+  private void writeExtensions(JsonWriter json, ComponentDto component, List<Page> pages) {
     json.name("extensions").beginArray();
+    Predicate<Page> isAuthorized = page -> {
+      String requiredPermission = page.isAdmin() ? UserRole.ADMIN : UserRole.USER;
+      return userSession.hasComponentUuidPermission(requiredPermission, component.uuid());
+    };
     pages.stream()
-      .filter(page -> page.isUserAuthorized(component))
-      .forEach(page -> writePage(json, page.getId(), i18n.message(ENGLISH, page.getId() + ".page", page.getTitle())));
+      .filter(isAuthorized)
+      .forEach(page -> writePage(json, page));
     json.endArray();
   }
 
@@ -206,8 +214,8 @@ public class ComponentAction implements NavigationWsAction {
 
     if (isAdmin) {
       json.name("extensions").beginArray();
-      List<ViewProxy<Page>> configPages = views.getPages(NavigationSection.RESOURCE_CONFIGURATION, component.scope(), component.qualifier(), component.language());
-      configPages.forEach(page -> writePage(json, page.getId(), i18n.message(ENGLISH, page.getId() + ".page", page.getTitle())));
+      List<Page> configPages = pageRepository.getComponentPages(true, component.qualifier());
+      configPages.forEach(page -> writePage(json, page));
       json.endArray();
     }
     json.endObject();
@@ -233,13 +241,6 @@ public class ComponentAction implements NavigationWsAction {
     return resourceType != null && resourceType.getBooleanProperty(resourceTypeProperty);
   }
 
-  private static void writePage(JsonWriter json, String id, String name) {
-    json.beginObject()
-      .prop("id", id)
-      .prop("name", name)
-      .endObject();
-  }
-
   private void writeBreadCrumbs(JsonWriter json, DbSession session, ComponentDto component) {
     json.name("breadcrumbs").beginArray();
 
index 40878b2efdf90b9c899d172ed4a17efb3043edeb..cfef93904a875507f8ed416bc00de15af35fdfd1 100644 (file)
@@ -8,16 +8,14 @@
   "snapshotDate": "2016-12-06T11:44:00+0200",
   "extensions": [
     {
-      "id": "/admin/page",
-      "name": "Admin Page"
+      "key": "first_page",
+      "name": "First Page",
+      "path": "/static/my_plugin/first_page.js"
     },
     {
-      "id": "first_page",
-      "name": "First Page"
-    },
-    {
-      "id": "/second/page",
-      "name": "Second Page"
+      "key": "second_page",
+      "name": "Second Page",
+      "path": "/static/my_plugin/second_page.js"
     }
   ],
   "qualityProfiles": [
     "showHistory": true,
     "showUpdateKey": true,
     "showBackgroundTasks": true,
-    "extensions": []
+    "extensions": [
+      {
+        "key": "admin_page",
+        "name": "Admin Page",
+        "path": "/static/my_plugin/admin_page.js"
+      }
+    ]
   },
   "breadcrumbs": [
     {
index 49349b3058b17867eaf575c77121aa6d146ff174..d1043e7fa1a4b1e18001191557c57d9ae7c50290 100644 (file)
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
+
 package org.sonar.server.ui.ws;
 
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.ResourceType;
 import org.sonar.api.resources.ResourceTypes;
-import org.sonar.api.resources.Scopes;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
-import org.sonar.api.web.NavigationSection;
-import org.sonar.api.web.Page;
-import org.sonar.api.web.ResourceLanguage;
-import org.sonar.api.web.ResourceQualifier;
-import org.sonar.api.web.ResourceScope;
 import org.sonar.api.web.UserRole;
-import org.sonar.api.web.View;
+import org.sonar.api.web.page.Page;
+import org.sonar.api.web.page.Page.Qualifier;
+import org.sonar.api.web.page.PageDefinition;
 import org.sonar.core.component.DefaultResourceTypes;
+import org.sonar.core.platform.PluginRepository;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDbTester;
@@ -59,16 +54,15 @@ import org.sonar.server.qualitygate.QualityGateFinder;
 import org.sonar.server.qualityprofile.QPMeasureData;
 import org.sonar.server.qualityprofile.QualityProfile;
 import org.sonar.server.tester.UserSessionRule;
-import org.sonar.server.ui.Views;
+import org.sonar.server.ui.PageRepository;
 import org.sonar.server.ws.WsActionTester;
 
-import static java.util.Locale.ENGLISH;
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY;
+import static org.sonar.api.web.page.Page.Scope.COMPONENT;
 import static org.sonar.core.permission.GlobalPermissions.QUALITY_PROFILE_ADMIN;
 import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN;
 import static org.sonar.db.component.ComponentTesting.newDirectory;
@@ -103,16 +97,17 @@ public class ComponentActionTest {
   private UserDbTester userDbTester = dbTester.users();
   private PropertyDbTester propertyDbTester = new PropertyDbTester(dbTester);
 
-  private I18n i18n = mock(I18n.class);
-
   private ResourceTypes resourceTypes = mock(ResourceTypes.class);
 
   private WsActionTester ws;
 
-  @Before
-  public void before() {
-    when(i18n.message(eq(ENGLISH), any(String.class), any(String.class)))
-      .thenAnswer(invocation -> invocation.getArgumentAt(2, String.class));
+  private static QualityProfile createQProfile(String qpKey, String qpName, String languageKey) {
+    return new QualityProfile(qpKey, qpName, languageKey, new Date());
+  }
+
+  private static String qualityProfilesToJson(QualityProfile... qps) {
+    List<QualityProfile> qualityProfiles = Arrays.asList(qps);
+    return QPMeasureData.toJson(new QPMeasureData(qualityProfiles));
   }
 
   @Test
@@ -228,7 +223,7 @@ public class ComponentActionTest {
 
   @Test
   public void return_extensions() throws Exception {
-    init(createViews());
+    init(createPages());
     componentDbTester.insertProjectAndSnapshot(PROJECT);
     userSessionRule.anonymous().addProjectUuidPermissions(UserRole.USER, PROJECT.uuid());
 
@@ -237,7 +232,7 @@ public class ComponentActionTest {
 
   @Test
   public void return_extensions_for_admin() throws Exception {
-    init(createViews());
+    init(createPages());
     componentDbTester.insertProjectAndSnapshot(PROJECT);
     userSessionRule.anonymous()
       .addProjectUuidPermissions(UserRole.USER, PROJECT.uuid())
@@ -254,39 +249,20 @@ public class ComponentActionTest {
       .addProjectUuidPermissions(UserRole.USER, "abcd")
       .addProjectUuidPermissions(UserRole.ADMIN, "abcd");
 
-    @NavigationSection(NavigationSection.RESOURCE_CONFIGURATION)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class FirstPage implements Page {
-      @Override
-      public String getTitle() {
-        return "First Page";
-      }
-
-      @Override
-      public String getId() {
-        return "first_page";
-      }
-    }
-
-    @NavigationSection(NavigationSection.RESOURCE_CONFIGURATION)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class SecondPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Second Page";
-      }
-
-      @Override
-      public String getId() {
-        return "/second/page";
-      }
-    }
+    Page page1 = Page.builder("my_plugin/first_page")
+      .setName("First Page")
+      .setAdmin(true)
+      .setScope(COMPONENT)
+      .setComponentQualifiers(Qualifier.PROJECT)
+      .build();
+    Page page2 = Page.builder("my_plugin/second_page")
+      .setName("Second Page")
+      .setAdmin(true)
+      .setScope(COMPONENT)
+      .setComponentQualifiers(Qualifier.PROJECT)
+      .build();
 
-    init(new Page[] {new FirstPage(), new SecondPage()});
+    init(page1, page2);
     executeAndVerify(PROJECT.key(), "return_configuration_for_admin.json");
   }
 
@@ -351,7 +327,7 @@ public class ComponentActionTest {
 
   @Test
   public void work_with_only_system_admin() throws Exception {
-    init(createViews());
+    init(createPages());
     componentDbTester.insertProjectAndSnapshot(PROJECT);
     userSessionRule.setGlobalPermissions(SYSTEM_ADMIN);
 
@@ -360,8 +336,9 @@ public class ComponentActionTest {
 
   @Test
   public void test_example_response() throws Exception {
-    init(createViews());
-    ComponentDto project = newProjectDto("ABCD").setKey("org.codehaus.sonar:sonar").setName("Sonarqube").setDescription("Open source platform for continuous inspection of code quality");
+    init(createPages());
+    ComponentDto project = newProjectDto("ABCD").setKey("org.codehaus.sonar:sonar").setName("Sonarqube")
+      .setDescription("Open source platform for continuous inspection of code quality");
     componentDbTester.insertComponent(project);
     SnapshotDto analysis = newAnalysis(project)
       .setCreatedAt(DateUtils.parseDateTime("2016-12-06T11:44:00+0200").getTime())
@@ -376,15 +353,26 @@ public class ComponentActionTest {
       createQProfile("qp2", "Sonar Way Xoo", "xoo"));
     QualityGateDto qualityGateDto = dbTester.qualityGates().insertQualityGate("Sonar way");
     dbTester.qualityGates().associateProjectToQualityGate(project, qualityGateDto);
-    userSessionRule.login(user).addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
+    userSessionRule.login(user)
+      .addProjectUuidPermissions(UserRole.USER, project.uuid())
+      .addProjectUuidPermissions(UserRole.ADMIN, project.uuid());
 
     String result = execute(project.key());
     assertJson(ws.getDef().responseExampleAsString()).ignoreFields("snapshotDate", "key").isSimilarTo(result);
   }
 
-  private void init(View... views) {
-    ws = new WsActionTester(new ComponentAction(dbClient, new Views(userSessionRule, views), i18n, resourceTypes, userSessionRule, new ComponentFinder(dbClient),
-      new QualityGateFinder(dbClient)));
+  private void init(Page... pages) {
+    PluginRepository pluginRepository = mock(PluginRepository.class);
+    when(pluginRepository.hasPlugin(anyString())).thenReturn(true);
+    PageRepository pageRepository = new PageRepository(pluginRepository, new PageDefinition[] {context -> {
+      for (Page page : pages) {
+        context.addPage(page);
+      }
+    }});
+    pageRepository.start();
+    ws = new WsActionTester(
+      new ComponentAction(dbClient, pageRepository, resourceTypes, userSessionRule, new ComponentFinder(dbClient),
+        new QualityGateFinder(dbClient)));
   }
 
   private String execute(String componentKey) {
@@ -408,67 +396,24 @@ public class ComponentActionTest {
     dbTester.commit();
   }
 
-  private static QualityProfile createQProfile(String qpKey, String qpName, String languageKey) {
-    return new QualityProfile(qpKey, qpName, languageKey, new Date());
-  }
-
-  private static String qualityProfilesToJson(QualityProfile... qps) {
-    List<QualityProfile> qualityProfiles = Arrays.asList(qps);
-    return QPMeasureData.toJson(new QPMeasureData(qualityProfiles));
-  }
-
-  private View[] createViews() {
-    @NavigationSection(NavigationSection.RESOURCE)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class FirstPage implements Page {
-      @Override
-      public String getTitle() {
-        return "First Page";
-      }
-
-      @Override
-      public String getId() {
-        return "first_page";
-      }
-    }
-    Page page1 = new FirstPage();
-
-    @NavigationSection(NavigationSection.RESOURCE)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    class SecondPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Second Page";
-      }
-
-      @Override
-      public String getId() {
-        return "/second/page";
-      }
-    }
-    Page page2 = new SecondPage();
-
-    @NavigationSection(NavigationSection.RESOURCE)
-    @ResourceScope(Scopes.PROJECT)
-    @ResourceQualifier(Qualifiers.PROJECT)
-    @ResourceLanguage("xoo")
-    @UserRole(UserRole.ADMIN)
-    class AdminPage implements Page {
-      @Override
-      public String getTitle() {
-        return "Admin Page";
-      }
+  private Page[] createPages() {
+    Page page1 = Page.builder("my_plugin/first_page")
+      .setName("First Page")
+      .setScope(COMPONENT)
+      .setComponentQualifiers(Qualifier.PROJECT)
+      .build();
+    Page page2 = Page.builder("my_plugin/second_page")
+      .setName("Second Page")
+      .setScope(COMPONENT)
+      .setComponentQualifiers(Qualifier.PROJECT)
+      .build();
+    Page adminPage = Page.builder("my_plugin/admin_page")
+      .setName("Admin Page")
+      .setScope(COMPONENT)
+      .setComponentQualifiers(Qualifier.PROJECT)
+      .setAdmin(true)
+      .build();
 
-      @Override
-      public String getId() {
-        return "/admin/page";
-      }
-    }
-    Page adminPage = new AdminPage();
     return new Page[] {page1, page2, adminPage};
   }
 }
index b68d79e7f3e3eaf930a785d2c5e12dd5aa3bf2cb..be150b7ce8b9455f2ea1786af2306a92a799ea61 100644 (file)
     "showUpdateKey": false,
     "extensions": [
       {
-        "id": "first_page",
+        "key": "my_plugin/first_page",
         "name": "First Page"
       },
       {
-        "id": "/second/page",
+        "key": "my_plugin/second_page",
         "name": "Second Page"
       }
     ]
index e470ef4428b282f8e5336a595620e43d4d11020e..8ecf18f4e6a01a9697c7366a7ba28e41a5e55c69 100644 (file)
@@ -1,11 +1,11 @@
 {
   "extensions": [
     {
-      "id": "first_page",
+      "key": "my_plugin/first_page",
       "name": "First Page"
     },
     {
-      "id": "/second/page",
+      "key": "my_plugin/second_page",
       "name": "Second Page"
     }
   ]
index 7301a92fd5449567d9531c52c9155d18cdea07d3..8ecf18f4e6a01a9697c7366a7ba28e41a5e55c69 100644 (file)
@@ -1,16 +1,12 @@
 {
   "extensions": [
     {
-      "id": "first_page",
+      "key": "my_plugin/first_page",
       "name": "First Page"
     },
     {
-      "id": "/second/page",
+      "key": "my_plugin/second_page",
       "name": "Second Page"
-    },
-    {
-      "id": "/admin/page",
-      "name": "Admin Page"
     }
   ]
 }