diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts
index 77c1b3578aeae5902a8be569c9249f0fcdd149f3..14a19afcd3b5d2b54db27795cf995aa29a1b6ec5 100644
--- a/smp-angular/src/app/app.module.ts
+++ b/smp-angular/src/app/app.module.ts
@@ -130,7 +130,7 @@ import {
 } from "./common/panels/domain-member-panel/domain-member-panel.component";
 import {
   MemberDialogComponent
-} from "./common/panels/domain-member-panel/member-dialog/member-dialog.component";
+} from "./common/dialogs/member-dialog/member-dialog.component";
 import {MatAutocompleteModule} from "@angular/material/autocomplete";
 import {MembershipService} from "./common/panels/domain-member-panel/membership.service";
 import {AdminUserComponent} from "./system-settings/admin-users/admin-user.component";
@@ -142,6 +142,9 @@ import {EditDomainComponent} from "./edit/edit-domain/edit-domain.component";
 import {EditDomainService} from "./edit/edit-domain/edit-domain.service";
 import {SmpFieldErrorComponent} from "./common/components/smp-field-error/smp-field-error.component";
 import {DomainGroupComponent} from "./edit/edit-domain/domain-group-panel/domain-group.component";
+import {GroupDialogComponent} from "./edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component";
+import {EditGroupComponent} from "./edit/edit-group/edit-group.component";
+import {EditGroupService} from "./edit/edit-group/edit-group.service";
 
 
 @NgModule({
@@ -179,9 +182,11 @@ import {DomainGroupComponent} from "./edit/edit-domain/domain-group-panel/domain
     DomainResourceTypePanelComponent,
     DomainSelectorComponent,
     EditDomainComponent,
+    EditGroupComponent,
     ExpiredPasswordDialogComponent,
     ExtensionComponent,
     ExtensionPanelComponent,
+    GroupDialogComponent,
     FooterComponent,
     InformationDialogComponent,
     IsAuthorized,
@@ -271,6 +276,7 @@ import {DomainGroupComponent} from "./edit/edit-domain/domain-group-panel/domain
     MembershipService,
     DownloadService,
     EditDomainService,
+    EditGroupService,
     ExtensionService,
     GlobalLookups,
     HttpEventService,
diff --git a/smp-angular/src/app/app.routes.ts b/smp-angular/src/app/app.routes.ts
index d7988abf52bbba43eb8dd8830fcc479fe5de2a3f..7ff9afaa2c3f572b797749400bed11f96b99f492 100644
--- a/smp-angular/src/app/app.routes.ts
+++ b/smp-angular/src/app/app.routes.ts
@@ -1,7 +1,6 @@
 import {RouterModule, Routes} from '@angular/router';
 import {LoginComponent} from './login/login.component';
 import {ServiceGroupSearchComponent} from './service-group-search/service-group-search.component';
-import {UserComponent} from './system-settings/user/user.component';
 import {AlertComponent} from "./alert/alert.component";
 import {PropertyComponent} from "./system-settings/property/property.component";
 import {UserProfileComponent} from "./user-settings/user-profile/user-profile.component";
@@ -15,6 +14,7 @@ import {AdminDomainComponent} from "./system-settings/admin-domain/admin-domain.
 import {dirtyDeactivateGuard} from "./guards/dirty.guard";
 import {AdminUserComponent} from "./system-settings/admin-users/admin-user.component";
 import {EditDomainComponent} from "./edit/edit-domain/edit-domain.component";
+import {EditGroupComponent} from "./edit/edit-group/edit-group.component";
 
 
 const appRoutes: Routes = [
@@ -27,7 +27,7 @@ const appRoutes: Routes = [
     canActivateChild: [authenticationGuard],
     children: [
       {path: 'edit-domain', component: EditDomainComponent, canDeactivate: [dirtyDeactivateGuard]},
-      {path: 'edit-group', component: UserComponent, canDeactivate: [dirtyDeactivateGuard]},
+      {path: 'edit-group', component: EditGroupComponent, canDeactivate: [dirtyDeactivateGuard]},
       {path: 'edit-resource', component: PropertyComponent, canDeactivate: [dirtyDeactivateGuard]}
     ]
   },
diff --git a/smp-angular/src/app/common/alert-message/alert-message.component.ts b/smp-angular/src/app/common/alert-message/alert-message.component.ts
index 908ab6243580ae9609eae978c601835fbc452817..60edc305ff29dfb49c0cb55a5758c92cab66250c 100644
--- a/smp-angular/src/app/common/alert-message/alert-message.component.ts
+++ b/smp-angular/src/app/common/alert-message/alert-message.component.ts
@@ -25,9 +25,7 @@ export class AlertMessageComponent implements OnInit {
   }
 
   setSticky(sticky: boolean):void {
-    console.log("set sticky " + sticky)
     this.showSticky = sticky;
-
   }
 
   get messageText(){
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.css b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.css
similarity index 100%
rename from smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.css
rename to smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.css
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.html b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html
similarity index 97%
rename from smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.html
rename to smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html
index 66c9c2922e6956608529065815d06aaba80973e2..2f5eda50ab6934212ab3fb0f0e4b7c8295f5b09c 100644
--- a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.html
+++ b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html
@@ -28,7 +28,7 @@
           {{role.key}}
         </mat-option>
       </mat-select>
-      <mat-hint> Chose member role</mat-hint>
+      <mat-hint> Choose member role</mat-hint>
     </mat-form-field>
   </form>
 </mat-dialog-content>
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.ts b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts
similarity index 88%
rename from smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.ts
rename to smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts
index e7fa0916ff7196716aca1096a69ae411e797d358..880c9a5b28afca23599af73fe5be2728d6edf0fd 100644
--- a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/member-dialog.component.ts
+++ b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts
@@ -1,14 +1,14 @@
 import {Component, Inject, Input, OnInit} from '@angular/core';
 import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
 import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
-import {MembershipRoleEnum} from "../../../enums/membership-role.enum";
+import {MembershipRoleEnum} from "../../enums/membership-role.enum";
 import {Observable} from "rxjs";
-import {SearchUserRo} from "./search-user-ro.model";
-import {MembershipService} from "../membership.service";
-import {MemberRo} from "../../../model/member-ro.model";
-import {DomainRo} from "../../../model/domain-ro.model";
-import {MemberTypeEnum} from "../../../enums/member-type.enum";
-import {AlertMessageService} from "../../../alert-message/alert-message.service";
+import {SearchUserRo} from "../../model/search-user-ro.model";
+import {MembershipService} from "../../panels/domain-member-panel/membership.service";
+import {MemberRo} from "../../model/member-ro.model";
+import {DomainRo} from "../../model/domain-ro.model";
+import {MemberTypeEnum} from "../../enums/member-type.enum";
+import {AlertMessageService} from "../../alert-message/alert-message.service";
 
 
 @Component({
@@ -92,7 +92,7 @@ export class MemberDialogComponent implements OnInit {
       this.memberForm.controls['member-memberOf'].setValue("");
       this.memberForm.controls['member-roleType'].setValue("");
     }
-
+    this.memberForm.markAsPristine();
   }
 
   ngOnInit() {
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/search-user-ro.model.ts b/smp-angular/src/app/common/model/search-user-ro.model.ts
similarity index 59%
rename from smp-angular/src/app/common/panels/domain-member-panel/member-dialog/search-user-ro.model.ts
rename to smp-angular/src/app/common/model/search-user-ro.model.ts
index 4b96bc26228ac850015a897dfb4f64c81328b1dc..e47992589e10bfc3c96d4a8ffa5391a8fed9e0c4 100644
--- a/smp-angular/src/app/common/panels/domain-member-panel/member-dialog/search-user-ro.model.ts
+++ b/smp-angular/src/app/common/model/search-user-ro.model.ts
@@ -1,4 +1,4 @@
-import {SearchTableEntity} from "../../../search-table/search-table-entity.model";
+import {SearchTableEntity} from "../search-table/search-table-entity.model";
 
 export interface SearchUserRo extends SearchTableEntity {
   userId: string,
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.html b/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.html
index bcbf9dfe271e7ec811c115c2f0d978618859b4b0..4148b0542d7fc459312239086b0324ec38946139 100644
--- a/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.html
+++ b/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.html
@@ -62,6 +62,7 @@
           <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
           <tr mat-row *matRowDef="let odd = odd; let row; columns: displayedColumns;"
               (click)="memberSelected(row)"
+              (dblclick)="showEditDailogForMember(row)"
               [ngClass]="{'datatable-row-selected': row==selectedMember,'datatable-row-odd': odd}"
           ></tr>
 
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.ts b/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.ts
index 9b22863f6d95d6f22046eefd884d5e3e799876f4..865f4af18df76fe0921d20076c90971c8272a981 100644
--- a/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.ts
+++ b/smp-angular/src/app/common/panels/domain-member-panel/domain-member-panel.component.ts
@@ -1,4 +1,4 @@
-import {Component, EventEmitter, Input, Output, ViewChild,} from '@angular/core';
+import {Component, Input, ViewChild,} from '@angular/core';
 import {DomainRo} from "../../model/domain-ro.model";
 import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
 import {AdminDomainService} from "../../../system-settings/admin-domain/admin-domain.service";
@@ -9,7 +9,7 @@ import {MatPaginator, PageEvent} from "@angular/material/paginator";
 import {MemberRo} from "../../model/member-ro.model";
 import {finalize} from "rxjs/operators";
 import {TableResult} from "../../model/table-result.model";
-import {MemberDialogComponent} from "./member-dialog/member-dialog.component";
+import {MemberDialogComponent} from "../../dialogs/member-dialog/member-dialog.component";
 import {MembershipService} from "./membership.service";
 import {MembershipRoleEnum} from "../../enums/membership-role.enum";
 import {MemberTypeEnum} from "../../enums/member-type.enum";
@@ -136,22 +136,27 @@ export class DomainMemberPanelComponent implements BeforeLeaveGuard {
     } as MemberRo
   }
 
-
   public onEditSelectedButtonClicked() {
+    this.showEditDailogForMember(this.selectedMember);
+  }
+
+  public showEditDailogForMember(member: MemberRo) {
     this.dialog.open(MemberDialogComponent, {
       data: {
         domain: this._domain,
-        member: this.selectedMember,
+        member: member,
         formTitle: "Edit member role for domain"
       }
     }).afterClosed().subscribe(value => {
       this.refresh();
     });
   }
+
   public onDeleteSelectedButtonClicked() {
     this.membershipService.deleteMemberFromDomain(this._domain.domainId, this.selectedMember).subscribe(value => {
       this.refresh();
-    });;
+    });
+    ;
   }
 
   isDirty(): boolean {
diff --git a/smp-angular/src/app/common/panels/domain-member-panel/membership.service.ts b/smp-angular/src/app/common/panels/domain-member-panel/membership.service.ts
index ba50f8dd3672aa69cf0494b60850dc16ff6aeb41..1dae173c9de2961c7f870b0b142c3f31b7bfdf74 100644
--- a/smp-angular/src/app/common/panels/domain-member-panel/membership.service.ts
+++ b/smp-angular/src/app/common/panels/domain-member-panel/membership.service.ts
@@ -8,8 +8,7 @@ import {SecurityService} from "../../../security/security.service";
 import {AlertMessageService} from "../../alert-message/alert-message.service";
 import {MemberRo} from "../../model/member-ro.model";
 import {TableResult} from "../../model/table-result.model";
-import {SearchUserRo} from "./member-dialog/search-user-ro.model";
-import {MembershipRoleEnum} from "../../enums/membership-role.enum";
+import {SearchUserRo} from "../../model/search-user-ro.model";
 
 
 @Injectable()
@@ -56,10 +55,10 @@ export class MembershipService {
 
     return this.http.put<MemberRo>(SmpConstants.REST_PUBLIC_DOMAIN_MEMBERS_ADD
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
-      .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId),member);
+      .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId), member);
   }
 
-  deleteMemberFromDomain( domainId: string, member: MemberRo): Observable<MemberRo> {
+  deleteMemberFromDomain(domainId: string, member: MemberRo): Observable<MemberRo> {
     const currentUser: User = this.securityService.getCurrentUser();
 
     return this.http.delete<MemberRo>(SmpConstants.REST_PUBLIC_DOMAIN_MEMBERS_DELETE
diff --git a/smp-angular/src/app/common/panels/user-settings-panel/user-profile-panel.component.html b/smp-angular/src/app/common/panels/user-settings-panel/user-profile-panel.component.html
index 4450cc2365f3f9bcf146f66e6fb1bd5219535665..8d8bf6314c022ba53d87c58ba43879c8076ef19e 100644
--- a/smp-angular/src/app/common/panels/user-settings-panel/user-profile-panel.component.html
+++ b/smp-angular/src/app/common/panels/user-settings-panel/user-profile-panel.component.html
@@ -23,7 +23,7 @@
               {{role.key}}
             </mat-option>
           </mat-select>
-          <mat-hint> Chose member role</mat-hint>
+          <mat-hint> Choose member role</mat-hint>
         </mat-form-field>
 
         <mat-checkbox
diff --git a/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.html b/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.html
index bb6abd3c1068032a45e18094a4233d86387a6628..ebcc96f4d017f192dacd205ebbb5bdd2dec83cb7 100644
--- a/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.html
+++ b/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.html
@@ -56,6 +56,7 @@
           <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
           <tr mat-row *matRowDef="let odd = odd; let row; columns: displayedColumns;"
               (click)="onGroupSelected(row)"
+              (dblclick)="showEditDialogForGroup(row)"
               [ngClass]="{'datatable-row-selected': row==selectedGroup,'datatable-row-odd': odd}"
           ></tr>
 
diff --git a/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts b/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts
index 5c9e1589681699170e4982ab30d1ac3ba666c267..ad9397ac64a8cd8edb2786f6329f79bb3cf540f5 100644
--- a/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts
+++ b/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts
@@ -1,4 +1,4 @@
-import {Component, Input,} from '@angular/core';
+import {Component, Input, ViewChild,} from '@angular/core';
 import {FormBuilder} from "@angular/forms";
 import {AlertMessageService} from "../../../common/alert-message/alert-message.service";
 import {MatDialog} from "@angular/material/dialog";
@@ -8,6 +8,9 @@ import {finalize} from "rxjs/operators";
 import {MatTableDataSource} from "@angular/material/table";
 import {GroupRo} from "../../../common/model/group-ro.model";
 import {EditDomainService} from "../edit-domain.service";
+import {GroupDialogComponent} from "./group-dialog/group-dialog.component";
+import {VisibilityEnum} from "../../../common/enums/visibility.enum";
+import {MatPaginator} from "@angular/material/paginator";
 
 @Component({
   selector: 'domain-group-panel',
@@ -28,6 +31,8 @@ export class DomainGroupComponent implements BeforeLeaveGuard {
 
   selectedGroup: GroupRo;
 
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+
   constructor(private editDomainService: EditDomainService,
               private alertService: AlertMessageService,
               private dialog: MatDialog,
@@ -57,6 +62,13 @@ export class DomainGroupComponent implements BeforeLeaveGuard {
     }
   }
 
+  public refresh() {
+    if (this.paginator) {
+      this.paginator.firstPage();
+    }
+    this.loadTableData();
+  }
+
   loadTableData() {
     if (!this._domain) {
       this.dataSource.data = null;
@@ -83,9 +95,31 @@ export class DomainGroupComponent implements BeforeLeaveGuard {
   }
 
   onAddButtonClicked() {
+    this.dialog.open(GroupDialogComponent, {
+      data: {
+        domain: this._domain,
+        group: this.createGroup(),
+        formTitle: "Invite new member to domain"
+      }
+    }).afterClosed().subscribe(value => {
+      this.refresh();
+    });
   };
 
   onEditSelectedButtonClicked() {
+    this.showEditDialogForGroup(this.selectedGroup);
+  };
+
+  showEditDialogForGroup(group:GroupRo) {
+    this.dialog.open(GroupDialogComponent, {
+      data: {
+        domain: this._domain,
+        group: group,
+        formTitle: "Invite new member to domain"
+      }
+    }).afterClosed().subscribe(value => {
+      this.refresh();
+    });
   };
 
   onDeleteSelectedButtonClicked() {
@@ -102,10 +136,17 @@ export class DomainGroupComponent implements BeforeLeaveGuard {
         }
       }, (error) => {
         this.alertService.error(error.error?.errorDescription)
-    }
+      }
     )
   };
 
+  public createGroup(): GroupRo {
+    return {
+      visibility: VisibilityEnum.Public
+    } as GroupRo
+  }
+
+
   onGroupSelected(group: GroupRo) {
     this.selectedGroup = group;
   }
diff --git a/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.css b/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..1c224cec9922cc4489dc8d1c050c783cb15c6255
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.css
@@ -0,0 +1,13 @@
+.empty-field-label {
+  color: gray;
+}
+
+
+#custom-file-upload {
+  display: none;
+}
+
+.custom-file-upload {
+  display: inline-block;
+  cursor: pointer;
+}
diff --git a/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.html b/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..a7e701006d7dc293466d2e69d862ea336dce5f40
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.html
@@ -0,0 +1,46 @@
+<h2 mat-dialog-title>{{formTitle}}</h2>
+<mat-dialog-content style="width:700px">
+  <form [formGroup]="groupForm">
+    <b *ngIf="newMode">To create a new group enter unique group name for the domain and click save.</b>
+    <mat-form-field  style="width: 100%">
+      <mat-label>Group name</mat-label>
+      <input id="name_id" type="text" matInput formControlName="name"
+             required>
+      <mat-hint >Unique group name for the domain</mat-hint>
+    </mat-form-field>
+
+    <mat-form-field  style="width: 100%">
+      <mat-label>Group description</mat-label>
+      <input id="description_id" type="text" matInput
+             formControlName="description"
+             >
+    </mat-form-field>
+
+
+    <mat-form-field style="width:100%">
+      <mat-label>Group visibility</mat-label>
+      <mat-select placeholder="Group visibility"
+                  formControlName="visibility"
+                  matTooltip="Group visibility."
+                  id="group_id" required>
+        <mat-option *ngFor="let visibility of groupVisibilityOptions"
+                    [value]="visibility.value">
+          {{visibility.key}}
+        </mat-option>
+      </mat-select>
+      <mat-hint>Choose group visibility</mat-hint>
+    </mat-form-field>
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button mat-raised-button color="primary" (click)="closeDialog()">
+    <mat-icon>cancel</mat-icon>
+    <span>Close</span>
+  </button>
+  <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
+          [disabled]="!submitButtonEnabled">
+    <mat-icon>save</mat-icon>
+    <span>Save</span>
+  </button>
+</mat-dialog-actions>
+
diff --git a/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.ts b/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fc30e583eae256197ea616cce1ec45424ceaf00a
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-domain/domain-group-panel/group-dialog/group-dialog.component.ts
@@ -0,0 +1,134 @@
+import {Component, Inject, Input} from '@angular/core';
+import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
+import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
+import {DomainRo} from "../../../../common/model/domain-ro.model";
+import {AlertMessageService} from "../../../../common/alert-message/alert-message.service";
+import {VisibilityEnum} from "../../../../common/enums/visibility.enum";
+import {GroupRo} from "../../../../common/model/group-ro.model";
+import {EditDomainService} from "../../edit-domain.service";
+
+
+@Component({
+  templateUrl: './group-dialog.component.html',
+  styleUrls: ['./group-dialog.component.css']
+})
+export class GroupDialogComponent {
+
+  readonly groupVisibilityOptions = Object.keys(VisibilityEnum)
+    .filter(el => el !== "Private").map(el => {
+      return {key: el, value: VisibilityEnum[el]}
+    });
+  formTitle = "Group dialog";
+  groupForm: FormGroup;
+
+  message: string;
+  messageType: string = "alert-error";
+
+  _group: GroupRo;
+  _currentDomain: DomainRo;
+
+  constructor(@Inject(MAT_DIALOG_DATA) public data: any,
+              private editDomainService: EditDomainService,
+              public dialogRef: MatDialogRef<GroupDialogComponent>,
+              private alertService: AlertMessageService,
+              private formBuilder: FormBuilder
+  ) {
+    dialogRef.disableClose = true;//disable default close operation
+    this.formTitle = data.formTitle;
+    this._currentDomain = data.domain;
+
+    this.groupForm = formBuilder.group({
+      'name': new FormControl({value: null}),
+      'description': new FormControl({value: null}),
+      'visibility': new FormControl({value: null}),
+      '': new FormControl({value: null})
+    });
+    this.group = data.group;
+  }
+
+  get newMode(): boolean {
+    return !this._group?.groupId
+  }
+
+  get group(): GroupRo {
+    let group = {...this._group};
+    group.groupName = this.groupForm.get('name').value;
+    group.groupDescription = this.groupForm.get('description').value;
+    group.visibility = this.groupForm.get('visibility').value;
+    return group;
+  }
+
+  @Input() set group(value: GroupRo) {
+    this._group = value;
+
+    if (!!value) {
+      this.groupForm.enable();
+      this.groupForm.controls['name'].setValue(value.groupName);
+      // control disable enable did not work??
+      if (this.newMode) {
+        this.groupForm.controls['name'].enable();
+      } else {
+        this.groupForm.controls['name'].disable();
+      }
+
+      this.groupForm.controls['description'].setValue(value.groupDescription);
+      this.groupForm.controls['visibility'].setValue(value.visibility);
+
+    } else {
+      this.groupForm.disable();
+      this.groupForm.controls['name'].setValue("");
+      this.groupForm.controls['description'].setValue("");
+      this.groupForm.controls['visibility'].setValue("");
+    }
+
+    this.groupForm.markAsPristine();
+  }
+
+  clearAlert() {
+    this.message = null;
+    this.messageType = null;
+  }
+
+
+  closeDialog() {
+    this.dialogRef.close()
+  }
+
+  get submitButtonEnabled(): boolean {
+    return this.groupForm.valid && this.groupForm.dirty;
+  }
+
+  public onSaveButtonClicked() {
+
+    let group = this.group;
+    if (this.newMode) {
+      this.createGroup(group);
+    } else {
+      this.saveGroup(group);
+    }
+  }
+
+  public createGroup(group: GroupRo) {
+
+    this.editDomainService.createDomainGroupObservable(this._currentDomain.domainId, group).subscribe((group: GroupRo) => {
+      if (!!group) {
+        this.closeDialog();
+      }
+    }, (error) => {
+      this.alertService.error(error.error?.errorDescription)
+    });
+
+  }
+
+  public saveGroup(group: GroupRo) {
+    this.editDomainService.saveDomainGroupObservable(this._currentDomain.domainId, group).subscribe((group: GroupRo) => {
+      if (!!group) {
+        this.closeDialog();
+      }
+    }, (error) => {
+      this.alertService.error(error.error?.errorDescription)
+    });
+  }
+
+
+}
diff --git a/smp-angular/src/app/edit/edit-domain/edit-domain.component.ts b/smp-angular/src/app/edit/edit-domain/edit-domain.component.ts
index 97b3c37b38396648a425d0da61a101d94e5e5510..16a84f0a8915567b2c78a7a4bd149aaef6d27291 100644
--- a/smp-angular/src/app/edit/edit-domain/edit-domain.component.ts
+++ b/smp-angular/src/app/edit/edit-domain/edit-domain.component.ts
@@ -39,7 +39,6 @@ export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGu
         );
 
         domainService.getDomains();
-
   }
 
 
diff --git a/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts b/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts
index 2cfb18dc38cc657ed04f14dfac89271b59a27222..f61409702172e25c151252caa70d4ab5cdb87e32 100644
--- a/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts
+++ b/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts
@@ -31,7 +31,6 @@ export class EditDomainService {
       });
   }
 
-
   public getDomainGroupsObservable(domainId: string): Observable<GroupRo[]>
   {
     const currentUser: User = this.securityService.getCurrentUser();
@@ -40,8 +39,7 @@ export class EditDomainService {
       .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId));
   }
 
-  public deleteDomainGroupObservable(domainId: string, groupId:string ): Observable<GroupRo>
-  {
+  public deleteDomainGroupObservable(domainId: string, groupId:string ): Observable<GroupRo> {
     const currentUser: User = this.securityService.getCurrentUser();
     return this.http.delete<GroupRo>(SmpConstants.REST_PUBLIC_GROUP_DOMAIN_DELETE
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
@@ -49,7 +47,24 @@ export class EditDomainService {
       .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, groupId));
   }
 
+  public createDomainGroupObservable(domainId: string, group:GroupRo ): Observable<GroupRo>
+  {
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.put<GroupRo>(SmpConstants.REST_PUBLIC_GROUP_DOMAIN_CREATE
+      .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+      .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId)
+      , group);
+  }
 
+  public saveDomainGroupObservable(domainId: string, group:GroupRo ): Observable<GroupRo>
+  {
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.post<GroupRo>(SmpConstants.REST_PUBLIC_GROUP_DOMAIN_UPDATE
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+        .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId)
+        .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group.groupId)
+      , group);
+  }
   notifyDomainsUpdated(res: DomainRo[]) {
     this.domainUpdateSubject.next(res);
   }
diff --git a/smp-angular/src/app/edit/edit-group/edit-group.component.css b/smp-angular/src/app/edit/edit-group/edit-group.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..167fddb57e4fd3359cb65ec8e93aeebaad73e8b4
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-group/edit-group.component.css
@@ -0,0 +1,28 @@
+
+#admin-group-panel {
+  display: flex;
+  flex-flow: column;
+  align-items: center;
+  height: 100%;
+  min-height: 600px;
+  padding: 0 2em;
+}
+#group-filter {
+  width: 100%;
+  padding-top: 1em;
+}
+
+
+#admin-group-table {
+  width: 100%;
+  padding-top: 1em;
+}
+
+#custom-file-upload {
+  display: none;
+}
+
+.custom-file-upload {
+  display: block;
+  cursor: pointer;
+}
diff --git a/smp-angular/src/app/edit/edit-group/edit-group.component.html b/smp-angular/src/app/edit/edit-group/edit-group.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..dfbda58df49df62790f709d04fd5715dc1725a26
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-group/edit-group.component.html
@@ -0,0 +1,44 @@
+<div id="admin-group-panel">
+  <data-panel id="admin-group-data-panel"
+              title="Edit Group"
+              text="Edit group administration panel is a tool for group administrators to manage group members and resources"
+              [labelColumnContent]="searchGroupPanel">
+  </data-panel>
+
+</div>
+
+<ng-template #searchGroupPanel>
+  <mat-form-field id="group-filter">
+    <mat-label>Filter by group name</mat-label>
+    <input matInput (keyup)="applyGroupFilter($event)" placeholder="Group name" #inputDomainFilter>
+  </mat-form-field>
+
+  <table class="mat-elevation-z2" id="admin-domain-table" mat-table [dataSource]="dataSource" matSort>
+    <ng-container matColumnDef="groupName">
+      <th mat-header-cell *matHeaderCellDef mat-sort-header>Group name</th>
+      <td mat-cell *matCellDef="let row" [matTooltip]="row.groupDescription">{{row.groupName}}</td>
+    </ng-container>
+
+    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+    <tr mat-row *matRowDef="let odd = odd; let row; columns: displayedColumns;"
+        (click)="onGroupSelected(row)"
+        [ngClass]="{'datatable-row-selected': groupSelected,'datatable-row-odd': odd}"
+    ></tr>
+
+
+    <tr class="mat-row" *matNoDataRow>
+      <td *ngIf="inputDomainFilter.value;else noDataFound" class="mat-cell" colspan="2">No data matching the filter
+        "{{inputDomainFilter.value}}"
+      </td>
+      <ng-template #noDataFound>
+        <td class="mat-cell" colspan="2">No data</td>
+      </ng-template>
+    </tr>
+  </table>
+
+  <mat-paginator class="mat-elevation-z2" id="extension-paginator"
+                 [hidePageSize]="true"
+                 [showFirstLastButtons]="true"
+                 [pageSize]="5" aria-label="Select page"></mat-paginator>
+
+</ng-template>
diff --git a/smp-angular/src/app/edit/edit-group/edit-group.component.ts b/smp-angular/src/app/edit/edit-group/edit-group.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7325d84ecae5b81e6a5e168330ad204cfb49603c
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-group/edit-group.component.ts
@@ -0,0 +1,64 @@
+import {Component, ViewChild} from '@angular/core';
+import {BeforeLeaveGuard} from "../../window/sidenav/navigation-on-leave-guard";
+import {MatTableDataSource} from "@angular/material/table";
+import {GroupRo} from "../../common/model/group-ro.model";
+import {MatPaginator} from "@angular/material/paginator";
+import {AlertMessageService} from "../../common/alert-message/alert-message.service";
+import {MatDialog} from "@angular/material/dialog";
+import {EditGroupService} from "./edit-group.service";
+
+
+@Component({
+  moduleId: module.id,
+  templateUrl: './edit-group.component.html',
+  styleUrls: ['./edit-group.component.css']
+})
+export class EditGroupComponent implements BeforeLeaveGuard {
+  displayedColumns: string[] = ['groupName'];
+  dataSource: MatTableDataSource<GroupRo> = new MatTableDataSource();
+  selected?: GroupRo;
+
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+
+  constructor(private editGroupService: EditGroupService,
+              private alertService: AlertMessageService,
+              private dialog: MatDialog) {
+    /*
+        editGroupService.onGroupUpdatedEvent().subscribe((groupList: GroupRo[]) => {
+            this.updateGroupList(groupList);
+          }
+        );
+
+        editGroupService.getUserAdminGroups();
+
+     */
+  }
+
+
+  updateGroupList(groupList: GroupRo[]) {
+    this.dataSource.data = groupList;
+  }
+
+
+  isDirty(): boolean {
+    return false;
+  }
+
+  applyGroupFilter(event: Event) {
+    const filterValue = (event.target as HTMLInputElement).value;
+    this.dataSource.filter = filterValue.trim().toLowerCase();
+
+    if (this.dataSource.paginator) {
+      this.dataSource.paginator.firstPage();
+    }
+  }
+
+  onGroupSelected(group: GroupRo) {
+    this.selected = group;
+  }
+
+
+  get groupSelected(): boolean {
+    return !!this.selected;
+  }
+}
diff --git a/smp-angular/src/app/edit/edit-group/edit-group.service.ts b/smp-angular/src/app/edit/edit-group/edit-group.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..58410c18f1a53f1a1abfcff86a28568e9a907f6b
--- /dev/null
+++ b/smp-angular/src/app/edit/edit-group/edit-group.service.ts
@@ -0,0 +1,40 @@
+import {Injectable} from '@angular/core';
+import {Observable, Subject} from 'rxjs';
+
+import {HttpClient} from '@angular/common/http';
+import {SecurityService} from "../../security/security.service";
+import {AlertMessageService} from "../../common/alert-message/alert-message.service";
+import {User} from "../../security/user.model";
+import {SmpConstants} from "../../smp.constants";
+import {GroupRo} from "../../common/model/group-ro.model";
+
+@Injectable()
+export class EditGroupService {
+  private groupsUpdateSubject = new Subject<GroupRo[]>();
+
+
+  constructor(
+    private http: HttpClient,
+    private securityService: SecurityService,
+    private alertService: AlertMessageService) {
+  }
+
+  public getUserAdminGroups() {
+    const currentUser: User = this.securityService.getCurrentUser();
+    this.http.get<GroupRo[]>(SmpConstants.REST_PUBLIC_GROUP_EDIT
+      .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId))
+      .subscribe((result: GroupRo[]) => {
+        this.notifyGroupUpdated(result);
+      }, (error: any) => {
+        this.alertService.error(error.error?.errorDescription)
+      });
+  }
+
+  notifyGroupUpdated(res: GroupRo[]) {
+    this.groupsUpdateSubject.next(res);
+  }
+
+  onGroupUpdatedEvent(): Observable<GroupRo[]> {
+    return this.groupsUpdateSubject.asObservable();
+  }
+}
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html b/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html
index dd7b49082647f0e1ef20842af9bbd3b26b70a9f1..5c173ac8507fbe4ea6f6c56493e6c4ad0bece167 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-panel/domain-panel.component.html
@@ -1,20 +1,5 @@
 <div id="domain-panel" class="mat-elevation-z2" >
   <form [formGroup]="domainForm" >
-    <mat-toolbar>
-      <mat-toolbar-row>
-        <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
-                [disabled]="!resetButtonEnabled">
-          <mat-icon>refresh</mat-icon>
-          <span>Reset</span>
-        </button>
-        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
-                [disabled]="!submitButtonEnabled">
-          <mat-icon>save</mat-icon>
-          <span>Save</span>
-        </button>
-
-      </mat-toolbar-row>
-    </mat-toolbar>
     <h3>Domain details</h3>
     <div class="panel" *ngIf="_domain!=null &&  !_domain.domainId"><p style="font-weight: bold">Enter data and click 'Save' to create new domain</div>
     <mat-form-field style="width:100%">
@@ -92,5 +77,20 @@
       to get read the domain resources
     </mat-hint>
   </mat-form-field>
+    <mat-toolbar>
+      <mat-toolbar-row>
+        <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
+                [disabled]="!resetButtonEnabled">
+          <mat-icon>refresh</mat-icon>
+          <span>Reset</span>
+        </button>
+        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
+                [disabled]="!submitButtonEnabled">
+          <mat-icon>save</mat-icon>
+          <span>Save</span>
+        </button>
+
+      </mat-toolbar-row>
+    </mat-toolbar>
   </form>
 </div>
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html b/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html
index 8b3d5eb799acfdbc34b4f06e9faa2d8fcb6a137e..dfe8911ceee53b8324aa19a0ae1ba79fb2166552 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-sml-panel/domain-sml-integration-panel.component.html
@@ -1,32 +1,7 @@
 <form [formGroup]="domainForm" >
 
   <div id="domain-sml-integration-panel" class="mat-elevation-z2">
-    <mat-toolbar>
-      <mat-toolbar-row>
-        <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
-                [disabled]="!resetButtonEnabled">
-          <mat-icon>refresh</mat-icon>
-          <span>Reset</span>
-        </button>
-        <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
-                [disabled]="!submitButtonEnabled">
-          <mat-icon>save</mat-icon>
-          <span>Save</span>
-        </button>
-        <tool-button-spacer></tool-button-spacer>
 
-        <button  id="registerButton" mat-raised-button (click)="smlRegisterSelectedDomain()"
-                 [disabled]="!enableSMLRegister()" color="primary">
-          <mat-icon>link</mat-icon>
-          <span>Register</span>
-        </button>
-        <button  id="unregisterButton" mat-raised-button (click)="smlUnregisterSelectedDomain()"
-                 [disabled]="!enableSMLUnregister()" color="primary">
-          <mat-icon>link_off</mat-icon>
-          <span>Unregister</span>
-        </button>
-      </mat-toolbar-row>
-    </mat-toolbar>
     <h3>SML integration data</h3>
     <div class="panel" *ngIf="isDomainRegistered"><p style="font-weight: bold">Domain is registered to SML!</p>The Registered domain can not be deleted or changed the SMP SML identifier</div>
     <mat-form-field style="width:100%">
@@ -114,5 +89,30 @@
       Use ClientCert http header authentication.
     </mat-slide-toggle>
   </div>
+  <mat-toolbar>
+    <mat-toolbar-row>
+      <button id="cancelButton" mat-raised-button (click)="onResetButtonClicked()" color="primary"
+              [disabled]="!resetButtonEnabled">
+        <mat-icon>refresh</mat-icon>
+        <span>Reset</span>
+      </button>
+      <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()" color="primary"
+              [disabled]="!submitButtonEnabled">
+        <mat-icon>save</mat-icon>
+        <span>Save</span>
+      </button>
+      <tool-button-spacer></tool-button-spacer>
 
+      <button  id="registerButton" mat-raised-button (click)="smlRegisterSelectedDomain()"
+               [disabled]="!enableSMLRegister()" color="primary">
+        <mat-icon>link</mat-icon>
+        <span>Register</span>
+      </button>
+      <button  id="unregisterButton" mat-raised-button (click)="smlUnregisterSelectedDomain()"
+               [disabled]="!enableSMLUnregister()" color="primary">
+        <mat-icon>link_off</mat-icon>
+        <span>Unregister</span>
+      </button>
+    </mat-toolbar-row>
+  </mat-toolbar>
 </form>
diff --git a/smp-angular/src/app/system-settings/admin-users/admin-user.component.html b/smp-angular/src/app/system-settings/admin-users/admin-user.component.html
index a306de2f0946aaddc2217ca5c6e01f3e4fc15bbe..269f069211286de142f9fb1bab452df866b1923f 100644
--- a/smp-angular/src/app/system-settings/admin-users/admin-user.component.html
+++ b/smp-angular/src/app/system-settings/admin-users/admin-user.component.html
@@ -19,23 +19,6 @@
     <input matInput (keyup)="applyUserFilter($event)" placeholder="User name or full name" #inputUserFilter>
   </mat-form-field>
 
-  <mat-toolbar>
-    <mat-toolbar-row class="mat-elevation-z5">
-      <button mat-raised-button
-              mat-flat-button color="primary"
-              (click)="onCreateUserClicked()"
-              >Create User
-      </button>
-
-      <button mat-raised-button
-              [disabled]="canNotDelete"
-              color="primary"
-              (click)="onDeleteSelectedUserClicked()">
-        <mat-icon>delete</mat-icon>
-        <span>Delete selected</span>
-      </button>
-    </mat-toolbar-row>
-  </mat-toolbar>
   <table class="mat-elevation-z2" id="admin-domain-table" mat-table [dataSource]="userData" >
     <ng-container matColumnDef="username">
       <th mat-header-cell *matHeaderCellDef >Username</th>
@@ -72,4 +55,22 @@
                  [showFirstLastButtons]="true"
                  aria-label="Select page"></mat-paginator>
 
+  <mat-toolbar>
+    <mat-toolbar-row class="mat-elevation-z5">
+      <button mat-raised-button
+              mat-flat-button color="primary"
+              (click)="onCreateUserClicked()"
+      >Create User
+      </button>
+
+      <button mat-raised-button
+              [disabled]="canNotDelete"
+              color="primary"
+              (click)="onDeleteSelectedUserClicked()">
+        <mat-icon>delete</mat-icon>
+        <span>Delete selected</span>
+      </button>
+    </mat-toolbar-row>
+  </mat-toolbar>
+
 </ng-template>
diff --git a/smp-angular/src/app/system-settings/admin-users/admin-user.component.ts b/smp-angular/src/app/system-settings/admin-users/admin-user.component.ts
index a201f5ea5dd08e087ecfd271cee8bd17feb16c94..5ccabc9a19a0f451a435a935e197a52664b42c0f 100644
--- a/smp-angular/src/app/system-settings/admin-users/admin-user.component.ts
+++ b/smp-angular/src/app/system-settings/admin-users/admin-user.component.ts
@@ -5,7 +5,7 @@ import {ConfirmationDialogComponent} from "../../common/dialogs/confirmation-dia
 import {MatDialog, MatDialogConfig, MatDialogRef} from "@angular/material/dialog";
 import {BeforeLeaveGuard} from "../../window/sidenav/navigation-on-leave-guard";
 import {CancelDialogComponent} from "../../common/dialogs/cancel-dialog/cancel-dialog.component";
-import {SearchUserRo} from "../../common/panels/domain-member-panel/member-dialog/search-user-ro.model";
+import {SearchUserRo} from "../../common/model/search-user-ro.model";
 import {AdminUserService} from "./admin-user.service";
 import {TableResult} from "../../common/model/table-result.model";
 import {finalize} from "rxjs/operators";
diff --git a/smp-angular/src/theme.scss b/smp-angular/src/theme.scss
index f2c41ddadc3c86e4547037fdb3bdc5c8bd4b1824..8b9a316382292164ec77b9de49f0ff0db283988b 100644
--- a/smp-angular/src/theme.scss
+++ b/smp-angular/src/theme.scss
@@ -23,7 +23,32 @@ $smp-theme: mat.define-light-theme((
   typography: mat.define-typography-config(),
   density: 0,
 ));
-
+/*
+$smp-theme: mat.define-light-theme((
+  color: (
+    primary: mat.define-palette(smp-colors.$smp-primary-palette),
+    accent: mat.define-palette(smp-colors.$smp-accent-palette),
+    warn: mat.define-palette(smp-colors.$smp-warn-palette),
+  ),
+  typography: mat.define-typography-config(
+    $font-family:  null,
+    $headline-1:  mat.define-typography-level(32px, 48px, 700),
+    $headline-2: null,
+    $headline-3: null,
+    $headline-4: null,
+    $headline-5: null,
+    $headline-6: null,
+    $subtitle-1: null,
+    $subtitle-2: null,
+    $body-1:  mat.define-typography-level(12px, 14px, 500),
+    $body-2:  mat.define-typography-level(11px, 14px, 500),
+    $caption:  mat.define-typography-level(10px, 12px, 500),
+    $button: null,
+    $overline: null,
+  ),
+  density: 0,
+));
+*/
 
 // -----------------------------------------
 // blue theme
@@ -81,14 +106,17 @@ $purple_green_theme: mat.define-dark-theme((
   @include mat.all-component-colors($indigo_pink_theme);
   @include smp.all-component-colors($indigo_pink_theme);
 }
+
 .pink_blue-grey_theme {
   @include mat.all-component-colors($pink_blue-grey_theme);
   @include smp.all-component-colors($pink_blue-grey_theme);
 }
+
 .purple_green_theme {
   @include mat.all-component-colors($purple_green_theme);
   @include smp.all-component-colors($purple_green_theme);
 }
+
 // Include theme styles for core and each component used in your app.
 // Alternatively, you can import and @include the theme mixins for each component
 // that you are using.
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java
index fe4c8183ebf383b7e3e765ca14f31cad0cdbf9b9..95a176b32c1adee5964cd861a55944c3819a466b 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java
@@ -36,6 +36,7 @@ public class DomainMemberDao extends BaseDao<DBDomainMember> {
 
     private final DomainDao domainDao;
 
+
     public DomainMemberDao(DomainDao domainDao) {
         this.domainDao = domainDao;
     }
@@ -45,7 +46,7 @@ public class DomainMemberDao extends BaseDao<DBDomainMember> {
     }
 
     public boolean isUserDomainsMember(DBUser user, List<DBDomain> domainList) {
-        List<Long> domainIds = domainList.stream().map(dbDomain -> dbDomain.getId()).collect(Collectors.toList());
+        List<Long> domainIds = domainList.stream().map(DBDomain::getId).collect(Collectors.toList());
         return isUserDomainsMember(user.getId(), domainIds);
     }
 
@@ -68,9 +69,6 @@ public class DomainMemberDao extends BaseDao<DBDomainMember> {
     public boolean isUserAnyDomainAdministrator(Long userId){
         return domainDao.getDomainsByUserIdAndRolesCount(userId, MembershipRoleType.ADMIN)>0;
     }
-    public boolean isUserGroupAdministrator(Long userId){
-        return false;
-    }
 
     public boolean isUserResourceAdministrator(Long userId){
         return false;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java
index 327073d77513328208aa55285cf28690d61e39c4..8f29a9d9a11ae4ac81fbddfea9dbf7b6ed82fe53 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java
@@ -13,6 +13,7 @@
 
 package eu.europa.ec.edelivery.smp.data.dao;
 
+import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBGroup;
 import org.springframework.stereotype.Repository;
@@ -21,6 +22,7 @@ import javax.persistence.NoResultException;
 import javax.persistence.NonUniqueResultException;
 import javax.persistence.TypedQuery;
 import javax.transaction.Transactional;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
@@ -65,6 +67,7 @@ public class GroupDao extends BaseDao<DBGroup> {
         return query.getResultList();
     }
 
+
     /**
      * Returns the group or Optional.empty() if there is no group for name and domain.
      *
@@ -122,6 +125,24 @@ public class GroupDao extends BaseDao<DBGroup> {
             throw new IllegalStateException(ILLEGAL_STATE_DOMAIN_MULTIPLE_ENTRY.getMessage(name,domainCode));
         }
     }
+
+    public Long getGroupsByUserIdAndRolesCount(Long userId, MembershipRoleType... roleTypes) {
+
+        List<MembershipRoleType> list  = Arrays.asList(roleTypes ==null || roleTypes.length==0 ?MembershipRoleType.values(): roleTypes);
+        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_GROUP_BY_USER_ROLES_COUNT, Long.class);
+        query.setParameter(PARAM_USER_ID, userId);
+        query.setParameter(PARAM_MEMBERSHIP_ROLES, list);
+        return query.getSingleResult();
+    }
+
+    public List<DBGroup> getGroupsByUserIdAndRoles(Long userId, MembershipRoleType... roleTypes) {
+
+        List<MembershipRoleType> list  = Arrays.asList(roleTypes ==null || roleTypes.length==0 ?MembershipRoleType.values(): roleTypes);
+        TypedQuery<DBGroup> query = memEManager.createNamedQuery(QUERY_GROUP_BY_USER_ROLES, DBGroup.class);
+        query.setParameter(PARAM_USER_ID, userId);
+        query.setParameter(PARAM_MEMBERSHIP_ROLES, list);
+        return query.getResultList();
+    }
     /**
      * Removes Entity by given domain code
      *
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java
index 643c52a391c9e0cb14e4410e2829c8661374f65f..09f84764fdc586ca615ce0271fc60f6cdbf8e6ea 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java
@@ -20,6 +20,7 @@ import eu.europa.ec.edelivery.smp.data.model.user.DBGroupMember;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.TypedQuery;
@@ -35,8 +36,15 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @Repository
 public class GroupMemberDao extends BaseDao<DBGroupMember> {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(GroupMemberDao.class);
+
+    private final GroupDao groupDao;
+
+    public GroupMemberDao(GroupDao groupDao) {
+        this.groupDao = groupDao;
+    }
+
     public boolean isUserGroupMember(DBUser user, List<DBGroup> groups) {
-        List<Long> groupIds = groups.stream().map(grop -> grop.getId()).collect(Collectors.toList());
+        List<Long> groupIds = groups.stream().map(DBGroup::getId).collect(Collectors.toList());
         return isGroupResourceMember(user.getId(), groupIds);
     }
 
@@ -64,7 +72,7 @@ public class GroupMemberDao extends BaseDao<DBGroupMember> {
 
         query.setParameter(PARAM_USER_ID, userId);
         query.setParameter(PARAM_GROUP_IDS, groupIds);
-        return query.getResultList().stream().anyMatch(member ->member.getRole() == roleType );
+        return query.getResultList().stream().anyMatch(member -> member.getRole() == roleType);
     }
 
     public boolean isUserAnyDomainGroupResourceMemberWithRole(DBUser user, DBDomain domain, MembershipRoleType roleType) {
@@ -76,4 +84,46 @@ public class GroupMemberDao extends BaseDao<DBGroupMember> {
         query.setParameter(PARAM_MEMBERSHIP_ROLE, roleType);
         return query.getSingleResult() > 0;
     }
+
+    public boolean isUserGroupAdministrator(Long userId) {
+        return groupDao.getGroupsByUserIdAndRolesCount(userId, MembershipRoleType.ADMIN) > 0;
+    }
+
+    public List<DBGroupMember> getGroupMembers(Long groupId, int iPage, int iPageSize, String filter) {
+        boolean hasFilter = StringUtils.isNotBlank(filter);
+        TypedQuery<DBGroupMember> query = memEManager.createNamedQuery(hasFilter ?
+                QUERY_GROUP_MEMBERS_FILTER : QUERY_GROUP_MEMBERS, DBGroupMember.class);
+
+        if (iPageSize > -1 && iPage > -1) {
+            query.setFirstResult(iPage * iPageSize);
+        }
+        if (iPageSize > 0) {
+            query.setMaxResults(iPageSize);
+        }
+        query.setParameter(PARAM_GROUP_ID, groupId);
+        if (hasFilter) {
+            query.setParameter(PARAM_USER_FILTER, "%" + StringUtils.trim(filter) + "%");
+        }
+        return query.getResultList();
+    }
+
+    public Long getGroupMemberCount(Long groupId, String filter) {
+        boolean hasFilter = StringUtils.isNotBlank(filter);
+        TypedQuery<Long> query = memEManager.createNamedQuery(hasFilter ? QUERY_GROUP_MEMBERS_FILTER_COUNT : QUERY_GROUP_MEMBERS_COUNT, Long.class);
+        query.setParameter(PARAM_GROUP_ID, groupId);
+        if (hasFilter) {
+            query.setParameter(PARAM_USER_FILTER, "%" + StringUtils.trim(filter) + "%");
+        }
+        return query.getSingleResult();
+    }
+
+
+    public DBGroupMember addMemberToDomain(DBGroup group, DBUser user, MembershipRoleType role) {
+        DBGroupMember groupMember = new DBGroupMember();
+        groupMember.setRole(role);
+        groupMember.setUser(user);
+        groupMember.setGroup(group);
+        groupMember = merge(groupMember);
+        return groupMember;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
index 2e9b56e51feaad78833e4d4bc4e37f17a50155b6..a111fae202379e68cc34e509e3c295cfce83c4df 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java
@@ -23,6 +23,12 @@ public class QueryNames {
     public static final String QUERY_GROUP_BY_DOMAIN = "DBGroup.getByDomain";
     public static final String QUERY_GROUP_BY_NAME_DOMAIN = "DBGroup.getByNameDomain";
     public static final String QUERY_GROUP_BY_NAME_DOMAIN_CODE = "DBGroup.getByNameDomainCode";
+    public static final String QUERY_GROUP_BY_USER_ROLES = "DBGroup.getByUserAndRoles";
+    public static final String QUERY_GROUP_BY_USER_ROLES_COUNT = "DBGroup.getByUserAndRolesCount";
+    public static final String QUERY_GROUP_MEMBERS_COUNT = "DBGroup.getByGroupCount";
+    public static final String QUERY_GROUP_MEMBERS_FILTER_COUNT = "DBGroup.getByGroupFilterCount";
+    public static final String QUERY_GROUP_MEMBERS = "DBGroup.getByGroup";
+    public static final String QUERY_GROUP_MEMBERS_FILTER = "DBGroup.getByGroupFilter";
 
     public static final String QUERY_DOMAIN_MEMBER_ALL = "DBDomainMember.getAll";
     public static final String QUERY_DOMAIN_MEMBER_BY_USER_DOMAINS_COUNT = "DBDomainMember.getByUserAndDomainsCount";
@@ -123,6 +129,7 @@ public class QueryNames {
 
     public static final String PARAM_DOCUMENT_ID = "document_id";
 
+    public static final String PARAM_GROUP_ID = "group_id";
     public static final String PARAM_GROUP_IDS = "group_ids";
     public static final String PARAM_MEMBERSHIP_ROLE = "membership_role";
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java
index c7af3e058b66e848d444c939ba9cc67f80f6ab98..f54fe80c7ad3e2aed14315400b3228a1ec014fcc 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java
@@ -38,12 +38,15 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
         })
 
 @org.hibernate.annotations.Table(appliesTo = "SMP_GROUP", comment = "The group spans the resources belonging to the domain group.")
-@NamedQueries({
-        @NamedQuery(name = QUERY_GROUP_ALL, query = "SELECT u FROM DBGroup u"),
-        @NamedQuery(name = QUERY_GROUP_BY_DOMAIN, query = "SELECT u FROM DBGroup u where u.domain.id = :domain_id"),
-        @NamedQuery(name = QUERY_GROUP_BY_NAME_DOMAIN, query = "SELECT u FROM DBGroup u where u.groupName = :name and u.domain.id = :domain_id"),
-        @NamedQuery(name = QUERY_GROUP_BY_NAME_DOMAIN_CODE, query = "SELECT u FROM DBGroup u where u.groupName = :name and u.domain.domainCode = :domain_code"),
-})
+@NamedQuery(name = QUERY_GROUP_ALL, query = "SELECT u FROM DBGroup u")
+@NamedQuery(name = QUERY_GROUP_BY_DOMAIN, query = "SELECT u FROM DBGroup u where u.domain.id = :domain_id")
+@NamedQuery(name = QUERY_GROUP_BY_NAME_DOMAIN, query = "SELECT u FROM DBGroup u where u.groupName = :name and u.domain.id = :domain_id")
+@NamedQuery(name = QUERY_GROUP_BY_NAME_DOMAIN_CODE, query = "SELECT u FROM DBGroup u where u.groupName = :name and u.domain.domainCode = :domain_code")
+@NamedQuery(name = QUERY_GROUP_BY_USER_ROLES_COUNT, query = "SELECT count(c) FROM DBGroup c JOIN DBGroupMember dm ON c.id = dm.group.id " +
+        " WHERE dm.role in (:membership_roles) and dm.user.id= :user_id")
+
+@NamedQuery(name = QUERY_GROUP_BY_USER_ROLES, query = "SELECT c FROM DBGroup c JOIN DBGroupMember dm ON c.id = dm.group.id " +
+        " WHERE dm.role in (:membership_roles) and dm.user.id= :user_id")
 public class DBGroup extends BaseEntity {
 
     @Id
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java
index 40b6cfbe790e2268bb7c24e9b7f529e370eae565..bf89df0aa72db7791290f339f70821f362e68fea 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java
@@ -4,6 +4,8 @@ import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.model.BaseEntity;
 import eu.europa.ec.edelivery.smp.data.model.CommonColumnsLengths;
 import eu.europa.ec.edelivery.smp.data.model.DBGroup;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.hibernate.annotations.GenericGenerator;
 import org.hibernate.envers.Audited;
 
@@ -21,18 +23,28 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @Audited
 @Table(name = "SMP_GROUP_MEMBER",
         indexes = {@Index(name = "SMP_GRP_MEM_IDX", columnList = "FK_GROUP_ID, FK_USER_ID", unique = true)
-})
-@NamedQueries({
-        @NamedQuery(name = QUERY_GROUP_MEMBER_ALL, query = "SELECT u FROM DBGroupMember u"),
-        @NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_GROUPS_COUNT, query = "SELECT count(c) FROM DBGroupMember c " +
-                " WHERE c.user.id = :user_id AND c.group.id IN (:group_ids)"),
-        @NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_COUNT, query = "SELECT count(c) FROM DBGroupMember c JOIN c.group.domain d " +
-                " WHERE c.user.id = :user_id AND d.id = :domain_id"),
-        @NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_GROUPS, query = "SELECT c FROM DBGroupMember c " +
-                " WHERE c.user.id = :user_id AND c.group.id IN (:group_ids)"),
-        @NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_ROLE_COUNT, query = "SELECT count(c) FROM DBGroupMember c " +
-                " WHERE c.user.id = :user_id AND c.group.domain.id = :domain_id AND c.role= :membership_role ")
-})
+        })
+
+@NamedQuery(name = QUERY_GROUP_MEMBER_ALL, query = "SELECT u FROM DBGroupMember u")
+@NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_GROUPS_COUNT, query = "SELECT count(c) FROM DBGroupMember c " +
+        " WHERE c.user.id = :user_id AND c.group.id IN (:group_ids)")
+@NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_COUNT, query = "SELECT count(c) FROM DBGroupMember c JOIN c.group.domain d " +
+        " WHERE c.user.id = :user_id AND d.id = :domain_id")
+@NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_GROUPS, query = "SELECT c FROM DBGroupMember c " +
+        " WHERE c.user.id = :user_id AND c.group.id IN (:group_ids)")
+@NamedQuery(name = QUERY_GROUP_MEMBERS_COUNT, query = "SELECT count(c) FROM DBGroupMember c " +
+        " WHERE c.group.id = :group_id")
+@NamedQuery(name = QUERY_GROUP_MEMBERS, query = "SELECT c FROM DBGroupMember c " +
+        " WHERE c.group.id = :group_id order by c.user.username")
+@NamedQuery(name = QUERY_GROUP_MEMBERS_FILTER_COUNT, query = "SELECT count(c) FROM DBGroupMember c " +
+        " WHERE c.group.id = :group_id AND (lower(c.user.fullName) like lower(:user_filter) OR lower(c.user.username) like lower(:user_filter))")
+@NamedQuery(name = QUERY_GROUP_MEMBERS_FILTER, query = "SELECT c FROM DBGroupMember c " +
+        " WHERE c.group.id = :group_id  AND (lower(c.user.fullName) like lower(:user_filter) OR lower(c.user.username) like lower(:user_filter))  order by c.user.username")
+
+
+@NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_ROLE_COUNT, query = "SELECT count(c) FROM DBGroupMember c " +
+        " WHERE c.user.id = :user_id AND c.group.domain.id = :domain_id AND c.role= :membership_role ")
+
 public class DBGroupMember extends BaseEntity {
 
     @Id
@@ -97,4 +109,20 @@ public class DBGroupMember extends BaseEntity {
     public void setRole(MembershipRoleType role) {
         this.role = role;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+
+        if (o == null || getClass() != o.getClass()) return false;
+
+        DBGroupMember that = (DBGroupMember) o;
+
+        return new EqualsBuilder().appendSuper(super.equals(o)).append(id, that.id).append(role, that.role).isEquals();
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder(17, 37).appendSuper(super.hashCode()).append(id).append(role).toHashCode();
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java
index 818bda65dec05d50bf31c83b49613a48efbb00b3..4a5d05df65da839607908b5f69e6dfb078859159 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java
@@ -3,6 +3,8 @@ package eu.europa.ec.edelivery.smp.services.ui;
 import eu.europa.ec.edelivery.smp.data.dao.BaseDao;
 import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
 import eu.europa.ec.edelivery.smp.data.dao.GroupDao;
+import eu.europa.ec.edelivery.smp.data.dao.GroupMemberDao;
+import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBGroup;
 import eu.europa.ec.edelivery.smp.data.ui.GroupRO;
@@ -11,6 +13,7 @@ import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -31,13 +34,15 @@ public class UIGroupPublicService extends UIServiceBase<DBGroup, GroupRO> {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIGroupPublicService.class);
     private final GroupDao groupDao;
+    private final GroupMemberDao groupMemberDao;
     private final DomainDao domainDao;
     private final ConversionService conversionService;
 
-    public UIGroupPublicService(GroupDao groupDao, DomainDao domainDao, ConversionService conversionService) {
+    public UIGroupPublicService(GroupDao groupDao, DomainDao domainDao, GroupMemberDao groupMemberDao, ConversionService conversionService) {
         this.groupDao = groupDao;
         this.domainDao = domainDao;
         this.conversionService = conversionService;
+        this.groupMemberDao = groupMemberDao;
     }
 
     @Override
@@ -69,6 +74,14 @@ public class UIGroupPublicService extends UIServiceBase<DBGroup, GroupRO> {
                 .collect(Collectors.toList());
     }
 
+    @Transactional
+    public List<GroupRO> getAllGroupsForUser(Long userId, MembershipRoleType role) {
+        List<DBGroup> domainGroups = groupDao.getGroupsByUserIdAndRoles(userId, role);
+
+        return domainGroups.stream().map(domain -> conversionService.convert(domain, GroupRO.class))
+                .collect(Collectors.toList());
+    }
+
     @Transactional
     public GroupRO createGroupForDomain(Long domainId, GroupRO groupRO) {
         LOG.info("create group [{}] to domain [{}]", groupRO, domainId);
@@ -85,7 +98,7 @@ public class UIGroupPublicService extends UIServiceBase<DBGroup, GroupRO> {
         group.setVisibility(groupRO.getVisibility());
         group.setDomain(domain);
         // to get ID for conversion
-        domainDao.persistFlushDetach(domain);
+        groupDao.persistFlushDetach(group);
 
         return conversionService.convert(group, GroupRO.class);
     }
@@ -99,27 +112,37 @@ public class UIGroupPublicService extends UIServiceBase<DBGroup, GroupRO> {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DeleteGroup", "Can not find group to delete");
         }
 
-        if (Objects.equals(group.getDomain().getId(), domainId)) {
+        if (!Objects.equals(group.getDomain().getId(), domainId)) {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DeleteGroup", "Group does not belong to domain");
         }
+        Long userCount = groupMemberDao.getGroupMemberCount(groupId, null);
+        if (userCount > 0) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DeleteGroup", "Group has members [" + userCount + "] and can not be deleted");
+        }
+
         groupDao.remove(group);
         return conversionService.convert(group, GroupRO.class);
     }
-/*
+
     @Transactional
-    public MemberRO deleteMemberFromDomain(Long domainId, Long memberId) {
-        LOG.info("Delete member [{}] from domain [{}]", memberId, domainId);
-        DBDomainMember domainMember = domainMemberDao.find(memberId);
-        if (domainMember == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Membership", "Membership does not exists!");
+    public GroupRO saveGroupForDomain(Long domainId, Long groupId, GroupRO groupRO) {
+        LOG.info("save group [{}] to domain [{}]", groupRO, domainId);
+
+        if (StringUtils.isBlank(groupRO.getGroupName())) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UpdateGroup", "Group name must not be blank!");
         }
-        if (!Objects.equals(domainMember.getDomain().getId(),domainId  )){
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Membership", "Membership does not belong to domain!");
+
+        DBGroup group = groupDao.find(groupId);
+        if (group == null) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "UpdateGroup", "Group with does not exists!");
         }
 
-        domainMemberDao.remove(domainMember);
-        return conversionService.convert(domainMember, MemberRO.class);
-    }
+        group.setGroupName(groupRO.getGroupName());
+        group.setGroupDescription(groupRO.getGroupDescription());
+        group.setVisibility(groupRO.getVisibility());
+        // to get ID for conversion
+        groupDao.persistFlushDetach(group);
 
- */
+        return conversionService.convert(group, GroupRO.class);
+    }
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDaoTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDaoTest.java
index 1abe05b767f0f132af80fc7a90292e0ab0c8a7dd..b2b377ab9c53b49e566ac06c8760051c584cba60 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDaoTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDaoTest.java
@@ -1,5 +1,6 @@
 package eu.europa.ec.edelivery.smp.data.dao;
 
+import eu.europa.ec.edelivery.smp.conversion.DBGroupToGroupROConverter;
 import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBGroup;
@@ -10,11 +11,13 @@ import eu.europa.ec.edelivery.smp.data.model.user.DBResourceMember;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 import eu.europa.ec.edelivery.smp.testutil.TestConstants;
 import eu.europa.ec.edelivery.smp.testutil.TestDBUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.junit.Before;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import java.util.Collections;
+import java.util.List;
 
 import static org.junit.Assert.*;
 /**
@@ -112,4 +115,49 @@ public class GroupMemberDaoTest extends AbstractBaseDao  {
         result = testInstance.isUserAnyDomainGroupResourceMemberWithRole(user, testUtilsDao.getD1(), MembershipRoleType.ADMIN);
         assertFalse(result);
     }
+
+    @Test
+    public void testGetGroupMembersOne() {
+        DBGroup group = testUtilsDao.getGroupD1G1();
+        DBUser user = testUtilsDao.getUser1();
+        addMemberToGroup(user, group, MembershipRoleType.ADMIN);
+        // then
+        Long resultCount = testInstance.getGroupMemberCount(group.getId(), null);
+        List<DBGroupMember> result = testInstance.getGroupMembers(group.getId(), 0, 10, null);
+        assertEquals(1, resultCount.intValue());
+        assertEquals(1, result.size());
+    }
+
+    @Test
+    public void testGetDomainMembersOneFilter() {
+        DBGroup group = testUtilsDao.getGroupD1G1();
+        DBUser user = testUtilsDao.getUser1();
+        addMemberToGroup(user, group, MembershipRoleType.ADMIN);
+        // then filter no match
+        assertFilter("NotExistsAtAll", 0, group);
+        assertFilter(user.getUsername(), 1, group);
+        assertFilter(user.getFullName(), 1, group);
+
+        assertFilter(StringUtils.upperCase(user.getUsername()), 1, group);
+        assertFilter(StringUtils.upperCase(user.getFullName()), 1, group);
+        assertFilter(StringUtils.lowerCase(user.getUsername()), 1, group);
+        assertFilter(StringUtils.lowerCase(user.getFullName()), 1, group);
+        assertFilter("", 1, group);
+        assertFilter(null, 1, group);
+    }
+
+    private void assertFilter(String filter, int expectedCount, DBGroup group) {
+        Long resultCount = testInstance.getGroupMemberCount(group.getId(), filter);
+        List<DBGroupMember> result = testInstance.getGroupMembers(group.getId(), 0, 10, filter);
+        assertEquals(expectedCount, resultCount.intValue());
+        assertEquals(expectedCount, result.size());
+    }
+
+    private void addMemberToGroup(DBUser user, DBGroup group, MembershipRoleType role) {
+        DBGroupMember groupMember = new DBGroupMember();
+        groupMember.setGroup(group);
+        groupMember.setUser(user);
+        groupMember.setRole(role);
+        testInstance.persistFlushDetach(groupMember);
+    }
 }
diff --git a/smp-springboot/src/main/java/eu/europa/ec/springboot/smp/SMPApplication.java b/smp-springboot/src/main/java/eu/europa/ec/springboot/smp/SMPApplication.java
index 0c273efd819eaa2f5fd0c96b7c558baa54c33e09..0828e5c002a2609aa11cf8f170cf3d4fd65d64fb 100644
--- a/smp-springboot/src/main/java/eu/europa/ec/springboot/smp/SMPApplication.java
+++ b/smp-springboot/src/main/java/eu/europa/ec/springboot/smp/SMPApplication.java
@@ -69,6 +69,7 @@ public class SMPApplication implements ApplicationRunner {
     public static void main(String... args) {
         // validate parameters
         LOG.info("Start the SMP with parameters: [{}].", String.join(",", args));
+        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
         // start spring boot application
         APPLICATION_CONTEXT = SpringApplication.run(SMPApplication.class, args);
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java
index ca3ef952ac041f0aa68303936c6b806d6cec4571..4bae166e734caf18d13eb1431d6120aac278c5fe 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java
@@ -2,6 +2,7 @@ package eu.europa.ec.edelivery.smp.auth;
 
 import eu.europa.ec.edelivery.smp.auth.enums.SMPUserAuthenticationTypes;
 import eu.europa.ec.edelivery.smp.data.dao.DomainMemberDao;
+import eu.europa.ec.edelivery.smp.data.dao.GroupMemberDao;
 import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
@@ -38,20 +39,24 @@ public class SMPAuthorizationService {
     private static final String ERR_INVALID_OR_NULL = "Invalid or Expired session! Please login again.";
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(SMPAuthorizationService.class);
 
-    DomainMemberDao domainMemberDao;
+    private final UserDao userDao;
+    private final DomainMemberDao domainMemberDao;
+    private final GroupMemberDao groupMemberDao;
 
     private final ConversionService conversionService;
     private final ConfigurationService configurationService;
-    private final UserDao userDao;
 
-    public SMPAuthorizationService(ConversionService conversionService,
-                                   ConfigurationService configurationService,
-                                   UserDao userDao,
-                                   DomainMemberDao domainMemberDao) {
-        this.conversionService = conversionService;
-        this.configurationService = configurationService;
+
+    public SMPAuthorizationService(UserDao userDao,
+                                   DomainMemberDao domainMemberDao,
+                                   GroupMemberDao groupMemberDao,
+                                   ConversionService conversionService,
+                                   ConfigurationService configurationService) {
         this.userDao = userDao;
         this.domainMemberDao = domainMemberDao;
+        this.groupMemberDao = groupMemberDao;
+        this.conversionService = conversionService;
+        this.configurationService = configurationService;
     }
 
     public boolean isSystemAdministrator() {
@@ -80,7 +85,8 @@ public class SMPAuthorizationService {
 
     public boolean isAnyGroupAdministrator() {
         SMPUserDetails userDetails = getAndValidateUserDetails();
-        return domainMemberDao.isUserGroupAdministrator(userDetails.getUser().getId());
+        return groupMemberDao.isUserGroupAdministrator(userDetails.getUser().getId())
+                || domainMemberDao.isUserAnyDomainAdministrator(userDetails.getUser().getId()) ;
     }
     public boolean isAnyResourceAdministrator() {
         SMPUserDetails userDetails = getAndValidateUserDetails();
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java
index 291cfb0115d5399a522e915f1f745d358d839b6a..33a19e39cd1ffd7db521d7044d435227af4e16a9 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java
@@ -43,6 +43,8 @@ public class ResourceConstants {
     public static final String PARAM_PAGINATION_ORDER_TYPE="orderType";
 
 
+    public static final String PARAM_ROLE="role";
+
     public static final String PARAM_QUERY_PARTC_ID="participantIdentifier";
     public static final String PARAM_QUERY_PARTC_SCHEME="participantScheme";
     public static final String PARAM_QUERY_DOMAIN_CODE ="domainCode";
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java
index 22f91ec2665f3110efff241133c6219d6f91944a..9af61808706ca5f2be4b45d767cd9dd7fe0ddf8e 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainResource.java
@@ -47,14 +47,19 @@ public class DomainResource {
             @RequestParam(value = PARAM_QUERY_USER, required = false) String user) {
 
         LOG.info("Search for page: {}, page size: {}, user: {}", page, pageSize, user);
-        ServiceResult<DomainPublicRO> result = uiDomainService.getTableList(page, pageSize, orderBy, orderType, null);
-        return result;
+        return uiDomainService.getTableList(page, pageSize, orderBy, orderType, null);
     }
 
+
+    /**
+     * Method returns all domains where user is administrator
+     * @param userEncId encrypted user identifier
+     * @return Domain list where user has role domain administrator
+     */
     @GetMapping(path = "/{user-enc-id}", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
     @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.anyDomainAdministrator")
-    public List<DomainRO> getAllDomainList(@PathVariable("user-enc-id") String userEncId) {
-        logAdminAccess("getAllDomainListForUser");
+    public List<DomainRO> getAllDomainsForDomainAdminUser(@PathVariable("user-enc-id") String userEncId) {
+        logAdminAccess("getAllDomainsForDomainAdminUser");
         Long userId = SessionSecurityUtils.decryptEntityId(userEncId);
 
         return uiDomainService.getAllDomainsForDomainAdminUser(userId);
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/GroupResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/GroupResource.java
index c175020fb8d0eacf7b0d38bd0bc04d8585a8c909..afb79241f1d2c315c65a5939e2f20a4be7337b90 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/GroupResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/GroupResource.java
@@ -1,6 +1,8 @@
 package eu.europa.ec.edelivery.smp.ui.external;
 
 
+import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
+import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
 import eu.europa.ec.edelivery.smp.data.ui.GroupRO;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
@@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
 import java.util.List;
 
 import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.CONTEXT_PATH_PUBLIC_GROUP;
+import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.PARAM_ROLE;
 
 /**
  * Purpose of the DomainResource is to provide search method to retrieve configured domains in SMP.
@@ -33,8 +36,15 @@ public class GroupResource {
     }
 
 
+
+    /**
+     * Return all Groups for the domain
+     * @param userEncId
+     * @param domainEncId
+     * @return
+     */
     @GetMapping(path = "/{user-enc-id}/domain/{domain-enc-id}", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#userEncId)")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#domainEncId)")
     public List<GroupRO> getAllGroupsForDomain(@PathVariable("user-enc-id") String userEncId,
                                                @PathVariable("domain-enc-id") String domainEncId) {
         logAdminAccess("getAllGroupsForDomain");
@@ -43,7 +53,7 @@ public class GroupResource {
     }
 
     @PutMapping(path = "/{user-enc-id}/domain/{domain-enc-id}/create", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#userEncId)")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#domainEncId)")
     public GroupRO putGroupForDomain(@PathVariable("user-enc-id") String userEncId,
                                      @PathVariable("domain-enc-id") String domainEncId,
                                      @RequestBody GroupRO group) {
@@ -52,8 +62,20 @@ public class GroupResource {
         return uiGroupPublicService.createGroupForDomain(domainId, group);
     }
 
+    @PostMapping(path = "/{user-enc-id}/{group-enc-id}/domain/{domain-enc-id}/update", produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#domainEncId)")
+    public GroupRO submitGroupForDomain(@PathVariable("user-enc-id") String userEncId,
+                                        @PathVariable("domain-enc-id") String domainEncId,
+                                        @PathVariable("group-enc-id") String groupEncId,
+                                        @RequestBody GroupRO group) {
+        logAdminAccess("updateGroupForDomain");
+        Long domainId = SessionSecurityUtils.decryptEntityId(domainEncId);
+        Long groupId = SessionSecurityUtils.decryptEntityId(groupEncId);
+        return uiGroupPublicService.saveGroupForDomain(domainId,groupId, group);
+    }
+
     @DeleteMapping(path = "/{user-enc-id}/{group-enc-id}/domain/{domain-enc-id}/delete", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#userEncId)")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#domainEncId)")
     public GroupRO deleteGroupFromDomain(@PathVariable("user-enc-id") String userEncId,
                                          @PathVariable("domain-enc-id") String domainEncId,
                                          @PathVariable("group-enc-id") String groupEncId) {
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java
index 2951303d027654b290a46f485fcfd7694f95b8af..465762ac3c106c57832b9b2b75fa78343bb765fb 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/UserResource.java
@@ -135,7 +135,7 @@ public class UserResource {
     @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userId)")
     @GetMapping(path = "/{user-id}/username-credential-status")
     public CredentialRO getUsernameCredentialStatus(@PathVariable("user-id") String userId) {
-        LOG.debug("get User credential status: [{}]", userId);
+        LOG.debug("Get user credential status for user: [{}]", userId);
         Long entityId = decryptEntityId(userId);
         // Update the user and mark the password as changed at this very instant of time
         List<CredentialRO> credentialROList = uiUserService.getUserCredentials(entityId,
@@ -147,7 +147,7 @@ public class UserResource {
     @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#encUserId)")
     @GetMapping(path = "/{user-id}/access-token-credentials")
     public List<CredentialRO> getAccessTokenCredentials(@PathVariable("user-id") String encUserId) {
-        LOG.debug("get User credential status: [{}]", encUserId);
+        LOG.debug("Get access token credential status for user:: [{}]", encUserId);
         Long userId = decryptEntityId(encUserId);
         // Update the user and mark the password as changed at this very instant of time
         return uiUserService.getUserCredentials(userId,
@@ -256,7 +256,7 @@ public class UserResource {
     protected NavigationTreeNodeRO createPublicNavigationTreeNode() {
         NavigationTreeNodeRO node = new NavigationTreeNodeRO("search-tools", "Search", "search", "public");
         node.addChild(new NavigationTreeNodeRO("search-resources", "Resources", "find_in_page", "search-resource","Search registered resources"));
-        node.addChild(new NavigationTreeNodeRO("search-lookup", "DNS lookup", "dns", "dns-lookup" , "DNS lookup tools"));
+        //node.addChild(new NavigationTreeNodeRO("search-lookup", "DNS lookup", "dns", "dns-lookup" , "DNS lookup tools"));
         return node;
     }
 
@@ -290,7 +290,7 @@ public class UserResource {
         }
         if (authorizationService.isAnyGroupAdministrator()) {
             // is group admin
-            node.addChild(new NavigationTreeNodeRO("edit-group", "Edit groups", "key", "edit-group"));
+            node.addChild(new NavigationTreeNodeRO("edit-group", "Edit groups", "people", "edit-group"));
         }
         if (authorizationService.isAnyResourceAdministrator()) {
             // is resource admin
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java
index 5fadb083429d550e02022f50fd5f7f58df744ba3..04c58d10e53c05e9a975a5048c760a960e088f45 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationServiceTest.java
@@ -1,6 +1,7 @@
 package eu.europa.ec.edelivery.smp.auth;
 
 import eu.europa.ec.edelivery.smp.data.dao.DomainMemberDao;
+import eu.europa.ec.edelivery.smp.data.dao.GroupMemberDao;
 import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 import eu.europa.ec.edelivery.smp.data.ui.UserRO;
@@ -33,9 +34,10 @@ public class SMPAuthorizationServiceTest {
     ConfigurationService configurationService = Mockito.mock(ConfigurationService.class);
     UserDao userDao = Mockito.mock(UserDao.class);
     DomainMemberDao domainMemberDao = Mockito.mock(DomainMemberDao.class);
+    GroupMemberDao groupMemberDao = Mockito.mock(GroupMemberDao.class);
 
-    SMPAuthorizationService testInstance = new SMPAuthorizationService(conversionService,
-            configurationService, userDao, domainMemberDao);
+    SMPAuthorizationService testInstance = new SMPAuthorizationService(userDao, domainMemberDao, groupMemberDao, conversionService,
+            configurationService);
 
 
     @Before