]> source.dussan.org Git - sonarqube.git/blob
7b1c5f1271e0bc048ebe8727d55f17aa6a66338a
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 package org.sonar.server.platform.db.migration.version.v64;
22
23 import com.google.common.collect.ImmutableMap;
24 import java.sql.SQLException;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Optional;
28 import javax.annotation.Nullable;
29 import org.apache.commons.lang.RandomStringUtils;
30 import org.junit.Rule;
31 import org.junit.Test;
32 import org.junit.rules.ExpectedException;
33 import org.sonar.core.util.stream.MoreCollectors;
34 import org.sonar.db.CoreDbTester;
35 import org.sonar.server.platform.db.migration.version.v63.DefaultOrganizationUuidProviderImpl;
36
37 import static java.lang.String.format;
38 import static org.apache.commons.lang.math.RandomUtils.nextLong;
39 import static org.assertj.core.api.Assertions.assertThat;
40
41 public class PopulateOrganizationMembersTableTest {
42
43   private static final String TABLE = "organization_members";
44
45   private static final String DEFAULT_ORGANIZATION_UUID = "def org uuid";
46
47   private static final String PERMISSION_PROVISIONING = "provisioning";
48   private static final String PERMISSION_ADMIN = "admin";
49   private static final String PERMISSION_BROWSE = "user";
50   private static final String PERMISSION_CODEVIEWER = "codeviewer";
51
52   private static final String ORG1_UUID = "ORG1_UUID";
53   private static final String ORG2_UUID = "ORG2_UUID";
54
55   private static final String USER1_LOGIN = "USER1";
56   private static final String USER2_LOGIN = "USER2";
57   private static final String USER3_LOGIN = "USER3";
58
59   @Rule
60   public ExpectedException expectedException = ExpectedException.none();
61
62   @Rule
63   public CoreDbTester db = CoreDbTester.createForSchema(PopulateOrganizationMembersTableTest.class, "initial.sql");
64
65   private PopulateOrganizationMembersTable underTest = new PopulateOrganizationMembersTable(db.database(), new DefaultOrganizationUuidProviderImpl());
66
67   @Test
68   public void fails_with_ISE_when_no_default_organization_is_set() throws SQLException {
69     expectedException.expect(IllegalStateException.class);
70     expectedException.expectMessage("Default organization uuid is missing");
71
72     underTest.execute();
73   }
74
75   @Test
76   public void fails_with_ISE_when_default_organization_does_not_exist_in_table_ORGANIZATIONS() throws SQLException {
77     setDefaultOrganizationProperty("blabla");
78
79     expectedException.expect(IllegalStateException.class);
80     expectedException.expectMessage("Default organization with uuid 'blabla' does not exist in table ORGANIZATIONS");
81
82     underTest.execute();
83   }
84
85   @Test
86   public void execute_has_no_effect_when_table_is_empty() throws SQLException {
87     setupDefaultOrganization();
88
89     underTest.execute();
90   }
91
92   @Test
93   public void execute_is_reentrant_when_table_is_empty() throws SQLException {
94     setupDefaultOrganization();
95
96     underTest.execute();
97     underTest.execute();
98   }
99
100   @Test
101   public void migrate_user_having_direct_global_permissions() throws Exception {
102     setupDefaultOrganization();
103     insertOrganization(ORG1_UUID);
104     insertOrganization(ORG2_UUID);
105     int userId = insertUser(USER1_LOGIN);
106     insertUserRole(userId, PERMISSION_PROVISIONING, ORG1_UUID, null);
107     insertUserRole(userId, PERMISSION_ADMIN, ORG1_UUID, null);
108     insertUserRole(userId, PERMISSION_ADMIN, ORG2_UUID, null);
109
110     underTest.execute();
111
112     verifyUserMembership(userId, ORG1_UUID, ORG2_UUID, DEFAULT_ORGANIZATION_UUID);
113   }
114
115   @Test
116   public void migrate_user_having_direct_project_permissions() throws Exception {
117     setupDefaultOrganization();
118     insertOrganization(ORG1_UUID);
119     insertOrganization(ORG2_UUID);
120     int userId = insertUser(USER1_LOGIN);
121     insertUserRole(userId, PERMISSION_BROWSE, ORG1_UUID, 1);
122     insertUserRole(userId, PERMISSION_CODEVIEWER, ORG1_UUID, 1);
123     insertUserRole(userId, PERMISSION_ADMIN, ORG2_UUID, 2);
124
125     underTest.execute();
126
127     verifyUserMembership(userId, ORG1_UUID, ORG2_UUID, DEFAULT_ORGANIZATION_UUID);
128   }
129
130   @Test
131   public void migrate_user_having_global_permissions_from_group() throws Exception {
132     setupDefaultOrganization();
133     insertOrganization(ORG1_UUID);
134     insertOrganization(ORG2_UUID);
135     int userId = insertUser(USER1_LOGIN);
136     int group1Id = insertNewGroup(ORG1_UUID);
137     int group2Id = insertNewGroup(ORG2_UUID);
138     insertUserGroup(userId, group1Id);
139     insertUserGroup(userId, group2Id);
140
141     underTest.execute();
142
143     verifyUserMembership(userId, ORG1_UUID, ORG2_UUID, DEFAULT_ORGANIZATION_UUID);
144   }
145
146   @Test
147   public void user_without_any_permission_should_be_member_of_default_organization() throws Exception {
148     setupDefaultOrganization();
149     int userId = insertUser(USER1_LOGIN);
150
151     underTest.execute();
152
153     verifyUserMembership(userId, DEFAULT_ORGANIZATION_UUID, DEFAULT_ORGANIZATION_UUID);
154   }
155
156   @Test
157   public void migrate_users_having_any_kind_of_permission() throws Exception {
158     setupDefaultOrganization();
159     insertOrganization(ORG1_UUID);
160     insertOrganization(ORG2_UUID);
161     int user1 = insertUser(USER1_LOGIN);
162     int user2 = insertUser(USER2_LOGIN);
163     int user3 = insertUser(USER3_LOGIN);
164     int groupId = insertNewGroup(ORG1_UUID);
165     insertUserGroup(user2, groupId);
166     insertUserRole(user1, PERMISSION_PROVISIONING, ORG1_UUID, null);
167     insertUserRole(user1, PERMISSION_BROWSE, ORG2_UUID, 1);
168
169     underTest.execute();
170
171     verifyUserMembership(user1, ORG1_UUID, ORG2_UUID, DEFAULT_ORGANIZATION_UUID);
172     verifyUserMembership(user2, ORG1_UUID, DEFAULT_ORGANIZATION_UUID);
173     verifyUserMembership(user3, DEFAULT_ORGANIZATION_UUID);
174   }
175
176   @Test
177   public void migrate_missing_membership_on_direct_permission() throws Exception {
178     setupDefaultOrganization();
179     insertOrganization(ORG1_UUID);
180     insertOrganization(ORG2_UUID);
181     int userId = insertUser(USER1_LOGIN);
182     insertUserRole(userId, PERMISSION_ADMIN, ORG1_UUID, null);
183     insertUserRole(userId, PERMISSION_PROVISIONING, ORG2_UUID, null);
184     // Membership on organization 1 already exists, migration will add membership on organization 2 and default organization
185     insertOrganizationMember(userId, ORG1_UUID);
186
187     underTest.execute();
188
189     verifyUserMembership(userId, ORG1_UUID, ORG2_UUID, DEFAULT_ORGANIZATION_UUID);
190   }
191
192   @Test
193   public void migrate_missing_membership_on_group_permission() throws Exception {
194     setupDefaultOrganization();
195     insertOrganization(ORG1_UUID);
196     insertOrganization(ORG2_UUID);
197     int userId = insertUser(USER1_LOGIN);
198     int group1Id = insertNewGroup(ORG1_UUID);
199     int group2Id = insertNewGroup(ORG2_UUID);
200     insertUserGroup(userId, group1Id);
201     insertUserGroup(userId, group2Id);
202     // Membership on organization 1 already exists, migration will add membership on organization 2 and default organization
203     insertOrganizationMember(userId, ORG1_UUID);
204
205     underTest.execute();
206
207     verifyUserMembership(userId, ORG1_UUID, ORG2_UUID, DEFAULT_ORGANIZATION_UUID);
208   }
209
210   @Test
211   public void migrate_active_users_to_default_organization() throws Exception {
212     setupDefaultOrganization();
213     int user1Id = insertUser(USER1_LOGIN, false);
214     int user2Id = insertUser(USER2_LOGIN, false);
215     int user3Id = insertUser(USER3_LOGIN, false);
216     int group1Id = insertNewGroup(ORG1_UUID);
217     insertUserRole(user1Id, PERMISSION_ADMIN, ORG1_UUID, null);
218     insertUserGroup(user2Id, group1Id);
219
220     underTest.execute();
221
222     verifyUserMembership(user1Id);
223     verifyUserMembership(user2Id);
224     verifyUserMembership(user3Id);
225   }
226
227   @Test
228   public void ignore_already_associated_users() throws Exception {
229     setupDefaultOrganization();
230     insertOrganization(ORG1_UUID);
231     int userId = insertUser(USER1_LOGIN);
232     insertUserRole(userId, PERMISSION_PROVISIONING, ORG1_UUID, null);
233     // User is already associated to organization 1 and to default organization, it should not fail
234     insertOrganizationMember(userId, ORG1_UUID);
235     insertOrganizationMember(userId, DEFAULT_ORGANIZATION_UUID);
236
237     underTest.execute();
238
239     verifyUserMembership(userId, ORG1_UUID, DEFAULT_ORGANIZATION_UUID);
240   }
241
242   @Test
243   public void migration_is_reentrant() throws Exception {
244     setupDefaultOrganization();
245     insertOrganization(ORG1_UUID);
246     int userId = insertUser(USER1_LOGIN);
247     insertUserRole(userId, PERMISSION_PROVISIONING, ORG1_UUID, null);
248     verifyUserMembership(userId);
249
250     underTest.execute();
251     verifyUserMembership(userId, ORG1_UUID, DEFAULT_ORGANIZATION_UUID);
252
253     underTest.execute();
254     verifyUserMembership(userId, ORG1_UUID, DEFAULT_ORGANIZATION_UUID);
255   }
256
257   private void insertOrganizationMember(int userId, String organizationUuid) {
258     db.executeInsert(TABLE, "USER_ID", userId, "ORGANIZATION_UUID", organizationUuid);
259   }
260
261   private void insertOrganization(String uuid) {
262     db.executeInsert("ORGANIZATIONS", "UUID", uuid, "KEE", uuid, "NAME", uuid, "GUARDED", false, "CREATED_AT", nextLong(), "UPDATED_AT", nextLong());
263   }
264
265   private int insertUser(String login) {
266     return insertUser(login, true);
267   }
268
269   private int insertUser(String login, boolean enabled) {
270     db.executeInsert("USERS", "LOGIN", login, "NAME", login, "ACTIVE", enabled, "IS_ROOT", false);
271     return ((Long) db.selectFirst(format("select ID from users where login='%s'", login)).get("ID")).intValue();
272   }
273
274   private void insertUserRole(int userId, String permission, String organizationUuid, @Nullable Integer componentId) {
275     ImmutableMap.Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
276       .putAll(ImmutableMap.of("USER_ID", userId, "ROLE", permission, "ORGANIZATION_UUID", organizationUuid));
277     Optional.ofNullable(componentId).ifPresent(id -> builder.put("RESOURCE_ID", id));
278     db.executeInsert("USER_ROLES", builder.build());
279   }
280
281   private int insertNewGroup(String organizationUuid) {
282     String groupName = RandomStringUtils.random(10);
283     db.executeInsert("GROUPS", "NAME", groupName, "ORGANIZATION_UUID", organizationUuid);
284     return ((Long) db.selectFirst(format("select ID from groups where name='%s' and organization_uuid='%s'", groupName, organizationUuid)).get("ID")).intValue();
285   }
286
287   private void insertUserGroup(int userId, int groupId) {
288     db.executeInsert("GROUPS_USERS", "USER_ID", userId, "GROUP_ID", groupId);
289   }
290
291   private void setupDefaultOrganization() {
292     setDefaultOrganizationProperty(DEFAULT_ORGANIZATION_UUID);
293     insertOrganization(DEFAULT_ORGANIZATION_UUID);
294   }
295
296   private void setDefaultOrganizationProperty(String defaultOrganizationUuid) {
297     db.executeInsert(
298       "INTERNAL_PROPERTIES",
299       "KEE", "organization.default",
300       "IS_EMPTY", "false",
301       "TEXT_VALUE", defaultOrganizationUuid);
302   }
303
304   private void verifyUserMembership(int userId, String... organizationUuids) {
305     List<Map<String, Object>> rows = db.select(format("SELECT ORGANIZATION_UUID FROM " + TABLE + " WHERE USER_ID = %s", userId));
306     List<String> userOrganizationUuids = rows.stream()
307       .map(values -> (String) values.get("ORGANIZATION_UUID"))
308       .collect(MoreCollectors.toList());
309     assertThat(userOrganizationUuids).containsOnly(organizationUuids);
310   }
311
312 }