]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-13221 change ORGANIZATION_MEMBERS user_id FK to user_uuid
authorJacek <jacek.poreda@sonarsource.com>
Wed, 29 Apr 2020 12:32:19 +0000 (14:32 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 25 May 2020 20:05:21 +0000 (20:05 +0000)
65 files changed:
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/DefaultAssignee.java
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberDto.java
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationMemberMapper.java
server/sonar-db-dao/src/main/java/org/sonar/db/organization/OrganizationQuery.java
server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/organization/OrganizationMemberMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/permission/UserPermissionMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/permission/template/PermissionTemplateMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/qualityprofile/QProfileEditUsersMapper.xml
server/sonar-db-dao/src/main/resources/org/sonar/db/user/GroupMembershipMapper.xml
server/sonar-db-dao/src/schema/schema-sq.ddl
server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationDaoTest.java
server/sonar-db-dao/src/test/java/org/sonar/db/organization/OrganizationMemberDaoTest.java
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/organization/OrganizationDbTester.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/DbVersion83.java
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembers.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullable.java [new file with mode: 0644]
server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuid.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembersTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullableTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuidTest.java [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTableTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembersTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTableTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTableTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullableTest/schema.sql [new file with mode: 0644]
server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuidTest/schema.sql [new file with mode: 0644]
server/sonar-server-common/src/test/java/org/sonar/server/user/index/UserIndexerTest.java
server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/MemberUpdater.java
server/sonar-webserver-auth/src/main/java/org/sonar/server/organization/OrganizationUpdaterImpl.java
server/sonar-webserver-auth/src/main/java/org/sonar/server/user/ServerUserSession.java
server/sonar-webserver-auth/src/main/java/org/sonar/server/user/UserUpdater.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/MemberUpdaterTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/organization/OrganizationUpdaterImplTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/ServerUserSessionTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterCreateTest.java
server/sonar-webserver-auth/src/test/java/org/sonar/server/user/UserUpdaterReactivateTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/AssignAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AssignAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/organization/ws/SearchAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/permission/ws/PermissionWsSupport.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualityprofile/ws/QProfileWsSupport.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/user/ws/DeactivateAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/usergroups/ws/AddUserAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/organization/ws/AddMemberActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/organization/ws/CreateActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/organization/ws/DeleteActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/organization/ws/OrganizationDeleterTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/organization/ws/RemoveMemberActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/CreateActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/user/ws/DeactivateActionTest.java

index 49e1dadb4f5c4dab48e803e4f159b1eb30011f8d..811bfd0b8376b49ccc6214a5181ea66c43a06c4d 100644 (file)
@@ -81,6 +81,6 @@ public class DefaultAssignee {
   }
 
   private boolean isUserMemberOfOrganization(DbSession dbSession, UserDto user) {
-    return dbClient.organizationMemberDao().select(dbSession, analysisMetadataHolder.getOrganization().getUuid(), user.getId()).isPresent();
+    return dbClient.organizationMemberDao().select(dbSession, analysisMetadataHolder.getOrganization().getUuid(), user.getUuid()).isPresent();
   }
 }
index 7260f21e6d6962b98a2563c47f5829f024c6de01..bcf6436a626cb412bffb9d2ea9cf17ad2c10550c 100644 (file)
@@ -34,36 +34,32 @@ public class OrganizationMemberDao implements Dao {
     return dbSession.getMapper(OrganizationMemberMapper.class);
   }
 
-  public Optional<OrganizationMemberDto> select(DbSession dbSession, String organizationUuid, int userId) {
-    return Optional.ofNullable(mapper(dbSession).select(organizationUuid, userId));
+  public Optional<OrganizationMemberDto> select(DbSession dbSession, String organizationUuid, String userUuid) {
+    return Optional.ofNullable(mapper(dbSession).select(organizationUuid, userUuid));
   }
 
   public List<String> selectUserUuidsByOrganizationUuid(DbSession dbSession, String organizationUuid) {
     return mapper(dbSession).selectUserUuids(organizationUuid);
   }
 
-  public List<Integer> selectUserIdsByOrganizationUuid(DbSession dbSession, String organizationUuid) {
-    return mapper(dbSession).selectUserIds(organizationUuid);
-  }
-
   public void insert(DbSession dbSession, OrganizationMemberDto organizationMemberDto) {
     mapper(dbSession).insert(organizationMemberDto);
   }
 
-  public void delete(DbSession dbSession, String organizationMemberUuid, Integer userId) {
-    mapper(dbSession).delete(organizationMemberUuid, userId);
+  public void delete(DbSession dbSession, String organizationMemberUuid, String userUuid) {
+    mapper(dbSession).delete(organizationMemberUuid, userUuid);
   }
 
   public void deleteByOrganizationUuid(DbSession dbSession, String organizationMemberUuid) {
     mapper(dbSession).deleteByOrganization(organizationMemberUuid);
   }
 
-  public void deleteByUserId(DbSession dbSession, int userId) {
-    mapper(dbSession).deleteByUserId(userId);
+  public void deleteByUserUuid(DbSession dbSession, String userUuid) {
+    mapper(dbSession).deleteByUserUuid(userUuid);
   }
 
-  public Set<String> selectOrganizationUuidsByUser(DbSession dbSession, int userId) {
-    return mapper(dbSession).selectOrganizationUuidsByUser(userId);
+  public Set<String> selectOrganizationUuidsByUser(DbSession dbSession, String userUuid) {
+    return mapper(dbSession).selectOrganizationUuidsByUser(userUuid);
   }
 
   /**
index 807fd932e4faf5c63629dad1952c7a3b54d38668..e15b449aa2f35789dec1859b05801bf2009f300c 100644 (file)
@@ -21,7 +21,7 @@ package org.sonar.db.organization;
 
 public class OrganizationMemberDto {
   private String organizationUuid;
-  private Integer userId;
+  private String userUuid;
 
   public String getOrganizationUuid() {
     return organizationUuid;
@@ -32,12 +32,12 @@ public class OrganizationMemberDto {
     return this;
   }
 
-  public Integer getUserId() {
-    return userId;
+  public String getUserUuid() {
+    return userUuid;
   }
 
-  public OrganizationMemberDto setUserId(Integer userId) {
-    this.userId = userId;
+  public OrganizationMemberDto setUserUuid(String userUuid) {
+    this.userUuid = userUuid;
     return this;
   }
 }
index ddeaf3beddcbb181ddb405b9deff3ba4bffa6308..0f6cdda65ca714ca52522b5cbff7be1d8c6296c4 100644 (file)
@@ -25,24 +25,22 @@ import java.util.Set;
 import org.apache.ibatis.annotations.Param;
 
 public interface OrganizationMemberMapper {
-  OrganizationMemberDto select(@Param("organizationUuid") String organizationUuid, @Param("userId") int userId);
+  OrganizationMemberDto select(@Param("organizationUuid") String organizationUuid, @Param("userUuid") String userUuid);
 
-  Set<String> selectOrganizationUuidsByUser(@Param("userId") int userId);
+  Set<String> selectOrganizationUuidsByUser(@Param("userUuid") String userUuid);
 
   List<String> selectUserUuids(String organizationUuid);
 
-  List<Integer> selectUserIds(String organizationUuid);
-
   List<Map<String, String>> selectForIndexing(@Param("uuids") List<String> uuids);
 
   List<Map<String, String>> selectAllForIndexing();
 
   void insert(OrganizationMemberDto organizationMember);
 
-  void delete(@Param("organizationUuid") String organizationUuid, @Param("userId") Integer userId);
+  void delete(@Param("organizationUuid") String organizationUuid, @Param("userUuid") String userUuid);
 
   void deleteByOrganization(@Param("organizationUuid") String organizationUuid);
 
-  void deleteByUserId(@Param("userId") int userId);
+  void deleteByUserUuid(@Param("userUuid") String userUuid);
 
 }
index 3b95559d084e3a7459dfc413d3992aeb84026020..18eb017c9afe977b52a534e8c7f9acca94b9924f 100644 (file)
@@ -31,14 +31,14 @@ public class OrganizationQuery {
   private static final OrganizationQuery NO_FILTER = newOrganizationQueryBuilder().build();
   private final Set<String> keys;
   @Nullable
-  private final Integer userId;
+  private final String userUuid;
   private final boolean withAnalyses;
   @Nullable
   private final Long analyzedAfter;
 
   private OrganizationQuery(Builder builder) {
     this.keys = builder.keys;
-    this.userId = builder.member;
+    this.userUuid = builder.member;
     this.withAnalyses = builder.withAnalyses;
     this.analyzedAfter = builder.analyzedAfter;
   }
@@ -49,8 +49,8 @@ public class OrganizationQuery {
   }
 
   @CheckForNull
-  public Integer getMember() {
-    return userId;
+  public String getMember() {
+    return userUuid;
   }
 
   public boolean isWithAnalyses() {
@@ -73,7 +73,7 @@ public class OrganizationQuery {
   public static class Builder {
     private Set<String> keys;
     @Nullable
-    private Integer member;
+    private String member;
     private boolean withAnalyses = false;
     @Nullable
     private Long analyzedAfter;
@@ -91,8 +91,8 @@ public class OrganizationQuery {
       return this;
     }
 
-    public Builder setMember(@Nullable Integer userId) {
-      this.member = userId;
+    public Builder setMember(@Nullable String userUuid) {
+      this.member = userUuid;
       return this;
     }
 
index ad44cc71ecbd79dcd2942481a91a2d30df224c7c..8519e69c6ecd3a3a37de1ce1a163e5741bae4bea 100644 (file)
     from organizations org
     <if test="query.member != null">
       inner join organization_members om on org.uuid=om.organization_uuid
-        and om.user_id=#{query.member,jdbcType=INTEGER}
+        and om.user_uuid=#{query.member,jdbcType=VARCHAR}
     </if>
     <where>
       <if test="query.keys != null">
index 68e3767c9e4e94405ec6478440fb61732f79b1fb..b8e18e99667353571b3f07598ed607e605b8edd9 100644 (file)
@@ -5,7 +5,7 @@
 <mapper namespace="org.sonar.db.organization.OrganizationMemberMapper">
   <sql id="selectColumns">
     om.organization_uuid as "organizationUuid",
-    om.user_id as "userId"
+    om.user_uuid as "userUuid"
   </sql>
 
   <select id="select" resultType="OrganizationMember">
     from organization_members om
     where
     om.organization_uuid = #{organizationUuid, jdbcType=VARCHAR}
-    and om.user_id = #{userId, jdbcType=INTEGER}
+    and om.user_uuid = #{userUuid, jdbcType=VARCHAR}
   </select>
 
-  <select id="selectUserUuids" resultType="string">
-    select u.uuid
-    from organization_members om
-      inner join users u on om.user_id = u.id
-    where om.organization_uuid=#{organizationUuid,jdbcType=VARCHAR}
-  </select>
-
-  <select id="selectUserIds" resultType="Integer">
-    select om.user_id
+  <select id="selectUserUuids" resultType="String">
+    select om.user_uuid
     from organization_members om
     where om.organization_uuid=#{organizationUuid,jdbcType=VARCHAR}
   </select>
   <select id="selectOrganizationUuidsByUser" resultType="String">
     select om.organization_uuid as "organizationUuid"
     from organization_members om
-    where om.user_id = #{userId, jdbcType=INTEGER}
+    where om.user_uuid = #{userUuid, jdbcType=VARCHAR}
   </select>
 
   <select id="selectForIndexing" resultType="hashmap">
-    select u.uuid as "uuid", om.organization_uuid as "organizationUuid"
+    select om.user_uuid as "uuid", om.organization_uuid as "organizationUuid"
     from organization_members om
-     inner join users u on om.user_id=u.id
-    where u.uuid in
+    where om.user_uuid in
     <foreach collection="uuids" open="(" close=")" item="uuid" separator=",">
       #{uuid, jdbcType=VARCHAR}
     </foreach>
   </select>
 
   <select id="selectAllForIndexing" resultType="hashmap">
-    select u.uuid as "uuid", om.organization_uuid as "organizationUuid"
+    select om.user_uuid as "uuid", om.organization_uuid as "organizationUuid"
     from organization_members om
-    inner join users u on om.user_id=u.id
   </select>
 
   <insert id="insert" parameterType="OrganizationMember" useGeneratedKeys="false">
     insert into organization_members
     (
     organization_uuid,
-    user_id
+    user_uuid
     )
     values
     (
     #{organizationUuid, jdbcType=VARCHAR},
-    #{userId, jdbcType=INTEGER}
+    #{userUuid, jdbcType=VARCHAR}
     )
   </insert>
 
@@ -69,7 +60,7 @@
     delete from organization_members
     where
     organization_uuid = #{organizationUuid, jdbcType=VARCHAR}
-    and user_id = #{userId, jdbcType=INTEGER}
+    and user_uuid = #{userUuid, jdbcType=VARCHAR}
   </delete>
 
   <delete id="deleteByOrganization" parameterType="map">
@@ -78,8 +69,8 @@
     organization_uuid = #{organizationUuid, jdbcType=VARCHAR}
   </delete>
 
-  <delete id="deleteByUserId" parameterType="int">
-    DELETE FROM organization_members WHERE user_id=#{userId,jdbcType=BIGINT}
+  <delete id="deleteByUserUuid" parameterType="String">
+    DELETE FROM organization_members WHERE user_uuid=#{userUuid,jdbcType=VARCHAR}
   </delete>
 
 </mapper>
index 04422cb4010dbf3caaf398dc3610ab9bc373e43b..f67601e3a3ab9a997824deaa5cfa48495fd742e6 100644 (file)
@@ -41,7 +41,7 @@
       </otherwise>
     </choose>
     left join components p on ur.component_uuid = p.uuid
-    inner join organization_members om on u.id=om.user_id and om.organization_uuid=#{query.organizationUuid,jdbcType=VARCHAR}
+    inner join organization_members om on u.uuid=om.user_uuid and om.organization_uuid=#{query.organizationUuid,jdbcType=VARCHAR}
     <where>
       <include refid="sqlQueryFilters" />
     </where>
@@ -61,7 +61,7 @@
     from users u
     left join user_roles ur on ur.user_id = u.id
     left join components p on ur.component_uuid = p.uuid
-    inner join organization_members om on u.id=om.user_id and om.organization_uuid=#{query.organizationUuid,jdbcType=VARCHAR}
+    inner join organization_members om on u.uuid=om.user_uuid and om.organization_uuid=#{query.organizationUuid,jdbcType=VARCHAR}
   </sql>
 
   <sql id="sqlQueryFilters">
index fa9d96cbc899c3a3d3e02a23a9983f47954f6d1f..3e2322b63caccaef38cc59e01812aeb65cab501b 100644 (file)
     FROM users u
     LEFT JOIN perm_templates_users ptu ON ptu.user_id=u.id
       AND ptu.template_uuid=#{templateUuid}
-    INNER JOIN organization_members om ON u.id=om.user_id
+    INNER JOIN organization_members om ON u.uuid=om.user_uuid
       AND om.organization_uuid=#{query.organizationUuid}
     <where>
       u.active = ${_true}
index 0256e05d9a2281c3859211cf45bdf26a1f9173ad..5a9387d1e5ffbd68b7f14fad0317a30160094617 100644 (file)
@@ -57,7 +57,7 @@
   <sql id="sqlSelectByQuery">
     FROM users u
     LEFT JOIN qprofile_edit_users qeu ON qeu.user_id=u.id AND qeu.qprofile_uuid=#{query.qProfileUuid, jdbcType=VARCHAR}
-    INNER JOIN organization_members om ON u.id=om.user_id AND om.organization_uuid=#{query.organizationUuid, jdbcType=VARCHAR}
+    INNER JOIN organization_members om ON u.uuid=om.user_uuid AND om.organization_uuid=#{query.organizationUuid, jdbcType=VARCHAR}
     <where>
       <choose>
         <when test="query.getMembership() == 'IN'">
index 449f48aa1b40e326c7792344f0c5acd8e6760b04..59bb09825903339ff7376b7b577e43f0781779bb 100644 (file)
@@ -78,7 +78,7 @@
   <sql id="userCommonClauses">
     FROM users u
     LEFT JOIN groups_users gu ON gu.user_uuid=u.uuid AND gu.group_uuid=#{groupUuid}
-    INNER JOIN organization_members om ON u.id=om.user_id AND om.organization_uuid=#{organizationUuid}
+    INNER JOIN organization_members om ON u.uuid=om.user_uuid AND om.organization_uuid=#{organizationUuid}
     <where>
       <choose>
         <when test="query.membership() == 'IN'">
index 434c991da892ab46ddb9b51645315c65326f5456..ce9787e7d1fef6a3a3b56706c8117cf41c325383 100644 (file)
@@ -524,10 +524,10 @@ CREATE UNIQUE INDEX "ORG_ALM_BINDINGS_INSTALL" ON "ORGANIZATION_ALM_BINDINGS"("A
 
 CREATE TABLE "ORGANIZATION_MEMBERS"(
     "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-    "USER_ID" INTEGER NOT NULL
+    "USER_UUID" VARCHAR(40) NOT NULL
 );
-ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
-CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_ID");
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("USER_UUID", "ORGANIZATION_UUID");
+CREATE INDEX "ORG_MEMBERS_USER_UUID" ON "ORGANIZATION_MEMBERS"("USER_UUID");
 
 CREATE TABLE "ORGANIZATIONS"(
     "UUID" VARCHAR(40) NOT NULL,
index a18e2739959bc7eec54f038a712b43edb4873645..dadc5cc54a4d556ca2363b1339cf0282db439bcd 100644 (file)
@@ -535,7 +535,7 @@ public class OrganizationDaoTest {
     db.organizations().addMember(organization, user);
     db.organizations().addMember(anotherOrganization, user);
 
-    List<OrganizationDto> result = underTest.selectByQuery(dbSession, newOrganizationQueryBuilder().setMember(user.getId()).build(), forPage(1).andSize(100));
+    List<OrganizationDto> result = underTest.selectByQuery(dbSession, newOrganizationQueryBuilder().setMember(user.getUuid()).build(), forPage(1).andSize(100));
 
     assertThat(result).extracting(OrganizationDto::getUuid)
       .containsExactlyInAnyOrder(organization.getUuid(), anotherOrganization.getUuid())
@@ -555,7 +555,7 @@ public class OrganizationDaoTest {
 
     List<OrganizationDto> result = underTest.selectByQuery(dbSession, newOrganizationQueryBuilder()
       .setKeys(Arrays.asList(organization.getKey(), anotherOrganization.getKey(), organizationWithoutMember.getKey()))
-      .setMember(user.getId()).build(), forPage(1).andSize(100));
+      .setMember(user.getUuid()).build(), forPage(1).andSize(100));
 
     assertThat(result).extracting(OrganizationDto::getUuid)
       .containsExactlyInAnyOrder(organization.getUuid(), anotherOrganization.getUuid())
index fde5f1b5fd0dbf5cafc25da313604e5e528b6683..fbc82aa2e0f8780c0c47875342dc5a7c8fc29308 100644 (file)
@@ -51,14 +51,14 @@ public class OrganizationMemberDaoTest {
 
   @Test
   public void select() {
-    underTest.insert(dbSession, create("O1", 512));
+    underTest.insert(dbSession, create("O1", "512"));
 
-    Optional<OrganizationMemberDto> result = underTest.select(dbSession, "O1", 512);
+    Optional<OrganizationMemberDto> result = underTest.select(dbSession, "O1", "512");
 
     assertThat(result).isPresent();
-    assertThat(result.get()).extracting(OrganizationMemberDto::getOrganizationUuid, OrganizationMemberDto::getUserId).containsExactly("O1", 512);
-    assertThat(underTest.select(dbSession, "O1", 256)).isNotPresent();
-    assertThat(underTest.select(dbSession, "O2", 512)).isNotPresent();
+    assertThat(result.get()).extracting(OrganizationMemberDto::getOrganizationUuid, OrganizationMemberDto::getUserUuid).containsExactly("O1", "512");
+    assertThat(underTest.select(dbSession, "O1", "256")).isNotPresent();
+    assertThat(underTest.select(dbSession, "O2", "512")).isNotPresent();
   }
 
   @Test
@@ -78,32 +78,16 @@ public class OrganizationMemberDaoTest {
   }
 
   @Test
-  public void select_user_ids() {
-    OrganizationDto organization = db.organizations().insert();
-    OrganizationDto anotherOrganization = db.organizations().insert();
-    UserDto user = db.users().insertUser();
-    UserDto anotherUser = db.users().insertUser();
-    UserDto userInAnotherOrganization = db.users().insertUser();
-    db.organizations().addMember(organization, user);
-    db.organizations().addMember(organization, anotherUser);
-    db.organizations().addMember(anotherOrganization, userInAnotherOrganization);
-
-    List<Integer> result = underTest.selectUserIdsByOrganizationUuid(dbSession, organization.getUuid());
-
-    assertThat(result).containsOnly(user.getId(), anotherUser.getId());
-  }
-
-  @Test
-  public void select_organization_uuids_by_user_id() {
+  public void select_organization_uuids_by_user_uuid() {
     OrganizationDto organizationDto1 = db.organizations().insert();
     OrganizationDto organizationDto2 = db.organizations().insert();
     OrganizationDto organizationDto3 = db.organizations().insert();
-    underTest.insert(dbSession, create(organizationDto1.getUuid(), 512));
-    underTest.insert(dbSession, create(organizationDto2.getUuid(), 512));
+    underTest.insert(dbSession, create(organizationDto1.getUuid(), "512"));
+    underTest.insert(dbSession, create(organizationDto2.getUuid(), "512"));
 
-    assertThat(underTest.selectOrganizationUuidsByUser(dbSession, 512)).containsOnly(organizationDto1.getUuid(), organizationDto2.getUuid())
+    assertThat(underTest.selectOrganizationUuidsByUser(dbSession, "512")).containsOnly(organizationDto1.getUuid(), organizationDto2.getUuid())
       .doesNotContain(organizationDto3.getUuid());
-    assertThat(underTest.selectOrganizationUuidsByUser(dbSession, 123)).isEmpty();
+    assertThat(underTest.selectOrganizationUuidsByUser(dbSession, "123")).isEmpty();
   }
 
   @Test
@@ -140,22 +124,22 @@ public class OrganizationMemberDaoTest {
 
   @Test
   public void insert() {
-    underTest.insert(dbSession, create("O_1", 256));
+    underTest.insert(dbSession, create("O_1", "256"));
 
-    Map<String, Object> result = db.selectFirst(dbSession, "select organization_uuid as \"organizationUuid\", user_id as \"userId\" from organization_members");
+    Map<String, Object> result = db.selectFirst(dbSession, "select organization_uuid as \"organizationUuid\", user_uuid as \"userUuid\" from organization_members");
 
-    assertThat(result).containsOnly(entry("organizationUuid", "O_1"), entry("userId", 256L));
+    assertThat(result).containsOnly(entry("organizationUuid", "O_1"), entry("userUuid", "256"));
   }
 
   @Test
   public void fail_insert_if_no_organization_uuid() {
     expectedException.expect(PersistenceException.class);
 
-    underTest.insert(dbSession, create(null, 256));
+    underTest.insert(dbSession, create(null, "256"));
   }
 
   @Test
-  public void fail_insert_if_no_user_id() {
+  public void fail_insert_if_no_user_uuid() {
     expectedException.expect(PersistenceException.class);
 
     underTest.insert(dbSession, create("O_1", null));
@@ -163,42 +147,42 @@ public class OrganizationMemberDaoTest {
 
   @Test
   public void fail_if_organization_member_already_exist() {
-    underTest.insert(dbSession, create("O_1", 256));
+    underTest.insert(dbSession, create("O_1", "256"));
     expectedException.expect(PersistenceException.class);
 
-    underTest.insert(dbSession, create("O_1", 256));
+    underTest.insert(dbSession, create("O_1", "256"));
   }
 
   @Test
   public void delete_by_organization() {
-    underTest.insert(dbSession, create("O1", 512));
-    underTest.insert(dbSession, create("O1", 513));
-    underTest.insert(dbSession, create("O2", 512));
+    underTest.insert(dbSession, create("O1", "512"));
+    underTest.insert(dbSession, create("O1", "513"));
+    underTest.insert(dbSession, create("O2", "512"));
 
     underTest.deleteByOrganizationUuid(dbSession, "O1");
 
-    assertThat(underTest.select(dbSession, "O1", 512)).isNotPresent();
-    assertThat(underTest.select(dbSession, "O1", 513)).isNotPresent();
-    assertThat(underTest.select(dbSession, "O2", 512)).isPresent();
+    assertThat(underTest.select(dbSession, "O1", "512")).isNotPresent();
+    assertThat(underTest.select(dbSession, "O1", "513")).isNotPresent();
+    assertThat(underTest.select(dbSession, "O2", "512")).isPresent();
   }
 
   @Test
-  public void delete_by_user_id() {
-    underTest.insert(dbSession, create("O1", 512));
-    underTest.insert(dbSession, create("O1", 513));
-    underTest.insert(dbSession, create("O2", 512));
+  public void delete_by_user_uuid() {
+    underTest.insert(dbSession, create("O1", "512"));
+    underTest.insert(dbSession, create("O1", "513"));
+    underTest.insert(dbSession, create("O2", "512"));
 
-    underTest.deleteByUserId(dbSession, 512);
+    underTest.deleteByUserUuid(dbSession, "512");
     db.commit();
 
-    assertThat(db.select("select organization_uuid as \"organizationUuid\", user_id as \"userId\" from organization_members"))
-      .extracting((row) -> row.get("organizationUuid"), (row) -> row.get("userId"))
-      .containsOnly(tuple("O1", 513L));
+    assertThat(db.select("select organization_uuid as \"organizationUuid\", user_uuid as \"userUuid\" from organization_members"))
+      .extracting((row) -> row.get("organizationUuid"), (row) -> row.get("userUuid"))
+      .containsOnly(tuple("O1", "513"));
   }
 
-  private OrganizationMemberDto create(String organizationUuid, Integer userId) {
+  private OrganizationMemberDto create(String organizationUuid, String userUuid) {
     return new OrganizationMemberDto()
       .setOrganizationUuid(organizationUuid)
-      .setUserId(userId);
+      .setUserUuid(userUuid);
   }
 }
index cbc5b21aa76f9e763646079b2a5c07e45352cbda..84e0afdf5fd5671772c603214813dd3fd58848a6 100644 (file)
@@ -102,7 +102,8 @@ public class OrganizationDbTester {
 
   public void addMember(OrganizationDto organization, UserDto... users) {
     Arrays.stream(users)
-      .forEach(u -> db.getDbClient().organizationMemberDao().insert(db.getSession(), new OrganizationMemberDto().setOrganizationUuid(organization.getUuid()).setUserId(u.getId())));
+      .forEach(
+        u -> db.getDbClient().organizationMemberDao().insert(db.getSession(), new OrganizationMemberDto().setOrganizationUuid(organization.getUuid()).setUserUuid(u.getUuid())));
     db.commit();
   }
 
@@ -116,7 +117,7 @@ public class OrganizationDbTester {
   }
 
   public void assertUserIsMemberOfOrganization(OrganizationDto organization, UserDto user) {
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getId())).as("User is not member of the organization").isPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getUuid())).as("User is not member of the organization").isPresent();
     String defaultGroupUuid = db.getDbClient().organizationDao().getDefaultGroupUuid(db.getSession(), organization.getUuid()).get();
     assertThat(db.getDbClient().groupMembershipDao().selectGroups(
       db.getSession(),
@@ -128,7 +129,7 @@ public class OrganizationDbTester {
   }
 
   public void assertUserIsNotMemberOfOrganization(OrganizationDto organization, UserDto user) {
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getId())).as("User is still member of the organization")
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getUuid())).as("User is still member of the organization")
       .isNotPresent();
     assertThat(db.getDbClient().groupMembershipDao().countGroups(db.getSession(),
       GroupMembershipQuery.builder().membership(IN).organizationUuid(organization.getUuid()).build(),
index 561e7fc7a0e9cc2c620dbb5415365b66ce358656..52b3721a17be88cc212721d67b936e7ac2a3bb88 100644 (file)
@@ -267,6 +267,14 @@ import org.sonar.server.platform.db.migration.version.v83.users.fk.groupsusers.D
 import org.sonar.server.platform.db.migration.version.v83.users.fk.groupsusers.DropUserIdColumnOfGroupsUsersTable;
 import org.sonar.server.platform.db.migration.version.v83.users.fk.groupsusers.MakeGroupsUsersUserUuidColumnNotNullable;
 import org.sonar.server.platform.db.migration.version.v83.users.fk.groupsusers.PopulateGroupsUsersUserUuid;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.AddIndexOnUserUuidOfOrganizationMembersTable;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.AddUserUuidColumnToOrganizationMembers;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.DropIndexOnUserIdOfOrganizationMembersTable;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.DropUserIdColumnOfOrganizationMembersTable;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.MakeOrganizationMembersUserUuidColumnNotNullable;
+import org.sonar.server.platform.db.migration.version.v83.users.fk.organizationmembers.PopulateOrganizationMembersUserUuid;
 import org.sonar.server.platform.db.migration.version.v83.usertokens.AddPrimaryKeyOnUuidColumnOfUserTokensTable;
 import org.sonar.server.platform.db.migration.version.v83.usertokens.AddUuidColumnToUserTokens;
 import org.sonar.server.platform.db.migration.version.v83.usertokens.DropIdColumnOfUserTokensTable;
@@ -646,7 +654,14 @@ public class DbVersion83 implements DbVersion {
       .add(3641, "Add unique index on 'user_uuid', 'group_id' columns of 'GROUPS_USERS' table", AddUniqueIndexOnUserUuidAndGroupIdOfGroupsUsersTable.class)
       .add(3642, "Drop column on 'user_id' column of 'GROUPS_USERS' table", DropUserIdColumnOfGroupsUsersTable.class)
 
-
-    ;
+      // Migration of FK in ORGANIZATION_MEMBERS to USERS
+      .add(3643, "Add 'user_uuid' column on 'ORGANIZATION_MEMBERS' table", AddUserUuidColumnToOrganizationMembers.class)
+      .add(3644, "Populate 'user_uuid' for 'ORGANIZATION_MEMBERS'", PopulateOrganizationMembersUserUuid.class)
+      .add(3645, "Make 'user_uuid' not-null for 'ORGANIZATION_MEMBERS'", MakeOrganizationMembersUserUuidColumnNotNullable.class)
+      .add(3646, "Drop index on 'user_id' column of 'ORGANIZATION_MEMBERS' table", DropIndexOnUserIdOfOrganizationMembersTable.class)
+      .add(3647, "Add index on 'user_uuid' column of 'ORGANIZATION_MEMBERS' table", AddIndexOnUserUuidOfOrganizationMembersTable.class)
+      .add(3648, "Drop index on 'user_id', 'group_id' columns of 'ORGANIZATION_MEMBERS' table", DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable.class)
+      .add(3649, "Add PK on 'user_uuid', 'organization_uuid' columns of 'ORGANIZATION_MEMBERS' table", AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable.class)
+      .add(3650, "Drop column on 'user_id' column of 'ORGANIZATION_MEMBERS' table", DropUserIdColumnOfOrganizationMembersTable.class);
   }
 }
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTable.java
new file mode 100644 (file)
index 0000000..8a65be7
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddIndexOnUserUuidOfOrganizationMembersTable extends DdlChange {
+  private static final String TABLE_NAME = "organization_members";
+  private static final String INDEX_NAME = "org_members_user_uuid";
+
+  public AddIndexOnUserUuidOfOrganizationMembersTable(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    if (!indexExists()) {
+      context.execute(new CreateIndexBuilder()
+        .setUnique(false)
+        .setTable(TABLE_NAME)
+        .setName(INDEX_NAME)
+        .addColumn(newVarcharColumnDefBuilder()
+          .setColumnName("user_uuid")
+          .setLimit(UUID_SIZE)
+          .build())
+        .build());
+    }
+  }
+
+  private boolean indexExists() throws SQLException {
+    try (Connection connection = getDatabase().getDataSource().getConnection()) {
+      return DatabaseUtils.indexExists(TABLE_NAME, INDEX_NAME, connection);
+    }
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable.java
new file mode 100644 (file)
index 0000000..12a1112
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.AddPrimaryKeyBuilder;
+
+public class AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable extends DdlChange {
+
+  public AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddPrimaryKeyBuilder("organization_members", "user_uuid", "organization_uuid").build());
+  }
+
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembers.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembers.java
new file mode 100644 (file)
index 0000000..a459754
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddUserUuidColumnToOrganizationMembers extends DdlChange {
+  private static final String TABLE = "organization_members";
+
+  private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder()
+    .setColumnName("user_uuid")
+    .setIsNullable(true)
+    .setDefaultValue(null)
+    .setLimit(VarcharColumnDef.UUID_SIZE)
+    .build();
+
+  public AddUserUuidColumnToOrganizationMembers(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddColumnsBuilder(getDialect(), TABLE)
+      .addColumn(uuidColumnDefinition)
+      .build());
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTable.java
new file mode 100644 (file)
index 0000000..e19b5e6
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.sql.DropIndexBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIndexOnUserIdOfOrganizationMembersTable extends DdlChange {
+  private static final String TABLE_NAME = "organization_members";
+  private static final String INDEX_NAME = "ix_org_members_on_user_id";
+
+  public DropIndexOnUserIdOfOrganizationMembersTable(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    if (indexExists()) {
+      context.execute(new DropIndexBuilder(getDialect())
+        .setTable(TABLE_NAME)
+        .setName(INDEX_NAME)
+        .build());
+    }
+  }
+
+  private boolean indexExists() throws SQLException {
+    try (Connection connection = getDatabase().getDataSource().getConnection()) {
+      return DatabaseUtils.indexExists(TABLE_NAME, INDEX_NAME, connection);
+    }
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable.java
new file mode 100644 (file)
index 0000000..03e495c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
+
+public class DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable extends DdlChange {
+  private static final String TABLE_NAME = "organization_members";
+
+  private final DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator;
+
+  public DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable(Database db, DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator) {
+    super(db);
+    this.dropPrimaryKeySqlGenerator = dropPrimaryKeySqlGenerator;
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(dropPrimaryKeySqlGenerator.generate(TABLE_NAME, "user_id", false));
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTable.java
new file mode 100644 (file)
index 0000000..36f782f
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropUserIdColumnOfOrganizationMembersTable extends DdlChange {
+  public DropUserIdColumnOfOrganizationMembersTable(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new DropColumnsBuilder(getDialect(), "organization_members", "user_id").build());
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullable.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullable.java
new file mode 100644 (file)
index 0000000..42a622b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class MakeOrganizationMembersUserUuidColumnNotNullable extends DdlChange {
+  private static final String TABLE_NAME = "organization_members";
+  private static final VarcharColumnDef uuidColumnDefinition = newVarcharColumnDefBuilder()
+    .setColumnName("user_uuid")
+    .setIsNullable(false)
+    .setDefaultValue(null)
+    .setLimit(VarcharColumnDef.UUID_SIZE)
+    .build();
+
+  public MakeOrganizationMembersUserUuidColumnNotNullable(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AlterColumnsBuilder(getDialect(), TABLE_NAME)
+      .updateColumn(uuidColumnDefinition)
+      .build());
+  }
+}
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuid.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuid.java
new file mode 100644 (file)
index 0000000..ea8e0c3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.MassUpdate;
+
+public class PopulateOrganizationMembersUserUuid extends DataChange {
+
+  public PopulateOrganizationMembersUserUuid(Database db) {
+    super(db);
+  }
+
+  @Override
+  protected void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+
+    massUpdate.select("select om.user_id, om.organization_uuid, u.uuid " +
+      "from organization_members om " +
+      "join users u on om.user_id = u.id where om.user_uuid is null");
+
+    massUpdate.update("update organization_members set user_uuid = ? where organization_uuid = ? and user_id = ?");
+
+    massUpdate.execute((row, update, index) -> {
+      long userId = row.getLong(1);
+      String organizationUuid = row.getString(2);
+      String userUuid = row.getString(3);
+
+      update.setString(1, userUuid);
+      update.setString(2, organizationUuid);
+      update.setLong(3, userId);
+      return true;
+    });
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTableTest.java
new file mode 100644 (file)
index 0000000..300b8bd
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class AddIndexOnUserUuidOfOrganizationMembersTableTest {
+
+  private static final String TABLE_NAME = "organization_members";
+  private static final String INDEX_NAME = "org_members_user_uuid";
+
+  @Rule
+  public CoreDbTester dbTester = CoreDbTester.createForSchema(AddIndexOnUserUuidOfOrganizationMembersTableTest.class, "schema.sql");
+
+  DdlChange underTest = new AddIndexOnUserUuidOfOrganizationMembersTable(dbTester.database());
+
+  @Test
+  public void add_index() throws SQLException {
+    underTest.execute();
+    dbTester.assertIndex(TABLE_NAME, INDEX_NAME, "user_uuid");
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    underTest.execute();
+    dbTester.assertIndex(TABLE_NAME, INDEX_NAME, "user_uuid");
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest.java
new file mode 100644 (file)
index 0000000..4a57df0
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest {
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest.class, "schema.sql");
+
+  private DdlChange underTest = new AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTable(db.database());
+
+  @Test
+  public void execute() throws SQLException {
+    underTest.execute();
+
+    db.assertPrimaryKey("organization_members", "pk_organization_members", "user_uuid", "organization_uuid");
+  }
+
+  @Test
+  public void migration_is_not_re_entrant() throws SQLException {
+    underTest.execute();
+
+    assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembersTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembersTest.java
new file mode 100644 (file)
index 0000000..b3c3fea
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AddUserUuidColumnToOrganizationMembersTest {
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(AddUserUuidColumnToOrganizationMembersTest.class, "schema.sql");
+
+  private DdlChange underTest = new AddUserUuidColumnToOrganizationMembers(db.database());
+
+  @Before
+  public void setup() {
+    insertGroupUser(1L);
+    insertGroupUser(2L);
+    insertGroupUser(3L);
+  }
+
+  @Test
+  public void add_uuid_column() throws SQLException {
+    underTest.execute();
+
+    db.assertColumnDefinition("organization_members", "user_uuid", Types.VARCHAR, 40, true);
+
+    assertThat(db.countSql("select count(*) from organization_members"))
+      .isEqualTo(3);
+  }
+
+  private void insertGroupUser(Long id) {
+    db.executeInsert("organization_members",
+      "user_id", id,
+      "organization_uuid", "uuid-" + id);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTableTest.java
new file mode 100644 (file)
index 0000000..e227574
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIndexOnUserIdOfOrganizationMembersTableTest {
+
+  private static final String TABLE_NAME = "organization_members";
+  private static final String INDEX_NAME = "ix_org_members_on_user_id";
+
+  @Rule
+  public CoreDbTester dbTester = CoreDbTester.createForSchema(DropIndexOnUserIdOfOrganizationMembersTableTest.class, "schema.sql");
+
+  DdlChange underTest = new DropIndexOnUserIdOfOrganizationMembersTable(dbTester.database());
+
+  @Test
+  public void add_index() throws SQLException {
+    underTest.execute();
+    dbTester.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    underTest.execute();
+    dbTester.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME);
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest.java
new file mode 100644 (file)
index 0000000..a8fa3ad
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator;
+import org.sonar.server.platform.db.migration.version.v83.util.SqlHelper;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest {
+  private static final String TABLE_NAME = "organization_members";
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest.class, "schema.sql");
+
+  private DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator = new DropPrimaryKeySqlGenerator(db.database(), new SqlHelper(db.database()));
+
+  private DdlChange underTest = new DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTable(db.database(), dropPrimaryKeySqlGenerator);
+
+  @Test
+  public void execute() throws SQLException {
+    underTest.execute();
+
+    db.assertNoPrimaryKey(TABLE_NAME);
+  }
+
+  @Test
+  public void migration_is_not_re_entrant() throws SQLException {
+    underTest.execute();
+
+    assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTableTest.java
new file mode 100644 (file)
index 0000000..ffdedf2
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class DropUserIdColumnOfOrganizationMembersTableTest {
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(DropUserIdColumnOfOrganizationMembersTableTest.class, "schema.sql");
+
+  private DdlChange underTest = new DropUserIdColumnOfOrganizationMembersTable(db.database());
+
+  @Test
+  public void execute() throws SQLException {
+    underTest.execute();
+
+    db.assertColumnDoesNotExist("organization_members", "user_id");
+  }
+
+  @Test
+  public void migration_is_not_re_entrant() throws SQLException {
+    underTest.execute();
+
+    assertThatThrownBy(() -> underTest.execute()).isInstanceOf(IllegalStateException.class);
+  }
+
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullableTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullableTest.java
new file mode 100644 (file)
index 0000000..b435228
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+
+import static java.sql.Types.VARCHAR;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+
+public class MakeOrganizationMembersUserUuidColumnNotNullableTest {
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(MakeOrganizationMembersUserUuidColumnNotNullableTest.class, "schema.sql");
+
+  private MigrationStep underTest = new MakeOrganizationMembersUserUuidColumnNotNullable(db.database());
+
+  @Test
+  public void uuid_column_is_not_null() throws SQLException {
+    underTest.execute();
+
+    db.assertColumnDefinition("organization_members", "user_uuid", VARCHAR, UUID_SIZE, false);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuidTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuidTest.java
new file mode 100644 (file)
index 0000000..f94a3ba
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.platform.db.migration.version.v83.users.fk.organizationmembers;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.util.Uuids;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PopulateOrganizationMembersUserUuidTest {
+
+  @Rule
+  public CoreDbTester db = CoreDbTester.createForSchema(PopulateOrganizationMembersUserUuidTest.class, "schema.sql");
+
+  private DataChange underTest = new PopulateOrganizationMembersUserUuid(db.database());
+
+  @Test
+  public void populate_uuids() throws SQLException {
+    long userId_1 = 1L;
+    String userUuid_1 = "uuid-1";
+    insertUser(userId_1, userUuid_1);
+
+    long userId_2 = 2L;
+    String userUuid_2 = "uuid-2";
+    insertUser(userId_2, userUuid_2);
+
+    long userId_3 = 3L;
+    String userUuid_3 = "uuid-3";
+    insertUser(userId_3, userUuid_3);
+
+    long userId_4 = 4L;
+    String userUuid_4 = "uuid-4";
+    insertUser(userId_4, userUuid_4);
+
+    String organizationUuid_1 = Uuids.createFast();
+    insertOrganizationMember(userId_1, organizationUuid_1);
+    String organizationUuid_2 = Uuids.createFast();
+    insertOrganizationMember(userId_2, organizationUuid_2);
+    String organizationUuid_3 = Uuids.createFast();
+    insertOrganizationMember(userId_3, organizationUuid_3);
+    String organizationUuid_4 = Uuids.createFast();
+    insertOrganizationMember(userId_4, organizationUuid_4);
+    String organizationUuid_5 = Uuids.createFast();
+    insertOrganizationMember(userId_1, organizationUuid_5);
+
+    underTest.execute();
+
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_1, organizationUuid_1, userUuid_1);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_2, organizationUuid_2, userUuid_2);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_3, organizationUuid_3, userUuid_3);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_4, organizationUuid_4, userUuid_4);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_1, organizationUuid_5, userUuid_1);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    long userId_1 = 1L;
+    String userUuid_1 = "uuid-1";
+    insertUser(userId_1, userUuid_1);
+
+    long userId_2 = 2L;
+    String userUuid_2 = "uuid-2";
+    insertUser(userId_2, userUuid_2);
+
+    long userId_3 = 3L;
+    String userUuid_3 = "uuid-3";
+    insertUser(userId_3, userUuid_3);
+
+    long userId_4 = 4L;
+    String userUuid_4 = "uuid-4";
+    insertUser(userId_4, userUuid_4);
+
+    String organizationUuid_1 = Uuids.createFast();
+    insertOrganizationMember(userId_1, organizationUuid_1);
+    String organizationUuid_2 = Uuids.createFast();
+    insertOrganizationMember(userId_2, organizationUuid_2);
+    String organizationUuid_3 = Uuids.createFast();
+    insertOrganizationMember(userId_3, organizationUuid_3);
+
+    underTest.execute();
+
+    String organizationUuid_4 = Uuids.createFast();
+    insertOrganizationMember(userId_3, organizationUuid_4);
+
+    // re-entrant
+    underTest.execute();
+
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_1, organizationUuid_1, userUuid_1);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_2, organizationUuid_2, userUuid_2);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_3, organizationUuid_3, userUuid_3);
+    assertThatQProfileChangeRulesProfileUuidIsEqualTo(userId_3, organizationUuid_4, userUuid_3);
+  }
+
+  private void assertThatQProfileChangeRulesProfileUuidIsEqualTo(Long userId, String organizationUuid, String expectedUuid) {
+    assertThat(db.select(String.format("select user_uuid from organization_members where user_id = %d and organization_uuid = '%s'", userId, organizationUuid))
+      .stream()
+      .map(row -> row.get("USER_UUID"))
+      .findFirst())
+        .hasValue(expectedUuid);
+  }
+
+  private void insertOrganizationMember(Long userId, String organizationUuid) {
+    db.executeInsert("organization_members",
+      "user_id", userId,
+      "organization_uuid", organizationUuid);
+  }
+
+  private void insertUser(Long id, String uuid) {
+    db.executeInsert("users",
+      "id", id,
+      "uuid", uuid,
+      "login", "login" + id,
+      "external_login", "ex-login" + id,
+      "external_identity_provider", "ex-provider" + id,
+      "external_id", id + 1,
+      "is_root", false,
+      "onboarded", false);
+  }
+}
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddIndexOnUserUuidOfOrganizationMembersTableTest/schema.sql
new file mode 100644 (file)
index 0000000..20cd233
--- /dev/null
@@ -0,0 +1,7 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40) NOT NULL,
+);
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
+
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddPrimaryKeyOnUserUuidAndOrganizationUuidColumnsOfUserRolesTableTest/schema.sql
new file mode 100644 (file)
index 0000000..3fa7761
--- /dev/null
@@ -0,0 +1,7 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40) NOT NULL,
+);
+CREATE INDEX "ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_UUID");
+
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembersTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/AddUserUuidColumnToOrganizationMembersTest/schema.sql
new file mode 100644 (file)
index 0000000..1a0f1aa
--- /dev/null
@@ -0,0 +1,7 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL
+);
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
+CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_ID");
+
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropIndexOnUserIdOfOrganizationMembersTableTest/schema.sql
new file mode 100644 (file)
index 0000000..83a2394
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40) NOT NULL,
+);
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
+CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_ID");
+
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropPrimaryKeyOnUserIdAndOrganizationUuidOfOrganizationMembersTableTest/schema.sql
new file mode 100644 (file)
index 0000000..e72612d
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40) NOT NULL,
+);
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
+CREATE INDEX "ORG_MEMBERS_ON_USER_UUID" ON "ORGANIZATION_MEMBERS"("USER_UUID");
+
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/DropUserIdColumnOfOrganizationMembersTableTest/schema.sql
new file mode 100644 (file)
index 0000000..6f3084d
--- /dev/null
@@ -0,0 +1,7 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40) NOT NULL,
+);
+CREATE INDEX "ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_UUID");
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_UUID");
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullableTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/MakeOrganizationMembersUserUuidColumnNotNullableTest/schema.sql
new file mode 100644 (file)
index 0000000..5951c00
--- /dev/null
@@ -0,0 +1,8 @@
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40),
+);
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
+CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_ID");
+
diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuidTest/schema.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v83/users/fk/organizationmembers/PopulateOrganizationMembersUserUuidTest/schema.sql
new file mode 100644 (file)
index 0000000..3dbd7d9
--- /dev/null
@@ -0,0 +1,40 @@
+CREATE TABLE "USERS"(
+    "ID" INTEGER NOT NULL AUTO_INCREMENT (1,1),
+    "UUID" VARCHAR(255) NOT NULL,
+    "LOGIN" VARCHAR(255) NOT NULL,
+    "ORGANIZATION_UUID" VARCHAR(40),
+    "NAME" VARCHAR(200),
+    "EMAIL" VARCHAR(100),
+    "CRYPTED_PASSWORD" VARCHAR(100),
+    "SALT" VARCHAR(40),
+    "HASH_METHOD" VARCHAR(10),
+    "ACTIVE" BOOLEAN DEFAULT TRUE,
+    "SCM_ACCOUNTS" VARCHAR(4000),
+    "EXTERNAL_LOGIN" VARCHAR(255) NOT NULL,
+    "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100) NOT NULL,
+    "EXTERNAL_ID" VARCHAR(255) NOT NULL,
+    "IS_ROOT" BOOLEAN NOT NULL,
+    "USER_LOCAL" BOOLEAN,
+    "ONBOARDED" BOOLEAN NOT NULL,
+    "HOMEPAGE_TYPE" VARCHAR(40),
+    "HOMEPAGE_PARAMETER" VARCHAR(40),
+    "LAST_CONNECTION_DATE" BIGINT,
+    "CREATED_AT" BIGINT,
+    "UPDATED_AT" BIGINT
+);
+ALTER TABLE "USERS" ADD CONSTRAINT "PK_USERS" PRIMARY KEY("ID");
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS"("LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS"("UPDATED_AT");
+CREATE UNIQUE INDEX "USERS_UUID" ON "USERS"("UUID");
+CREATE UNIQUE INDEX "UNIQ_EXTERNAL_ID" ON "USERS"("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_ID");
+CREATE UNIQUE INDEX "UNIQ_EXTERNAL_LOGIN" ON "USERS"("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_LOGIN");
+
+
+CREATE TABLE "ORGANIZATION_MEMBERS"(
+    "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+    "USER_ID" INTEGER NOT NULL,
+    "USER_UUID" VARCHAR(40),
+);
+ALTER TABLE "ORGANIZATION_MEMBERS" ADD CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY("ORGANIZATION_UUID", "USER_ID");
+CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS"("USER_ID");
+
index 3d18c40e753548cb21fd1ad12546433c4244cbc5..00146988e9c4ca78206d5a58e32e99fbfd0f5f88 100644 (file)
@@ -101,7 +101,7 @@ public class UserIndexerTest {
     assertThat(docs)
       .extracting(UserDoc::uuid)
       .containsExactlyInAnyOrder(user.getUuid())
-    .doesNotContain(anotherUser.getUuid());
+      .doesNotContain(anotherUser.getUuid());
   }
 
   @Test
@@ -117,9 +117,14 @@ public class UserIndexerTest {
     underTest.commitAndIndex(db.getSession(), user);
 
     List<UserDoc> docs = es.getDocuments(TYPE_USER, UserDoc.class);
-    assertThat(docs)
-      .extracting(UserDoc::uuid, UserDoc::organizationUuids)
-      .containsExactlyInAnyOrder(tuple(user.getUuid(), asList(organization1.getUuid(), organization2.getUuid())));
+    assertThat(docs).hasSize(1);
+
+    UserDoc userDoc = docs.get(0);
+    assertThat(userDoc.uuid())
+      .isEqualTo(user.getUuid());
+
+    assertThat(userDoc.organizationUuids())
+      .containsExactlyInAnyOrder(organization1.getUuid(), organization2.getUuid());
   }
 
   @Test
index ec2441e8005daee6091291ac0549a4948edb74a4..2f953b354a5164d8ff8929543e5d2afabd1cf6ec 100644 (file)
@@ -61,10 +61,10 @@ public class MemberUpdater {
   }
 
   public void addMembers(DbSession dbSession, OrganizationDto organization, List<UserDto> users) {
-    Set<Integer> currentMemberIds = new HashSet<>(dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, organization.getUuid()));
+    Set<String> currentMemberUuids = new HashSet<>(dbClient.organizationMemberDao().selectUserUuidsByOrganizationUuid(dbSession, organization.getUuid()));
     List<UserDto> usersToAdd = users.stream()
       .filter(UserDto::isActive)
-      .filter(u -> !currentMemberIds.contains(u.getId()))
+      .filter(u -> !currentMemberUuids.contains(u.getUuid()))
       .collect(toList());
     if (usersToAdd.isEmpty()) {
       return;
@@ -76,7 +76,7 @@ public class MemberUpdater {
   private void addMemberInDb(DbSession dbSession, OrganizationDto organization, UserDto user) {
     dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto()
       .setOrganizationUuid(organization.getUuid())
-      .setUserId(user.getId()));
+      .setUserUuid(user.getUuid()));
     dbClient.userGroupDao().insert(dbSession,
       new UserGroupDto().setGroupUuid(defaultGroupFinder.findDefaultGroup(dbSession, organization.getUuid()).getUuid()).setUserUuid(user.getUuid()));
   }
@@ -86,10 +86,10 @@ public class MemberUpdater {
   }
 
   public void removeMembers(DbSession dbSession, OrganizationDto organization, List<UserDto> users) {
-    Set<Integer> currentMemberIds = new HashSet<>(dbClient.organizationMemberDao().selectUserIdsByOrganizationUuid(dbSession, organization.getUuid()));
+    Set<String> currentMemberIds = new HashSet<>(dbClient.organizationMemberDao().selectUserUuidsByOrganizationUuid(dbSession, organization.getUuid()));
     List<UserDto> usersToRemove = users.stream()
       .filter(UserDto::isActive)
-      .filter(u -> currentMemberIds.contains(u.getId()))
+      .filter(u -> currentMemberIds.contains(u.getUuid()))
       .collect(toList());
     if (usersToRemove.isEmpty()) {
       return;
@@ -108,7 +108,7 @@ public class MemberUpdater {
    * Please note that no commit will not be executed.
    */
   public void synchronizeUserOrganizationMembership(DbSession dbSession, UserDto user, ALM alm, Set<String> organizationAlmIds) {
-    Set<String> userOrganizationUuids = dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, user.getId());
+    Set<String> userOrganizationUuids = dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, user.getUuid());
     Set<String> userOrganizationUuidsWithMembersSyncEnabled = dbClient.organizationAlmBindingDao().selectByOrganizationUuids(dbSession, userOrganizationUuids).stream()
       .filter(OrganizationAlmBindingDto::isMembersSyncEnable)
       .map(OrganizationAlmBindingDto::getOrganizationUuid)
@@ -134,6 +134,7 @@ public class MemberUpdater {
 
   private void removeMemberInDb(DbSession dbSession, OrganizationDto organization, UserDto user) {
     int userId = user.getId();
+    String userUuid = user.getUuid();
     String organizationUuid = organization.getUuid();
     dbClient.userPermissionDao().deleteOrganizationMemberPermissions(dbSession, organizationUuid, userId);
     dbClient.permissionTemplateDao().deleteUserPermissionsByOrganization(dbSession, organizationUuid, userId);
@@ -142,7 +143,7 @@ public class MemberUpdater {
     dbClient.propertiesDao().deleteByOrganizationAndUser(dbSession, organizationUuid, userId);
     dbClient.propertiesDao().deleteByOrganizationAndMatchingLogin(dbSession, organizationUuid, user.getLogin(), singletonList(DEFAULT_ISSUE_ASSIGNEE));
 
-    dbClient.organizationMemberDao().delete(dbSession, organizationUuid, userId);
+    dbClient.organizationMemberDao().delete(dbSession, organizationUuid, userUuid);
   }
 
 }
index 899e672363488554a12a4b4b10144cfea867f054..d3e41a8bf143c4ac83ccc91821f7eab5f2c82e19 100644 (file)
@@ -96,7 +96,7 @@ public class OrganizationUpdaterImpl implements OrganizationUpdater {
     QualityGateDto builtInQualityGate = dbClient.qualityGateDao().selectBuiltIn(dbSession);
     OrganizationDto organization = insertOrganization(dbSession, newOrganization, builtInQualityGate);
     beforeCommit.accept(organization);
-    insertOrganizationMember(dbSession, organization, userCreator.getId());
+    insertOrganizationMember(dbSession, organization, userCreator.getUuid());
     dbClient.qualityGateDao().associate(dbSession, uuidFactory.create(), organization, builtInQualityGate);
     GroupDto ownerGroup = insertOwnersGroup(dbSession, organization);
     GroupDto defaultGroup = defaultGroupCreator.create(dbSession, organization.getUuid());
@@ -244,9 +244,9 @@ public class OrganizationUpdaterImpl implements OrganizationUpdater {
       new UserGroupDto().setGroupUuid(group.getUuid()).setUserUuid(createUserUuid));
   }
 
-  private void insertOrganizationMember(DbSession dbSession, OrganizationDto organizationDto, int userId) {
+  private void insertOrganizationMember(DbSession dbSession, OrganizationDto organizationDto, String userUuid) {
     dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto()
       .setOrganizationUuid(organizationDto.getUuid())
-      .setUserId(userId));
+      .setUserUuid(userUuid));
   }
 }
index 9488e63375702f120c630cc17a948ba5408710b5..7f15cc5d2ce626ff887efbe33b3ecb806514dfbf 100644 (file)
@@ -259,7 +259,7 @@ public class ServerUserSession extends AbstractUserSession {
       return true;
     }
     try (DbSession dbSession = dbClient.openSession(false)) {
-      Optional<OrganizationMemberDto> organizationMemberDto = dbClient.organizationMemberDao().select(dbSession, organizationUuid, requireNonNull(getUserId()));
+      Optional<OrganizationMemberDto> organizationMemberDto = dbClient.organizationMemberDao().select(dbSession, organizationUuid, requireNonNull(getUuid()));
       if (organizationMemberDto.isPresent()) {
         organizationMembership.add(organizationUuid);
       }
index 926115569f52d52061cdf54e57758de8ae8354aa..5836c58045841416abefb9daa058272b6ea5f117 100644 (file)
@@ -463,7 +463,7 @@ public class UserUpdater {
 
   private void addUserToDefaultOrganization(DbSession dbSession, UserDto userDto) {
     String defOrgUuid = defaultOrganizationProvider.get().getUuid();
-    dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto().setOrganizationUuid(defOrgUuid).setUserId(userDto.getId()));
+    dbClient.organizationMemberDao().insert(dbSession, new OrganizationMemberDto().setOrganizationUuid(defOrgUuid).setUserUuid(userDto.getUuid()));
   }
 
   private void addDefaultGroup(DbSession dbSession, UserDto userDto) {
index fd9fb8f9e6117bcb2446b3cde51633322661812b..d23302b3885c636e9223aec75b74d830c37a028e 100644 (file)
@@ -453,7 +453,7 @@ public class MemberUpdaterTest {
     underTest.synchronizeUserOrganizationMembership(db.getSession(), user, GITHUB, ImmutableSet.of("unknown"));
 
     // User is member of no organization
-    assertThat(db.getDbClient().organizationMemberDao().selectOrganizationUuidsByUser(db.getSession(), user.getId())).isEmpty();
+    assertThat(db.getDbClient().organizationMemberDao().selectOrganizationUuidsByUser(db.getSession(), user.getUuid())).isEmpty();
   }
 
   @Test
index e6523acd80b37407e1ae183a246876ea4b13d307..ba5dee147caa402f2b65d4886856f825b00ebdbf 100644 (file)
@@ -209,7 +209,7 @@ public class OrganizationUpdaterImplTest {
 
     OrganizationDto result = underTest.create(dbSession, user, FULL_POPULATED_NEW_ORGANIZATION, EMPTY_ORGANIZATION_CONSUMER);
 
-    assertThat(dbClient.organizationMemberDao().select(dbSession, result.getUuid(), user.getId())).isPresent();
+    assertThat(dbClient.organizationMemberDao().select(dbSession, result.getUuid(), user.getUuid())).isPresent();
     assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(result.getUuid()).setTextQuery(user.getLogin()).build(), new SearchOptions()).getTotal()).isEqualTo(1L);
   }
 
index 469a34ba93ec4b8e9712fdfadaba595a7e78be8c..2d3ccc502f08d4799b4e02834f75faf669bda438 100644 (file)
@@ -661,7 +661,7 @@ public class ServerUserSessionTest {
     assertThat(session.hasMembership(organization)).isTrue();
 
     // membership updated but not cache
-    db.getDbClient().organizationMemberDao().delete(db.getSession(), organization.getUuid(), user.getId());
+    db.getDbClient().organizationMemberDao().delete(db.getSession(), organization.getUuid(), user.getUuid());
     db.commit();
     assertThat(session.hasMembership(organization)).isTrue();
   }
index 4ab155ff85f15f4e698696fa54ef206f4cf67770..e8cb660b556abd5406976c26f6faaa68fccf1ced 100644 (file)
@@ -640,7 +640,7 @@ public class UserUpdaterCreateTest {
       .build(), u -> {
       });
 
-    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
+    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getUuid())).isPresent();
   }
 
   @Test
@@ -656,7 +656,7 @@ public class UserUpdaterCreateTest {
       .build(), u -> {
       });
 
-    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
+    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getUuid())).isNotPresent();
   }
 
   private GroupDto createDefaultGroup() {
index a5c44f0793ec8284d9ec085bf3d76a3f883923dd..efb63e9c00facc59d2294f65bbfe28bb744114fc 100644 (file)
@@ -266,7 +266,7 @@ public class UserUpdaterReactivateTest {
     UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder().setLogin(user.getLogin()).setName(user.getName()).build(), u -> {
     });
 
-    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isPresent();
+    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getUuid())).isPresent();
   }
 
   @Test
@@ -278,7 +278,7 @@ public class UserUpdaterReactivateTest {
     UserDto dto = underTest.reactivateAndCommit(db.getSession(), user, NewUser.builder().setLogin(user.getLogin()).setName(user.getName()).build(), u -> {
     });
 
-    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getId())).isNotPresent();
+    assertThat(dbClient.organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dto.getUuid())).isNotPresent();
   }
 
   @Test
index e55e4225c0640643df5926149f22934793e4665f..6b15e1e841307d8dd2e7fb052c29df6ed162bae1 100644 (file)
@@ -78,7 +78,7 @@ public class AssignAction extends Action {
       return Collections.emptySet();
     }
     try (DbSession dbSession = dbClient.openSession(false)) {
-      return dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, assignee.getId());
+      return dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, assignee.getUuid());
     }
   }
 
index 40a9ca5fd5bad1304ec5b75f80896291e56c86de..e76e823400a3ec8b83ea99682a4fe6bc9f2acb18 100644 (file)
@@ -139,7 +139,7 @@ public class AssignAction implements IssuesWsAction {
       .orElseThrow(() -> new IllegalStateException(format("Unknown project %s", projectUuid)));
     OrganizationDto organizationDto = dbClient.organizationDao().selectByUuid(dbSession, project.getOrganizationUuid())
       .orElseThrow(() -> new IllegalStateException(format("Unknown organizationMember %s", project.getOrganizationUuid())));
-    checkArgument(dbClient.organizationMemberDao().select(dbSession, organizationDto.getUuid(), user.getId()).isPresent(),
+    checkArgument(dbClient.organizationMemberDao().select(dbSession, organizationDto.getUuid(), user.getUuid()).isPresent(),
       "User '%s' is not member of organization '%s'", user.getLogin(), organizationDto.getKey());
   }
 }
index 3be0d99f653b97f23b8b6677b6fa4ea6f74c8180..0b96bb9d28a319389ed38269c68b974f1bc204ae 100644 (file)
@@ -196,7 +196,7 @@ public class SearchResponseLoader {
       .forEach(result::addOrganization);
 
     if (userSession.isLoggedIn()) {
-      result.setUserOrganizationUuids(dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, userSession.getUserId()));
+      result.setUserOrganizationUuids(dbClient.organizationMemberDao().selectOrganizationUuidsByUser(dbSession, userSession.getUuid()));
     }
   }
 
index 9ada004b885c9d7ec4d9a5e1b74e74e03a0d52a5..9afa8c32e83f06a034cfe661e1b1e6d237defa08 100644 (file)
@@ -195,8 +195,8 @@ public class SearchAction implements OrganizationsWsAction {
   }
 
   @CheckForNull
-  private Integer getUserIdIfFilterOnMembership(Request request) {
+  private String getUserIdIfFilterOnMembership(Request request) {
     boolean filterOnAuthenticatedUser = request.mandatoryParamAsBoolean(PARAM_MEMBER);
-    return (userSession.isLoggedIn() && filterOnAuthenticatedUser) ? userSession.getUserId() : null;
+    return (userSession.isLoggedIn() && filterOnAuthenticatedUser) ? userSession.getUuid() : null;
   }
 }
index c11bf0e8a87702369f734777464d0d8a39b9f49f..793e711885232e7ea9392ae1e8ee7de50cc22bc0 100644 (file)
@@ -106,7 +106,7 @@ public class PermissionWsSupport {
   }
 
   public void checkMembership(DbSession dbSession, OrganizationDto organization, UserId user) {
-    checkArgument(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId()).isPresent(),
+    checkArgument(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getUuid()).isPresent(),
       "User '%s' is not member of organization '%s'", user.getLogin(), organization.getKey());
   }
 }
index 16228970436cf81effa8f2ed2481885642616663..3a7251a388a2885daaab59e2ecca28f4684e31c4 100644 (file)
@@ -165,12 +165,12 @@ public class QProfileWsSupport {
   }
 
   private void checkMembership(DbSession dbSession, OrganizationDto organization, UserDto user) {
-    checkArgument(isMember(dbSession, organization, user.getId()),
+    checkArgument(isMember(dbSession, organization, user.getUuid()),
       "User '%s' is not member of organization '%s'", user.getLogin(), organization.getKey());
   }
 
-  private boolean isMember(DbSession dbSession, OrganizationDto organization, int userId) {
-    return dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), userId).isPresent();
+  private boolean isMember(DbSession dbSession, OrganizationDto organization, String userUuid) {
+    return dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), userUuid).isPresent();
   }
 
   private void checkMembershipOnPaidOrganization(OrganizationDto organization) {
index 470bd4dec315fc364cae85400540912dd3598fbe..f9cc9cdb5de90a6c3d73cc9f7835aa7096163972 100644 (file)
@@ -105,7 +105,7 @@ public class DeactivateAction implements UsersWsAction {
       dbClient.userPermissionDao().deleteByUserId(dbSession, userId);
       dbClient.permissionTemplateDao().deleteUserPermissionsByUserId(dbSession, userId);
       dbClient.qProfileEditUsersDao().deleteByUser(dbSession, user);
-      dbClient.organizationMemberDao().deleteByUserId(dbSession, userId);
+      dbClient.organizationMemberDao().deleteByUserUuid(dbSession, user.getUuid());
       dbClient.userPropertiesDao().deleteByUser(dbSession, user);
       dbClient.almPatDao().deleteByUser(dbSession, user);
       deactivateUser(dbSession, user);
index 5b6fc589ef68f061a96dd1ecca2691088aee61ab..045d18127951e829752738e79aa6219b78c23dc1 100644 (file)
@@ -99,7 +99,7 @@ public class AddUserAction implements UserGroupsWsAction {
   }
 
   private void checkMembership(DbSession dbSession, OrganizationDto organization, UserDto user) {
-    checkArgument(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId()).isPresent(),
+    checkArgument(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getUuid()).isPresent(),
       "User '%s' is not member of organization '%s'", user.getLogin(), organization.getKey());
   }
 }
index 04ea22f6611ec89d5e0c202c651acbb4d6c9f3cb..ca4c8e8d60be83c5e593099dfb7f8957203c789e 100644 (file)
@@ -267,7 +267,7 @@ public class AddMemberActionTest {
   }
 
   private void assertMember(String organizationUuid, UserDto user) {
-    assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getId())).isPresent();
+    assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getUuid())).isPresent();
     String defaultGroupUuid = dbClient.organizationDao().getDefaultGroupUuid(dbSession, organizationUuid).get();
     assertThat(db.getDbClient().groupMembershipDao().selectGroups(db.getSession(), GroupMembershipQuery.builder()
       .membership(IN)
index b98c8208bc8264ad46a6f19223cf4a144f25d05c..9d8e0b24b7d4f47de8b446fd3d44854cae3a566c 100644 (file)
@@ -238,7 +238,7 @@ public class CreateActionTest {
     executeRequest("foo", "bar");
 
     OrganizationDto organization = dbClient.organizationDao().selectByKey(dbSession, "bar").get();
-    assertThat(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getId())).isPresent();
+    assertThat(dbClient.organizationMemberDao().select(dbSession, organization.getUuid(), user.getUuid())).isPresent();
     assertThat(es.client().prepareSearch(TYPE_USER)
       .setQuery(boolQuery()
         .must(termQuery(FIELD_ORGANIZATION_UUIDS, organization.getUuid()))
index a5a80e6f2c42463994871ee4af2d0ee0905fe163..2fbd4ab3eaf718e1d40736d8ad85396dbddd7187 100644 (file)
@@ -438,9 +438,9 @@ public class DeleteActionTest {
     sendRequest(org);
 
     verifyOrganizationDoesNotExist(org);
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user1.getId())).isNotPresent();
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user2.getId())).isNotPresent();
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), otherOrg.getUuid(), user1.getId())).isPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user1.getUuid())).isNotPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user2.getUuid())).isNotPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), otherOrg.getUuid(), user1.getUuid())).isPresent();
     assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(org.getUuid()).build(), new SearchOptions()).getTotal()).isEqualTo(0);
     assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(otherOrg.getUuid()).build(), new SearchOptions()).getTotal()).isEqualTo(1);
     verify(projectLifeCycleListeners).onProjectsDeleted(emptySet());
index 90d5e1d91760c69386833409e1efbc992d756b26..438b442538c87716de7629998e5eee8f1ee64949 100644 (file)
@@ -269,9 +269,9 @@ public class OrganizationDeleterTest {
     underTest.delete(dbSession, org);
 
     verifyOrganizationDoesNotExist(org);
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user1.getId())).isNotPresent();
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user2.getId())).isNotPresent();
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), otherOrg.getUuid(), user1.getId())).isPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user1.getUuid())).isNotPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), org.getUuid(), user2.getUuid())).isNotPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), otherOrg.getUuid(), user1.getUuid())).isPresent();
     assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(org.getUuid()).build(), new SearchOptions()).getTotal()).isEqualTo(0);
     assertThat(userIndex.search(UserQuery.builder().setOrganizationUuid(otherOrg.getUuid()).build(), new SearchOptions()).getTotal()).isEqualTo(1);
     verify(projectLifeCycleListeners).onProjectsDeleted(emptySet());
index e67bc0bafd9f4d2c7ee5f2ddcb18ff5a4aef47f9..842f1298640567a50a52a2441404ec97d0eebb2a 100644 (file)
@@ -263,11 +263,11 @@ public class RemoveMemberActionTest {
   }
 
   private void assertNotAMember(String organizationUuid, UserDto user) {
-    assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getId())).isNotPresent();
+    assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getUuid())).isNotPresent();
   }
 
   private void assertMember(String organizationUuid, UserDto user) {
-    assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getId())).isPresent();
+    assertThat(dbClient.organizationMemberDao().select(dbSession, organizationUuid, user.getUuid())).isPresent();
     assertThat(userIndex.search(UserQuery.builder()
       .setOrganizationUuid(organizationUuid)
       .setTextQuery(user.getLogin())
index c0e91ea4469096153212044bcd4c1f534c115868..c0c1cd2bce2578c18a02d770f4be0041a96834b9 100644 (file)
@@ -142,7 +142,7 @@ public class CreateActionTest {
 
     Optional<UserDto> dbUser = db.users().selectUserByLogin("john");
     assertThat(dbUser).isPresent();
-    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dbUser.get().getId())).isPresent();
+    assertThat(db.getDbClient().organizationMemberDao().select(db.getSession(), defaultOrganizationProvider.get().getUuid(), dbUser.get().getUuid())).isPresent();
   }
 
   @Test
index ae2c918676690d0dbd36b691e873372228261564..fbe72ca205436a9090310a9e98f390e01068edc1 100644 (file)
@@ -223,8 +223,8 @@ public class DeactivateActionTest {
 
     deactivate(user.getLogin());
 
-    assertThat(dbClient.organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getId())).isNotPresent();
-    assertThat(dbClient.organizationMemberDao().select(db.getSession(), anotherOrganization.getUuid(), user.getId())).isNotPresent();
+    assertThat(dbClient.organizationMemberDao().select(db.getSession(), organization.getUuid(), user.getUuid())).isNotPresent();
+    assertThat(dbClient.organizationMemberDao().select(db.getSession(), anotherOrganization.getUuid(), user.getUuid())).isNotPresent();
   }
 
   @Test