]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6427 Internal WS to get global navigation configuratio 236/head
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Mon, 20 Apr 2015 08:55:16 +0000 (10:55 +0200)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Tue, 21 Apr 2015 12:58:19 +0000 (14:58 +0200)
18 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalNavigationAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWs.java [new file with mode: 0644]
server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-global.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalNavigationActionTest.java [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/anonymous.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/empty.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/only_logo.json [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/user.json [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/dashboard/ActiveDashboardDao.java
sonar-core/src/main/java/org/sonar/core/dashboard/ActiveDashboardMapper.java
sonar-core/src/main/java/org/sonar/core/dashboard/DashboardDao.java
sonar-core/src/main/resources/org/sonar/core/dashboard/ActiveDashboardMapper.xml
sonar-core/src/test/java/org/sonar/core/dashboard/ActiveDashboardDaoTest.java
sonar-core/src/test/java/org/sonar/core/dashboard/DashboardDaoTest.java
sonar-core/src/test/resources/org/sonar/core/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForAnonymous.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForUser.xml [new file with mode: 0644]

index 95e0f4dcba8441bb002da4e725f3a9b4a3111703..1385f7d6877615d3b964e9c1868e6356fe72f24c 100644 (file)
@@ -347,6 +347,8 @@ import org.sonar.server.text.RubyTextService;
 import org.sonar.server.ui.JRubyI18n;
 import org.sonar.server.ui.PageDecorations;
 import org.sonar.server.ui.Views;
+import org.sonar.server.ui.ws.GlobalNavigationAction;
+import org.sonar.server.ui.ws.NavigationWs;
 import org.sonar.server.updatecenter.ws.UpdateCenterWs;
 import org.sonar.server.user.DefaultUserService;
 import org.sonar.server.user.DoPrivileged;
@@ -903,6 +905,10 @@ class ServerComponents {
     pico.addSingleton(ProjectSettingsFactory.class);
     pico.addSingleton(IndexPurgeListener.class);
 
+    // UI
+    pico.addSingleton(GlobalNavigationAction.class);
+    pico.addSingleton(NavigationWs.class);
+
     for (Object components : level4AddedComponents) {
       pico.addSingleton(components);
     }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalNavigationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/GlobalNavigationAction.java
new file mode 100644 (file)
index 0000000..c6a7c7d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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 org.sonar.api.config.Settings;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService.NewController;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.api.web.NavigationSection;
+import org.sonar.api.web.Page;
+import org.sonar.core.dashboard.ActiveDashboardDao;
+import org.sonar.core.dashboard.DashboardDto;
+import org.sonar.server.ui.ViewProxy;
+import org.sonar.server.ui.Views;
+import org.sonar.server.user.UserSession;
+
+import java.util.List;
+
+public class GlobalNavigationAction implements NavigationAction {
+
+  private final ActiveDashboardDao activeDashboardDao;
+  private final Views views;
+  private final Settings settings;
+
+  public GlobalNavigationAction(ActiveDashboardDao activeDashboardDao, Views views, Settings settings) {
+    this.activeDashboardDao = activeDashboardDao;
+    this.views = views;
+    this.settings = settings;
+  }
+
+  @Override
+  public void define(NewController context) {
+    context.createAction("global")
+      .setDescription("Get information concerning global navigation for the current user.")
+      .setHandler(this)
+      .setInternal(true)
+      .setResponseExample(getClass().getResource("example-global.json"))
+      .setSince("5.2");
+  }
+
+  @Override
+  public void handle(Request request, Response response) throws Exception {
+    UserSession userSession = UserSession.get();
+
+    List<DashboardDto> dashboards = activeDashboardDao.selectGlobalDashboardsForUserLogin(userSession.login());
+
+    JsonWriter json = response.newJsonWriter().beginObject();
+    writeDashboards(json, dashboards);
+    writePages(json);
+    writeLogoProperties(json);
+    json.endObject().close();
+  }
+
+  private void writeDashboards(JsonWriter json, List<DashboardDto> dashboards) {
+    json.name("globalDashboards").beginArray();
+    for (DashboardDto dashboard : dashboards) {
+      json.beginObject()
+        .prop("key", dashboard.getKey())
+        .prop("name", dashboard.getName())
+        .endObject();
+    }
+    json.endArray();
+  }
+
+  private void writePages(JsonWriter json) {
+    json.name("globalPages").beginArray();
+    for (ViewProxy<Page> page : views.getPages(NavigationSection.HOME)) {
+      json.beginObject()
+        .prop("name", page.getTitle())
+        .prop("url", page.isController() ? page.getId() : String.format("/plugins/home/%s", page.getId()))
+        .endObject();
+    }
+    json.endArray();
+  }
+
+  private void writeLogoProperties(JsonWriter json) {
+    json.prop("logoUrl", settings.getString("sonar.lf.logoUrl"));
+    json.prop("logoWidth", settings.getString("sonar.lf.logoWidthPx"));
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationAction.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationAction.java
new file mode 100644 (file)
index 0000000..80443aa
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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 org.sonar.server.ws.WsAction;
+
+public interface NavigationAction extends WsAction {
+
+  // Marker interface for navigation related actions
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWs.java b/server/sonar-server/src/main/java/org/sonar/server/ui/ws/NavigationWs.java
new file mode 100644 (file)
index 0000000..ce5bbc5
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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 org.sonar.api.server.ws.WebService;
+
+public class NavigationWs implements WebService {
+
+  private final NavigationAction[] actions;
+
+  public NavigationWs(NavigationAction... actions) {
+    this.actions = actions;
+  }
+
+  @Override
+  public void define(Context context) {
+    NewController navigation = context.createController("api/navigation")
+      .setDescription("Get information required to build navigation UI components")
+      .setSince("5.2");
+
+    for (NavigationAction action : actions) {
+      action.define(navigation);
+    }
+
+    navigation.done();
+  }
+
+}
diff --git a/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-global.json b/server/sonar-server/src/main/resources/org/sonar/server/ui/ws/example-global.json
new file mode 100644 (file)
index 0000000..b4ead35
--- /dev/null
@@ -0,0 +1,16 @@
+{
+  "globalDashboards": [
+    {
+      "id": 51,
+      "name": "Helicopter View"
+    }
+  ],
+  "globalPages": [
+    {
+      "name": "My Plugin",
+      "url": "/plugins/home/my-plugin"
+    }
+  ],
+  "logoUrl": "http://example.com/my-custom-logo.png",
+  "logoWidth": 135
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalNavigationActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ui/ws/GlobalNavigationActionTest.java
new file mode 100644 (file)
index 0000000..ec28952
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * 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 org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.System2;
+import org.sonar.api.web.Page;
+import org.sonar.api.web.View;
+import org.sonar.core.dashboard.ActiveDashboardDao;
+import org.sonar.core.dashboard.ActiveDashboardDto;
+import org.sonar.core.dashboard.DashboardDao;
+import org.sonar.core.dashboard.DashboardDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.ui.Views;
+import org.sonar.server.user.MockUserSession;
+import org.sonar.server.user.db.UserDao;
+import org.sonar.server.ws.WsTester;
+
+import static org.mockito.Mockito.mock;
+
+public class GlobalNavigationActionTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
+
+  private DbSession session;
+
+  private WsTester wsTester;
+
+  private UserDao userDao;
+
+  private DashboardDao dashboardDao;
+
+  private ActiveDashboardDao activeDashboardDao;
+
+  @Before
+  public void before() throws Exception {
+    dbTester.truncateTables();
+
+    userDao = new UserDao(dbTester.myBatis(), mock(System2.class));
+    dashboardDao = new DashboardDao(dbTester.myBatis());
+    activeDashboardDao = new ActiveDashboardDao(dbTester.myBatis());
+    DbClient dbClient = new DbClient(
+      dbTester.database(), dbTester.myBatis(), userDao, dashboardDao, activeDashboardDao);
+
+    session = dbClient.openSession(false);
+  }
+
+  @After
+  public void after() throws Exception {
+    session.close();
+  }
+
+  @Test
+  public void empty_call() throws Exception {
+    wsTester = new WsTester(new NavigationWs(new GlobalNavigationAction(activeDashboardDao, new Views(), new Settings())));
+
+    MockUserSession.set();
+
+    wsTester.newGetRequest("api/navigation", "global").execute().assertJson(getClass(), "empty.json");
+  }
+
+  @Test
+  public void only_logo() throws Exception {
+    wsTester = new WsTester(new NavigationWs(new GlobalNavigationAction(activeDashboardDao, new Views(),
+      new Settings()
+        .setProperty("sonar.lf.logoUrl", "http://some-server.tld/logo.png")
+        .setProperty("sonar.lf.logoWidthPx", "123"))));
+
+    MockUserSession.set();
+
+    wsTester.newGetRequest("api/navigation", "global").execute().assertJson(getClass(), "only_logo.json");
+  }
+
+  @Test
+  public void nominal_call_for_anonymous() throws Exception {
+    nominalSetup();
+
+    MockUserSession.set();
+
+    wsTester.newGetRequest("api/navigation", "global").execute().assertJson(getClass(), "anonymous.json");
+  }
+
+  @Test
+  public void nominal_call_for_user() throws Exception {
+    nominalSetup();
+
+    MockUserSession.set().setLogin("obiwan");
+
+    wsTester.newGetRequest("api/navigation", "global").execute().assertJson(getClass(), "user.json");
+  }
+
+  private void nominalSetup() {
+    createAndConfigureDashboardForUser();
+    createAndConfigureDashboardForAnonymous();
+
+    session.commit();
+
+    Settings settings = new Settings()
+      .setProperty("sonar.lf.logoUrl", "http://some-server.tld/logo.png")
+      .setProperty("sonar.lf.logoWidthPx", "123");
+    wsTester = new WsTester(new NavigationWs(new GlobalNavigationAction(activeDashboardDao, createViews(), settings)));
+  }
+
+  private void createAndConfigureDashboardForUser() {
+    UserDto user = createUser("obiwan", 42L);
+    userDao.insert(session, user);
+    DashboardDto defaultDashboardForUser = createDashboard(1L, "Default Dashboard for User", true);
+    dashboardDao.insert(defaultDashboardForUser);
+    activeDashboardDao.insert(createActiveDashboard(user.getId(), defaultDashboardForUser.getId(), 1));
+  }
+
+  private void createAndConfigureDashboardForAnonymous() {
+    DashboardDto defaultDashboardForAnonymous = createDashboard(2L, "Default Dashboard for Anonymous", true);
+    dashboardDao.insert(defaultDashboardForAnonymous);
+    activeDashboardDao.insert(createActiveDashboard(null, defaultDashboardForAnonymous.getId(), 1));
+  }
+
+  private UserDto createUser(String login, Long userId) {
+    return new UserDto()
+      .setActive(true)
+      .setId(userId)
+      .setLogin(login);
+  }
+
+  private DashboardDto createDashboard(long id, String name, boolean global) {
+    return new DashboardDto()
+      .setGlobal(global)
+      .setId(id)
+      .setName(name)
+      .setShared(true);
+  }
+
+  private ActiveDashboardDto createActiveDashboard(Long userId, Long dashboardId, int orderIndex) {
+    return new ActiveDashboardDto()
+      .setOrderIndex(orderIndex)
+      .setDashboardId(dashboardId)
+      .setUserId(userId);
+  }
+
+  private Views createViews() {
+    Page page = new Page() {
+      @Override
+      public String getTitle() {
+        return "My Plugin Page";
+      }
+      @Override
+      public String getId() {
+        return "my_plugin_page";
+      }
+    };
+    Page controller = new Page() {
+      @Override
+      public String getTitle() {
+        return "My Rails App";
+      }
+      @Override
+      public String getId() {
+        return "/my_rails_app";
+      }
+    };
+    return new Views(new View[] {page, controller});
+  }
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/anonymous.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/anonymous.json
new file mode 100644 (file)
index 0000000..d6877e5
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "globalDashboards": [
+    {
+      "name": "Default Dashboard for Anonymous"
+    }
+  ],
+  "globalPages": [
+    {
+      "name": "My Plugin Page",
+      "url": "/plugins/home/my_plugin_page"
+    },
+    {
+      "name": "My Rails App",
+      "url": "/my_rails_app"
+    }
+  ],
+  "logoUrl": "http://some-server.tld/logo.png",
+  "logoWidth": "123"
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/empty.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/empty.json
new file mode 100644 (file)
index 0000000..cc4b088
--- /dev/null
@@ -0,0 +1,4 @@
+{
+  "globalDashboards": [],
+  "globalPages": []
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/only_logo.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/only_logo.json
new file mode 100644 (file)
index 0000000..2a79a7d
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "globalDashboards": [],
+  "globalPages": [],
+  "logoUrl": "http://some-server.tld/logo.png",
+  "logoWidth": "123"
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/user.json b/server/sonar-server/src/test/resources/org/sonar/server/ui/ws/GlobalNavigationActionTest/user.json
new file mode 100644 (file)
index 0000000..eb0242c
--- /dev/null
@@ -0,0 +1,19 @@
+{
+  "globalDashboards": [
+    {
+      "name": "Default Dashboard for User"
+    }
+  ],
+  "globalPages": [
+    {
+      "name": "My Plugin Page",
+      "url": "/plugins/home/my_plugin_page"
+    },
+    {
+      "name": "My Rails App",
+      "url": "/my_rails_app"
+    }
+  ],
+  "logoUrl": "http://some-server.tld/logo.png",
+  "logoWidth": "123"
+}
index 3dc8e42b55fc8a09eff736f827069f395eac862a..cc3de408fc6297832efec07f71c7f49642dd9382 100644 (file)
@@ -22,9 +22,14 @@ package org.sonar.core.dashboard;
 import org.apache.ibatis.session.SqlSession;
 import org.sonar.api.BatchComponent;
 import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.DaoComponent;
 import org.sonar.core.persistence.MyBatis;
 
-public class ActiveDashboardDao implements BatchComponent, ServerComponent {
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+public class ActiveDashboardDao implements BatchComponent, ServerComponent, DaoComponent {
 
   private MyBatis mybatis;
 
@@ -34,9 +39,8 @@ public class ActiveDashboardDao implements BatchComponent, ServerComponent {
 
   public void insert(ActiveDashboardDto activeDashboardDto) {
     SqlSession session = mybatis.openSession(false);
-    ActiveDashboardMapper mapper = session.getMapper(ActiveDashboardMapper.class);
     try {
-      mapper.insert(activeDashboardDto);
+      getMapper(session).insert(activeDashboardDto);
       session.commit();
     } finally {
       MyBatis.closeQuietly(session);
@@ -45,9 +49,8 @@ public class ActiveDashboardDao implements BatchComponent, ServerComponent {
 
   public int selectMaxOrderIndexForNullUser() {
     SqlSession session = mybatis.openSession(false);
-    ActiveDashboardMapper mapper = session.getMapper(ActiveDashboardMapper.class);
     try {
-      Integer max = mapper.selectMaxOrderIndexForNullUser();
+      Integer max = getMapper(session).selectMaxOrderIndexForNullUser();
       return max != null ? max.intValue() : 0;
     } finally {
       session.close();
@@ -55,4 +58,16 @@ public class ActiveDashboardDao implements BatchComponent, ServerComponent {
 
   }
 
+  public List<DashboardDto> selectGlobalDashboardsForUserLogin(@Nullable String login) {
+    SqlSession session = mybatis.openSession(false);
+    try {
+      return getMapper(session).selectGlobalDashboardsForUserLogin(login);
+    } finally {
+      session.close();
+    }
+  }
+
+  private ActiveDashboardMapper getMapper(SqlSession session) {
+    return session.getMapper(ActiveDashboardMapper.class);
+  }
 }
index b4940f7065bbbeb1c1179bc1aff448e8332d9d0e..42dbc93c8aa18057c5e3f42570e48ce51af2708a 100644 (file)
 package org.sonar.core.dashboard;
 
 
+import org.apache.ibatis.annotations.Param;
+
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import java.util.List;
 
 public interface ActiveDashboardMapper {
 
@@ -29,4 +34,5 @@ public interface ActiveDashboardMapper {
   @CheckForNull
   Integer selectMaxOrderIndexForNullUser();
 
+  List<DashboardDto> selectGlobalDashboardsForUserLogin(@Nullable @Param("login") String login);
 }
index a0cccf0854a6fbd6058ec2c61feff98faa8865cf..9051746fcf7703582cef677fc6a97eeccf6979d2 100644 (file)
@@ -22,9 +22,10 @@ package org.sonar.core.dashboard;
 import org.apache.ibatis.session.SqlSession;
 import org.sonar.api.BatchComponent;
 import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.DaoComponent;
 import org.sonar.core.persistence.MyBatis;
 
-public class DashboardDao implements BatchComponent, ServerComponent {
+public class DashboardDao implements BatchComponent, ServerComponent, DaoComponent {
 
   private MyBatis mybatis;
 
index 16b9f3cdd744c789208ff7f750fe4fd14c70ccc7..68b740e858cd3dec3d232dc3d859ba54a0ae7b4a 100644 (file)
     WHERE user_id IS NULL
   </select>
 
+  <sql id="dashboardColumns">
+    d.id, d.user_id as "userId", d.name, d.description, d.column_layout as "columnLayout",
+    d.shared, d.is_global as "global", d.created_at as "createdAt", d.updated_at as "updatedAt"
+  </sql>
+
+  <select id="selectGlobalDashboardsForUserLogin" parameterType="String" resultType="Dashboard">
+    SELECT <include refid="dashboardColumns" />
+    FROM dashboards d
+    INNER JOIN active_dashboards ad on d.id=ad.dashboard_id
+    LEFT OUTER JOIN users u on u.id=ad.user_id
+    WHERE d.is_global=${_true}
+    <choose>
+      <when test="login == null">
+      AND u.login IS NULL
+      </when>
+      <otherwise>
+      AND u.login=#{login}
+      </otherwise>
+    </choose>
+    ORDER BY order_index ASC
+  </select>
+
 </mapper>
index 845402d0f4a3679aabca83ee16eda4e1ac61e8c7..bfcffe66513331fc82dc1ca1ded0a4c29605bfa5 100644 (file)
 package org.sonar.core.dashboard;
 
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Test;
-import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.junit.experimental.categories.Category;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.test.DbTests;
 
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
 
-public class ActiveDashboardDaoTest extends AbstractDaoTestCase {
+@Category(DbTests.class)
+public class ActiveDashboardDaoTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
 
   private ActiveDashboardDao dao;
 
   @Before
   public void createDao() throws Exception {
-    dao = new ActiveDashboardDao(getMyBatis());
+    dbTester.truncateTables();
+    dao = new ActiveDashboardDao(dbTester.myBatis());
   }
 
   @Test
   public void shouldInsert() throws Exception {
-    setupData("shouldInsert");
+    dbTester.prepareDbUnit(getClass(), "shouldInsert.xml");
 
     ActiveDashboardDto dashboard = new ActiveDashboardDto();
     dashboard.setDashboardId(2L);
@@ -45,37 +52,50 @@ public class ActiveDashboardDaoTest extends AbstractDaoTestCase {
     dashboard.setOrderIndex(4);
     dao.insert(dashboard);
 
-    checkTables("shouldInsert", "active_dashboards");
+    dbTester.assertDbUnit(getClass(), "shouldInsert-result.xml", "active_dashboards");
   }
 
   @Test
   public void shouldInsertWithNoUser() throws Exception {
-    setupData("shouldInsert");
+    dbTester.prepareDbUnit(getClass(), "shouldInsert.xml");
 
     ActiveDashboardDto dashboard = new ActiveDashboardDto();
     dashboard.setDashboardId(2L);
     dashboard.setOrderIndex(4);
     dao.insert(dashboard);
 
-    checkTables("shouldInsertWithNoUser", "active_dashboards");
+    dbTester.assertDbUnit(getClass(), "shouldInsertWithNoUser-result.xml", "active_dashboards");
   }
 
   @Test
   public void shouldGetMaxOrderIndexForNullUser() throws Exception {
-    setupData("shouldGetMaxOrderIndexForNullUser");
+    dbTester.prepareDbUnit(getClass(), "shouldGetMaxOrderIndexForNullUser.xml");
 
     int index = dao.selectMaxOrderIndexForNullUser();
 
-    assertThat(index, is(15));
+    assertThat(index).isEqualTo(15);
   }
 
   @Test
   public void shouldGetZeroMaxOrderIndex() throws Exception {
-    setupData("empty");
+    dbTester.prepareDbUnit(getClass(), "empty.xml");
 
     int index = dao.selectMaxOrderIndexForNullUser();
 
-    assertThat(index, is(0));
+    assertThat(index).isZero();
+  }
+
+  @Test
+  public void should_get_dashboards_for_anonymous() throws Exception {
+    dbTester.prepareDbUnit(getClass(), "shouldSelectDashboardsForAnonymous.xml");
+
+    assertThat(dao.selectGlobalDashboardsForUserLogin(null)).hasSize(2).extracting("id").containsExactly(2L, 1L);
   }
 
+  @Test
+  public void should_get_dashboards_for_user() throws Exception {
+    dbTester.prepareDbUnit(getClass(), "shouldSelectDashboardsForUser.xml");
+
+    assertThat(dao.selectGlobalDashboardsForUserLogin("obiwan")).hasSize(2).extracting("id").containsExactly(2L, 1L);
+  }
 }
index 76afb09d54b17c3ddfdfb265a978d81b33d48a3a..f4a76577d5d2ec71e0379ad70262bfa1741a1488 100644 (file)
 package org.sonar.core.dashboard;
 
 import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Test;
-import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.junit.experimental.categories.Category;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.test.DbTests;
 
 import java.util.Date;
 
@@ -30,18 +33,23 @@ import static org.hamcrest.Matchers.nullValue;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 
-public class DashboardDaoTest extends AbstractDaoTestCase {
+@Category(DbTests.class)
+public class DashboardDaoTest {
+
+  @ClassRule
+  public static final DbTester dbTester = new DbTester();
 
   private DashboardDao dao;
 
   @Before
   public void createDao() {
-    dao = new DashboardDao(getMyBatis());
+    dbTester.truncateTables();
+    dao = new DashboardDao(dbTester.myBatis());
   }
 
   @Test
   public void shouldSelectGlobalDashboard() {
-    setupData("shouldSelectGlobalDashboard");
+    dbTester.prepareDbUnit(getClass(), "shouldSelectGlobalDashboard.xml");
     DashboardDto dashboard = dao.selectGlobalDashboard("SQALE");
     assertThat(dashboard.getId(), is(2L));
     assertThat(dashboard.getUserId(), nullValue());
@@ -51,7 +59,7 @@ public class DashboardDaoTest extends AbstractDaoTestCase {
 
   @Test
   public void shouldInsert() {
-    setupData("shouldInsert");
+    dbTester.prepareDbUnit(getClass(), "shouldInsert.xml");
     Date aDate = new Date();
 
     DashboardDto dashboardDto = new DashboardDto();
@@ -82,12 +90,12 @@ public class DashboardDaoTest extends AbstractDaoTestCase {
 
     dao.insert(dashboardDto);
 
-    checkTables("shouldInsert", new String[]{"created_at", "updated_at"}, "dashboards", "widgets", "widget_properties");
+    dbTester.assertDbUnit(getClass(), "shouldInsert-result.xml", new String[] {"created_at", "updated_at"}, "dashboards", "widgets", "widget_properties");
   }
 
   @Test
   public void shouldInsertWithNullableColumns() throws Exception {
-    setupData("shouldInsert");
+    dbTester.prepareDbUnit(getClass(), "shouldInsert.xml");
 
     DashboardDto dashboardDto = new DashboardDto();
     dashboardDto.setUserId(null);
@@ -117,7 +125,7 @@ public class DashboardDaoTest extends AbstractDaoTestCase {
 
     dao.insert(dashboardDto);
 
-    checkTables("shouldInsertWithNullableColumns", "dashboards", "widgets", "widget_properties");
+    dbTester.assertDbUnit(getClass(), "shouldInsertWithNullableColumns-result.xml", "dashboards", "widgets", "widget_properties");
   }
 
 }
diff --git a/sonar-core/src/test/resources/org/sonar/core/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForAnonymous.xml b/sonar-core/src/test/resources/org/sonar/core/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForAnonymous.xml
new file mode 100644 (file)
index 0000000..f817e37
--- /dev/null
@@ -0,0 +1,68 @@
+<dataset>
+
+  <users id="42" login="obiwan" name="Obiwan" email="obiwan@keno.bi"
+    created_at="1418215735482" updated_at="1418215735482" active="[true]"/>
+
+  <dashboards
+    id="1"
+    user_id="1"
+    name="My Dashboard"
+    description="Dashboard shared by admin"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+  <dashboards
+    id="2"
+    user_id="[null]"
+    name="Default Dashboard"
+    description="Dashboard provided by system"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+  <dashboards
+    id="3"
+    user_id="[null]"
+    name="Project Dashboard"
+    description="Won't appear, not global"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[false]"
+  />
+  <dashboards
+    id="4"
+    user_id="[null]"
+    name="User Dashboard"
+    description="Won't appear, not anonymous"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+
+  <!-- Dashboard with ID 1 appears after ID 2 -->
+  <active_dashboards
+    id="1"
+    dashboard_id="1"
+    user_id="[null]"
+    order_index="2"/>
+  <!-- Dashboard with ID 2 appears before ID 1 -->
+  <active_dashboards
+    id="2"
+    dashboard_id="2"
+    user_id="[null]"
+    order_index="1"/>
+  <!-- Dashboard with ID 3 does not appear (not global) -->
+  <active_dashboards
+    id="3"
+    dashboard_id="3"
+    user_id="[null]"
+    order_index="1"/>
+  <!-- Dashboard with ID 4 does not appear (not anonymous) -->
+  <active_dashboards
+    id="4"
+    dashboard_id="4"
+    user_id="42"
+    order_index="1"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForUser.xml b/sonar-core/src/test/resources/org/sonar/core/dashboard/ActiveDashboardDaoTest/shouldSelectDashboardsForUser.xml
new file mode 100644 (file)
index 0000000..b3dc72f
--- /dev/null
@@ -0,0 +1,85 @@
+<dataset>
+
+  <users id="24" login="anakin" name="Anakin" email="anakin@skywalk.er"
+    created_at="1418215735482" updated_at="1418215735482" active="[true]"/>
+  <users id="42" login="obiwan" name="Obiwan" email="obiwan@keno.bi"
+    created_at="1418215735482" updated_at="1418215735482" active="[true]"/>
+
+  <dashboards
+    id="1"
+    user_id="1"
+    name="My Dashboard"
+    description="Dashboard shared by admin"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+  <dashboards
+    id="2"
+    user_id="[null]"
+    name="Default Dashboard"
+    description="Dashboard provided by system"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+  <dashboards
+    id="3"
+    user_id="[null]"
+    name="Project Dashboard"
+    description="Won't appear, not global"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[false]"
+  />
+  <dashboards
+    id="4"
+    user_id="[null]"
+    name="Anonymous Dashboard"
+    description="Won't appear, anonymous"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+  <dashboards
+    id="5"
+    user_id="[null]"
+    name="Another User Dashboard"
+    description="Won't appear, different user"
+    column_layout="100%"
+    shared="[true]"
+    is_global="[true]"
+  />
+
+  <!-- Dashboard with ID 1 appears after ID 2 -->
+  <active_dashboards
+    id="1"
+    dashboard_id="1"
+    user_id="42"
+    order_index="2"/>
+  <!-- Dashboard with ID 2 appears before ID 1 -->
+  <active_dashboards
+    id="2"
+    dashboard_id="2"
+    user_id="42"
+    order_index="1"/>
+  <!-- Dashboard with ID 3 does not appear (not global) -->
+  <active_dashboards
+    id="3"
+    dashboard_id="3"
+    user_id="42"
+    order_index="1"/>
+  <!-- Dashboard with ID 4 does not appear (anonymous) -->
+  <active_dashboards
+    id="4"
+    dashboard_id="4"
+    user_id="[null]"
+    order_index="1"/>
+  <!-- Dashboard with ID 5 does not appear (another user) -->
+  <active_dashboards
+    id="5"
+    dashboard_id="5"
+    user_id="24"
+    order_index="1"/>
+
+</dataset>