Repository: gravitee-io/graviteeio-access-management
Pull request #702 (2020-01-14 21:47:01)

Revert "feat(acl): assign owner to application and security domain"
Reverts gravitee-io/graviteeio-access-management#698


Patch:
diff --git a/gravitee-am-management-api/gravitee-am-management-api-handlers/gravitee-am-management-api-handlers-management/src/main/java/io/gravitee/am/management/handlers/management/api/manager/membership/impl/MembershipManagerImpl.java b/gravitee-am-management-api/gravitee-am-management-api-handlers/gravitee-am-management-api-handlers-management/src/main/java/io/gravitee/am/management/handlers/management/api/manager/membership/impl/MembershipManagerImpl.java
index 728d15e38d..46d69838ca 100644
--- a/gravitee-am-management-api/gravitee-am-management-api-handlers/gravitee-am-management-api-handlers-management/src/main/java/io/gravitee/am/management/handlers/management/api/manager/membership/impl/MembershipManagerImpl.java
+++ b/gravitee-am-management-api/gravitee-am-management-api-handlers/gravitee-am-management-api-handlers-management/src/main/java/io/gravitee/am/management/handlers/management/api/manager/membership/impl/MembershipManagerImpl.java
@@ -42,6 +42,7 @@ public class MembershipManagerImpl implements MembershipManager, InitializingBea
 
     private static final Logger logger = LoggerFactory.getLogger(MembershipManagerImpl.class);
     private ConcurrentMap<String, Membership> memberships = new ConcurrentHashMap<>();
+    private ConcurrentMap<String, List<Membership>> localMemberships = new ConcurrentHashMap<>();
 
     @Autowired
     private MembershipService membershipService;
@@ -77,9 +78,26 @@ public class MembershipManagerImpl implements MembershipManager, InitializingBea
 
     @Override
     public List<Membership> findByReference(String referenceId, ReferenceType referenceType) {
-        return memberships.values().stream()
+        List<Membership> membershipList = memberships.values().stream()
                 .filter(membership -> membership.getReferenceId().equals(referenceId) && membership.getReferenceType().equals(referenceType))
                 .collect(Collectors.toList());
+
+        // membership list can be empty if the resource (Domain or Application) has just been created
+        // and the propagation process has not been done yet, retry to be sure
+        if (membershipList == null || membershipList.isEmpty()) {
+            if (localMemberships.containsKey(referenceId + referenceType.name())) {
+                return localMemberships.get(referenceId + referenceType.name());
+            } else {
+                try {
+                    List<Membership> repoMemberships = membershipService.findByReference(referenceId, referenceType).blockingGet();
+                    localMemberships.put(referenceId + referenceType.name(), repoMemberships);
+                    return repoMemberships;
+                } catch (Exception ex) {
+                    logger.error("An error occurs while finding memberships by reference {} - {}", referenceId, referenceType, ex);
+                }
+            }
+        }
+        return membershipList;
     }
 
     private void updateMembership(String membershipId, MembershipEvent membershipEvent) {
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/RoleService.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/RoleService.java
index 45e0d37472..b594cd9f7c 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/RoleService.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/RoleService.java
@@ -38,6 +38,8 @@ public interface RoleService {
 
     Maybe<Role> findById(String id);
 
+    Maybe<Role> findSystemRole(SystemRole systemRole, RoleScope roleScope);
+
     Single<Set<Role>> findByIdIn(List<String> ids);
 
     Single<Role> createSystemRole(SystemRole systemRole, RoleScope roleScope, List<String> permissions, User principal);
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/ApplicationServiceImpl.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/ApplicationServiceImpl.java
index d44b517a68..956ef51c52 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/ApplicationServiceImpl.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/ApplicationServiceImpl.java
@@ -25,11 +25,16 @@ import io.gravitee.am.common.web.UriBuilder;
 import io.gravitee.am.identityprovider.api.User;
 import io.gravitee.am.model.Application;
 import io.gravitee.am.model.IdentityProvider;
+import io.gravitee.am.model.Membership;
 import io.gravitee.am.model.application.ApplicationOAuthSettings;
 import io.gravitee.am.model.application.ApplicationSettings;
 import io.gravitee.am.model.common.Page;
 import io.gravitee.am.model.common.event.Event;
 import io.gravitee.am.model.common.event.Payload;
+import io.gravitee.am.model.membership.MemberType;
+import io.gravitee.am.model.membership.ReferenceType;
+import io.gravitee.am.model.permissions.RoleScope;
+import io.gravitee.am.model.permissions.SystemRole;
 import io.gravitee.am.repository.management.api.ApplicationRepository;
 import io.gravitee.am.service.*;
 import io.gravitee.am.service.exception.*;
@@ -93,6 +98,12 @@ public class ApplicationServiceImpl implements ApplicationService {
     @Autowired
     private IdentityProviderService identityProviderService;
 
+    @Autowired
+    private RoleService roleService;
+
+    @Autowired
+    private MembershipService membershipService;
+
     @Override
     public Single<Page<Application>> findAll(int page, int size) {
         LOGGER.debug("Find applications");
@@ -324,6 +335,13 @@ public class ApplicationServiceImpl implements ApplicationService {
                                         return Completable.concat(deleteFormsCompletable);
                                     })
                             )
+                            // delete memberships
+                            .andThen(membershipService.findByReference(application.getId(), ReferenceType.APPLICATION)
+                                    .flatMapCompletable(memberships -> {
+                                        List<Completable> deleteFormsCompletable = memberships.stream().map(m -> membershipService.delete(m.getId())).collect(Collectors.toList());
+                                        return Completable.concat(deleteFormsCompletable);
+                                    })
+                            )
                             .doOnComplete(() -> auditService.report(AuditBuilder.builder(ApplicationAuditBuilder.class).principal(principal).type(EventType.APPLICATION_DELETED).application(application)))
                             .doOnError(throwable -> auditService.report(AuditBuilder.builder(ApplicationAuditBuilder.class).principal(principal).type(EventType.APPLICATION_DELETED).throwable(throwable)));
                 })
@@ -419,6 +437,25 @@ public class ApplicationServiceImpl implements ApplicationService {
                 .andThen(validateApplicationMetadata(application))
                 // create the application
                 .flatMap(applicationRepository::create)
+                // create the owner
+                .flatMap(application1 -> {
+                    if (principal == null) {
+                        return Single.just(application1);
+                    }
+                    return roleService.findSystemRole(SystemRole.PRIMARY_OWNER, RoleScope.APPLICATION)
+                            .switchIfEmpty(Single.error(new InvalidRoleException("Cannot assign owner to the application, owner role does not exist")))
+                            .flatMap(role -> {
+                                Membership membership = new Membership();
+                                membership.setDomain(application1.getDomain());
+                                membership.setMemberId(principal.getId());
+                                membership.setMemberType(MemberType.USER);
+                                membership.setReferenceId(application1.getId());
+                                membership.setReferenceType(ReferenceType.APPLICATION);
+                                membership.setRole(role.getId());
+                                return membershipService.addOrUpdate(membership)
+                                        .map(__ -> domain);
+                            });
+                })
                 // create event for sync process
                 .flatMap(application1 -> {
                     Event event = new Event(Type.APPLICATION, new Payload(application.getId(), application.getDomain(), Action.CREATE));
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/DomainServiceImpl.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/DomainServiceImpl.java
index 97f396ce93..05f52bfe11 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/DomainServiceImpl.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/DomainServiceImpl.java
@@ -16,13 +16,18 @@
 package io.gravitee.am.service.impl;
 
 import io.gravitee.am.common.audit.EventType;
+import io.gravitee.am.common.event.Action;
+import io.gravitee.am.common.event.Type;
 import io.gravitee.am.identityprovider.api.User;
 import io.gravitee.am.model.Domain;
-import io.gravitee.am.common.event.Action;
+import io.gravitee.am.model.Membership;
 import io.gravitee.am.model.common.event.Event;
 import io.gravitee.am.model.common.event.Payload;
-import io.gravitee.am.common.event.Type;
+import io.gravitee.am.model.membership.MemberType;
+import io.gravitee.am.model.membership.ReferenceType;
 import io.gravitee.am.model.oidc.OIDCSettings;
+import io.gravitee.am.model.permissions.RoleScope;
+import io.gravitee.am.model.permissions.SystemRole;
 import io.gravitee.am.repository.management.api.DomainRepository;
 import io.gravitee.am.service.*;
 import io.gravitee.am.service.exception.*;
@@ -104,6 +109,9 @@ public class DomainServiceImpl implements DomainService {
     @Autowired
     private EventService eventService;
 
+    @Autowired
+    private MembershipService membershipService;
+
     @Override
     public Maybe<Domain> findById(String id) {
         LOGGER.debug("Find domain by ID: {}", id);
@@ -168,8 +176,29 @@ public class DomainServiceImpl implements DomainService {
                         return domainRepository.create(domain);
                     }
                 })
+                // create default system scopes
                 .flatMap(this::createSystemScopes)
+                // create default certificate
                 .flatMap(this::createDefaultCertificate)
+                // create owner
+                .flatMap(domain -> {
+                    if (principal == null) {
+                        return Single.just(domain);
+                    }
+                    return roleService.findSystemRole(SystemRole.PRIMARY_OWNER, RoleScope.DOMAIN)
+                            .switchIfEmpty(Single.error(new InvalidRoleException("Cannot assign owner to the domain, owner role does not exist")))
+                            .flatMap(role -> {
+                                Membership membership = new Membership();
+                                membership.setDomain(domain.getId());
+                                membership.setMemberId(principal.getId());
+                                membership.setMemberType(MemberType.USER);
+                                membership.setReferenceId(domain.getId());
+                                membership.setReferenceType(ReferenceType.DOMAIN);
+                                membership.setRole(role.getId());
+                                return membershipService.addOrUpdate(membership)
+                                        .map(__ -> domain);
+                            });
+                })
                 // create event for sync process
                 .flatMap(domain -> {
                     Event event = new Event(Type.DOMAIN, new Payload(domain.getId(), domain.getId(), Action.CREATE));
@@ -391,8 +420,15 @@ public class DomainServiceImpl implements DomainService {
                             // delete policies
                             .andThen(policyService.findByDomain(domainId)
                                     .flatMapCompletable(policies -> {
-                                        List<Completable> deleteReportersCompletable = policies.stream().map(p -> policyService.delete(p.getId())).collect(Collectors.toList());
-                                        return Completable.concat(deleteReportersCompletable);
+                                        List<Completable> deletePoliciesCompletable = policies.stream().map(p -> policyService.delete(p.getId())).collect(Collectors.toList());
+                                        return Completable.concat(deletePoliciesCompletable);
+                                    })
+                            )
+                            // delete memberships
+                            .andThen(membershipService.findByReference(domainId, ReferenceType.DOMAIN)
+                                    .flatMapCompletable(memberships -> {
+                                        List<Completable> deleteMembershipsCompletable = memberships.stream().map(m -> membershipService.delete(m.getId())).collect(Collectors.toList());
+                                        return Completable.concat(deleteMembershipsCompletable);
                                     })
                             )
                             .andThen(domainRepository.delete(domainId))
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/RoleServiceImpl.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/RoleServiceImpl.java
index 276f9b04d6..e5bb10c0e0 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/RoleServiceImpl.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/impl/RoleServiceImpl.java
@@ -86,6 +86,17 @@ public class RoleServiceImpl implements RoleService {
                 });
     }
 
+    @Override
+    public Maybe<Role> findSystemRole(SystemRole systemRole, RoleScope roleScope) {
+        LOGGER.debug("Find system role : {} for the scope : {}", systemRole.name(), roleScope.name());
+        return roleRepository.findByDomainAndNameAndScope("admin", systemRole.name(), roleScope.getId())
+                .onErrorResumeNext(ex -> {
+                    LOGGER.error("An error occurs while trying to find system role : {} for the scope : {}", systemRole.name(), roleScope.name(), ex);
+                    return Maybe.error(new TechnicalManagementException(
+                            String.format("An error occurs while trying to find system role : %s for the scope : %s", systemRole.name(), roleScope.name()), ex));
+                });
+    }
+
     @Override
     public Single<Set<Role>> findByIdIn(List<String> ids) {
         LOGGER.debug("Find roles by ids: {}", ids);
diff --git a/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.html b/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.html
index a13782eb73..5c40b49304 100644
--- a/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.html
+++ b/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.html
@@ -69,18 +69,19 @@
       </ngx-datatable-column>
       <ngx-datatable-column name="Role" [flexGrow]="2" [cellClass]="'membership-name-cell'">
         <ng-template let-row="row" ngx-datatable-cell-template>
-          <mat-form-field>
+          <mat-form-field *ngIf="!isPrimaryOwner(row)">
             <mat-select name="memberUserRole" [value]="row.role" (selectionChange)="update(row.memberId, row.memberType, $event)" [disabled]="!editMode">
               <mat-option *ngFor="let role of roles" [value]="role.id">
                 <span>{{ role.name }}</span>
               </mat-option>
             </mat-select>
           </mat-form-field>
+          <p class="primary-owner-membership" *ngIf="isPrimaryOwner(row)">{{row.roleName}}</p>
         </ng-template>
       </ngx-datatable-column>
       <ngx-datatable-column name="" [flexGrow]="1">
         <ng-template let-row="row" ngx-datatable-cell-template>
-          <div fxLayout="row" class="members-actions" *ngIf="deleteMode">
+          <div fxLayout="row" class="members-actions" *ngIf="deleteMode && !isPrimaryOwner(row)">
             <button mat-icon-button (click)="delete(row.id, $event)"><mat-icon matTooltip="Delete">clear</mat-icon></button>
           </div>
         </ng-template>
diff --git a/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.scss b/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.scss
index 79ca14d96b..149ee8622b 100644
--- a/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.scss
+++ b/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.scss
@@ -8,6 +8,11 @@
     box-shadow: none;
     background: transparent;
     font-size: 14px;
+    p.primary-owner-membership {
+      margin-top: 1.2em;
+      font-size: 85%;
+      font-weight: bold;
+    }
     .membership-header {
       margin: 5px;
       align-items: center;
diff --git a/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.ts b/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.ts
index 93d5af6a00..a219cab70b 100644
--- a/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.ts
+++ b/gravitee-am-ui/src/app/domain/components/memberships/memberships.component.ts
@@ -132,6 +132,10 @@ export class MembershipsComponent implements OnInit, OnChanges {
       });
   }
 
+  isPrimaryOwner(membership) {
+    return membership.roleName && 'PRIMARY_OWNER' === membership.roleName;
+  }
+
   private initMembers() {
     const memberships = this.members.memberships;
     const metadata = this.members.metadata;


Test patch:
diff --git a/gravitee-am-service/src/test/java/io/gravitee/am/service/ApplicationServiceTest.java b/gravitee-am-service/src/test/java/io/gravitee/am/service/ApplicationServiceTest.java
index f8447be89d..9237985849 100644
--- a/gravitee-am-service/src/test/java/io/gravitee/am/service/ApplicationServiceTest.java
+++ b/gravitee-am-service/src/test/java/io/gravitee/am/service/ApplicationServiceTest.java
@@ -16,12 +16,16 @@
 package io.gravitee.am.service;
 
 import io.gravitee.am.common.oauth2.GrantType;
+import io.gravitee.am.identityprovider.api.DefaultUser;
 import io.gravitee.am.model.*;
 import io.gravitee.am.model.application.ApplicationOAuthSettings;
 import io.gravitee.am.model.application.ApplicationSettings;
 import io.gravitee.am.model.application.ApplicationType;
 import io.gravitee.am.model.common.Page;
 import io.gravitee.am.model.common.event.Event;
+import io.gravitee.am.model.membership.ReferenceType;
+import io.gravitee.am.model.permissions.RoleScope;
+import io.gravitee.am.model.permissions.SystemRole;
 import io.gravitee.am.repository.exceptions.TechnicalException;
 import io.gravitee.am.repository.management.api.ApplicationRepository;
 import io.gravitee.am.service.exception.*;
@@ -46,7 +50,6 @@ import org.mockito.junit.MockitoJUnitRunner;
 import java.util.*;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.*;
 
 /**
@@ -86,6 +89,12 @@ public class ApplicationServiceTest {
     @Mock
     private AuditService auditService;
 
+    @Mock
+    private MembershipService membershipService;
+
+    @Mock
+    private RoleService roleService;
+
     private final static String DOMAIN = "domain1";
 
     @Test
@@ -366,8 +375,10 @@ public class ApplicationServiceTest {
             mock.getSettings().getOauth().setGrantTypes(Collections.singletonList(GrantType.CLIENT_CREDENTIALS));
             return mock;
         }).when(applicationTemplateManager).apply(any());
+        when(membershipService.addOrUpdate(any())).thenReturn(Single.just(new Membership()));
+        when(roleService.findSystemRole(SystemRole.PRIMARY_OWNER, RoleScope.APPLICATION)).thenReturn(Maybe.just(new Role()));
 
-        TestObserver testObserver = applicationService.create(DOMAIN, newClient).test();
+        TestObserver testObserver = applicationService.create(DOMAIN, newClient, new DefaultUser("username")).test();
         testObserver.awaitTerminalEvent();
 
         testObserver.assertComplete();
@@ -375,6 +386,7 @@ public class ApplicationServiceTest {
 
         verify(applicationRepository, times(1)).findByDomainAndClientId(DOMAIN, null);
         verify(applicationRepository, times(1)).create(any(Application.class));
+        verify(membershipService).addOrUpdate(any());
     }
 
     @Test
@@ -777,28 +789,32 @@ public class ApplicationServiceTest {
         Application existingClient = Mockito.mock(Application.class);
         when(existingClient.getId()).thenReturn("my-client");
         when(existingClient.getDomain()).thenReturn("my-domain");
-        when(applicationRepository.findById("my-client")).thenReturn(Maybe.just(existingClient));
-        when(applicationRepository.delete("my-client")).thenReturn(Completable.complete());
+        when(applicationRepository.findById(existingClient.getId())).thenReturn(Maybe.just(existingClient));
+        when(applicationRepository.delete(existingClient.getId())).thenReturn(Completable.complete());
         when(eventService.create(any())).thenReturn(Single.just(new Event()));
         Form form = new Form();
         form.setId("form-id");
-        when(formService.findByDomainAndClient("my-domain", "my-client")).thenReturn(Single.just(Collections.singletonList(form)));
+        when(formService.findByDomainAndClient(existingClient.getDomain(), existingClient.getId())).thenReturn(Single.just(Collections.singletonList(form)));
         when(formService.delete(form.getId())).thenReturn(Completable.complete());
         Email email = new Email();
         email.setId("email-id");
-        when(emailTemplateService.findByDomainAndClient("my-domain", "my-client"))
-                .thenReturn(Single.just(Collections.singletonList(email)));
+        when(emailTemplateService.findByDomainAndClient(existingClient.getDomain(), existingClient.getId())).thenReturn(Single.just(Collections.singletonList(email)));
         when(emailTemplateService.delete(email.getId())).thenReturn(Completable.complete());
+        Membership membership = new Membership();
+        membership.setId("membership-id");
+        when(membershipService.findByReference(existingClient.getId(), ReferenceType.APPLICATION)).thenReturn(Single.just(Collections.singletonList(membership)));
+        when(membershipService.delete(anyString())).thenReturn(Completable.complete());
 
-        TestObserver testObserver = applicationService.delete("my-client").test();
+        TestObserver testObserver = applicationService.delete(existingClient.getId()).test();
         testObserver.awaitTerminalEvent();
 
         testObserver.assertComplete();
         testObserver.assertNoErrors();
 
-        verify(applicationRepository, times(1)).delete("my-client");
+        verify(applicationRepository, times(1)).delete(existingClient.getId());
         verify(formService, times(1)).delete(anyString());
         verify(emailTemplateService, times(1)).delete(anyString());
+        verify(membershipService, times(1)).delete(anyString());
     }
 
     @Test
@@ -806,21 +822,23 @@ public class ApplicationServiceTest {
         Application existingClient = Mockito.mock(Application.class);
         when(existingClient.getDomain()).thenReturn("my-domain");
         when(existingClient.getId()).thenReturn("my-client");
-        when(applicationRepository.findById("my-client")).thenReturn(Maybe.just(existingClient));
-        when(applicationRepository.delete("my-client")).thenReturn(Completable.complete());
+        when(applicationRepository.findById(existingClient.getId())).thenReturn(Maybe.just(existingClient));
+        when(applicationRepository.delete(existingClient.getId())).thenReturn(Completable.complete());
         when(eventService.create(any())).thenReturn(Single.just(new Event()));
-        when(formService.findByDomainAndClient("my-domain", "my-client")).thenReturn(Single.just(Collections.emptyList()));
-        when(emailTemplateService.findByDomainAndClient("my-domain", "my-client")).thenReturn(Single.just(Collections.emptyList()));
+        when(formService.findByDomainAndClient(existingClient.getDomain(), existingClient.getId())).thenReturn(Single.just(Collections.emptyList()));
+        when(emailTemplateService.findByDomainAndClient(existingClient.getDomain(), existingClient.getId())).thenReturn(Single.just(Collections.emptyList()));
+        when(membershipService.findByReference(existingClient.getId(), ReferenceType.APPLICATION)).thenReturn(Single.just(Collections.emptyList()));
 
-        TestObserver testObserver = applicationService.delete("my-client").test();
+        TestObserver testObserver = applicationService.delete(existingClient.getId()).test();
         testObserver.awaitTerminalEvent();
 
         testObserver.assertComplete();
         testObserver.assertNoErrors();
 
-        verify(applicationRepository, times(1)).delete("my-client");
+        verify(applicationRepository, times(1)).delete(existingClient.getId());
         verify(formService, never()).delete(anyString());
         verify(emailTemplateService, never()).delete(anyString());
+        verify(membershipService, never()).delete(anyString());
     }
 
     @Test
diff --git a/gravitee-am-service/src/test/java/io/gravitee/am/service/DomainServiceTest.java b/gravitee-am-service/src/test/java/io/gravitee/am/service/DomainServiceTest.java
index e6fdc8f7a4..194565350f 100644
--- a/gravitee-am-service/src/test/java/io/gravitee/am/service/DomainServiceTest.java
+++ b/gravitee-am-service/src/test/java/io/gravitee/am/service/DomainServiceTest.java
@@ -15,9 +15,13 @@
  */
 package io.gravitee.am.service;
 
+import io.gravitee.am.identityprovider.api.DefaultUser;
 import io.gravitee.am.model.*;
 import io.gravitee.am.model.common.event.Event;
+import io.gravitee.am.model.membership.ReferenceType;
 import io.gravitee.am.model.oauth2.Scope;
+import io.gravitee.am.model.permissions.RoleScope;
+import io.gravitee.am.model.permissions.SystemRole;
 import io.gravitee.am.repository.exceptions.TechnicalException;
 import io.gravitee.am.repository.management.api.DomainRepository;
 import io.gravitee.am.service.exception.DomainAlreadyExistsException;
@@ -67,6 +71,7 @@ public class DomainServiceTest {
     private static final String EMAIL_ID = "id-email";
     private static final String REPORTER_ID = "id-reporter";
     private static final String POLICY_ID = "id-policy";
+    private static final String MEMBERSHIP_ID = "id-membership";
 
     @InjectMocks
     private DomainService domainService = new DomainServiceImpl();
@@ -107,6 +112,9 @@ public class DomainServiceTest {
     @Mock
     private Policy policy;
 
+    @Mock
+    private Membership membership;
+
     @Mock
     private DomainRepository domainRepository;
 
@@ -152,6 +160,9 @@ public class DomainServiceTest {
     @Mock
     private EventService eventService;
 
+    @Mock
+    private MembershipService membershipService;
+
     @Test
     public void shouldFindById() {
         when(domainRepository.findById("my-domain")).thenReturn(Maybe.just(new Domain()));
@@ -237,8 +248,10 @@ public class DomainServiceTest {
         when(scopeService.create(anyString(), any(NewSystemScope.class))).thenReturn(Single.just(new Scope()));
         when(certificateService.create(eq(domain.getId()))).thenReturn(Single.just(new Certificate()));
         when(eventService.create(any())).thenReturn(Single.just(new Event()));
+        when(membershipService.addOrUpdate(any())).thenReturn(Single.just(new Membership()));
+        when(roleService.findSystemRole(SystemRole.PRIMARY_OWNER, RoleScope.DOMAIN)).thenReturn(Maybe.just(new Role()));
 
-        TestObserver testObserver = domainService.create(newDomain).test();
+        TestObserver testObserver = domainService.create(newDomain, new DefaultUser("username")).test();
         testObserver.awaitTerminalEvent();
 
         testObserver.assertComplete();
@@ -249,6 +262,7 @@ public class DomainServiceTest {
         verify(scopeService, times(io.gravitee.am.common.oidc.Scope.values().length)).create(anyString(), any(NewSystemScope.class));
         verify(certificateService).create(eq(domain.getId()));
         verify(eventService).create(any());
+        verify(membershipService).addOrUpdate(any());
     }
 
     @Test
@@ -448,6 +462,9 @@ public class DomainServiceTest {
         when(policy.getId()).thenReturn(POLICY_ID);
         when(policyService.findByDomain(DOMAIN_ID)).thenReturn(Single.just(Collections.singletonList(policy)));
         when(policyService.delete(anyString())).thenReturn(Completable.complete());
+        when(membership.getId()).thenReturn(MEMBERSHIP_ID);
+        when(membershipService.findByReference(DOMAIN_ID, ReferenceType.DOMAIN)).thenReturn(Single.just(Collections.singletonList(membership)));
+        when(membershipService.delete(anyString())).thenReturn(Completable.complete());
         when(eventService.create(any())).thenReturn(Single.just(new Event()));
 
         TestObserver testObserver = domainService.delete(DOMAIN_ID).test();
@@ -468,6 +485,7 @@ public class DomainServiceTest {
         verify(emailTemplateService, times(1)).delete(EMAIL_ID);
         verify(reporterService, times(1)).delete(REPORTER_ID);
         verify(policyService, times(1)).delete(POLICY_ID);
+        verify(membershipService, times(1)).delete(MEMBERSHIP_ID);
         verify(eventService, times(1)).create(any());
     }
 
@@ -487,6 +505,7 @@ public class DomainServiceTest {
         when(emailTemplateService.findByDomain(DOMAIN_ID)).thenReturn(Single.just(Collections.emptyList()));
         when(reporterService.findByDomain(DOMAIN_ID)).thenReturn(Single.just(Collections.emptyList()));
         when(policyService.findByDomain(DOMAIN_ID)).thenReturn(Single.just(Collections.emptyList()));
+        when(membershipService.findByReference(DOMAIN_ID, ReferenceType.DOMAIN)).thenReturn(Single.just(Collections.emptyList()));
         when(eventService.create(any())).thenReturn(Single.just(new Event()));
 
         TestObserver testObserver = domainService.delete(DOMAIN_ID).test();
@@ -506,6 +525,7 @@ public class DomainServiceTest {
         verify(emailTemplateService, never()).delete(anyString());
         verify(reporterService, never()).delete(anyString());
         verify(policyService, never()).delete(anyString());
+        verify(membershipService, never()).delete(anyString());
         verify(eventService, times(1)).create(any());
     }