diff --git a/changelog.txt b/changelog.txt
index 012e7793ea5af172eaa1a19050261c4924ad115f..0002f2a68c16b11234dc3a7773c1ffb29b174e25 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,6 +1,6 @@
 eDelivery SMP 5.1
 - added new HTTP headers when creating a new resource:
-    'Resource-Owner' as alternative to ServiceGroup-Owner
+    'Resource-Admin' as alternative to ServiceGroup-Owner
     'Resource-Group': the name of the group: to define to which group in domain the resource belongs to. The group must be in one of the admin's groups. If not given the first group from the list is used.
     'Resource-Visibility': The visibility of the resource: PUBLIC, PRIVATE. The default value is PUBLIC. Resource visibility can be set only at creation time. To change value of the existing resource it must be done via the UI.
 - added new properties:
diff --git a/domismp-tests/domismp-docker/compose/domismp-tomcat-mysql/docker-compose.local.yml b/domismp-tests/domismp-docker/compose/domismp-tomcat-mysql/docker-compose.local.yml
index 2f8c0a63b8ac7fb7edd6a958ca811001ceedba4e..c9d2740a0b50b59af06232cc6133c44e29fcb7f3 100644
--- a/domismp-tests/domismp-docker/compose/domismp-tomcat-mysql/docker-compose.local.yml
+++ b/domismp-tests/domismp-docker/compose/domismp-tomcat-mysql/docker-compose.local.yml
@@ -4,7 +4,7 @@
 services:
   domismp-service:
     ports:
-#      - "3908:3306"
+      - "3908:3306"
       - "8982:8080"
 #      - "6902:6901"
 #      - "8953:53"
diff --git a/domismp-tests/domismp-docker/images/domismp-springboot-mysql/entrypoint.sh b/domismp-tests/domismp-docker/images/domismp-springboot-mysql/entrypoint.sh
index 12d419efba5d49721983d9df52864e667d077afd..e76c5fad5a981b218ac218847111b15b3947a8df 100755
--- a/domismp-tests/domismp-docker/images/domismp-springboot-mysql/entrypoint.sh
+++ b/domismp-tests/domismp-docker/images/domismp-springboot-mysql/entrypoint.sh
@@ -108,6 +108,7 @@ init_smp() {
   # set smp data/security folder
   mkdir -p "${SMP_HOME}/smp/"
   mkdir -p  "${SMP_HOME}/smp-libs"
+  mkdir -p ${DATA_DIR}/smp/locales
   # copy smp keystore with sml authorized sml certificates
   cp /tmp/artefacts/shared-artefacts/smp-logback.xml "${SMP_HOME}/logback.xml"
   cp "/tmp/artefacts/shared-artefacts/smp-keystore-docker-demo.p12" "${SMP_HOME}/smp/smp-keystore-docker-demo.p12"
@@ -127,7 +128,7 @@ init_smp_properties() {
     echo "# SMP init parameters"
     echo "smp.security.folder=${SMP_HOME}/smp/"
     echo "smp.libraries.folder=${SMP_HOME}/smp-libs"
-    echo "smp.locale.folder=${SMP_HOME}/locales"
+    echo "smp.locale.folder=${SMP_HOME}/smp/locales"
     echo "smp.automation.authentication.external.tls.clientCert.enabled=true"
     echo "bdmsl.integration.enabled=false"
     echo "bdmsl.participant.multidomain.enabled=false"
diff --git a/domismp-tests/domismp-docker/images/domismp-tomcat-mysql/entrypoint.sh b/domismp-tests/domismp-docker/images/domismp-tomcat-mysql/entrypoint.sh
index 3a519cea4cdb9c55f599341117e64117dea943dd..871eb8793b149f31828b4fb0508049f5b52a935e 100755
--- a/domismp-tests/domismp-docker/images/domismp-tomcat-mysql/entrypoint.sh
+++ b/domismp-tests/domismp-docker/images/domismp-tomcat-mysql/entrypoint.sh
@@ -85,7 +85,7 @@ init_tomcat() {
   rm -rf ${TOMCAT_HOME}/classes
   ln -sf ${TOMCAT_DIR}/classes ${TOMCAT_HOME}/
   # set smp data/security folder
-  mkdir ${DATA_DIR}/smp/
+  mkdir -p ${DATA_DIR}/smp/locales
 
   # sleep a little to avoid mv issues
   sleep 5s
@@ -103,6 +103,8 @@ init_mysql() {
     sleep 3s
     mv /var/lib/mysql ${DATA_DIR}
   fi
+  # set mysql authentication plugin to mysql_native_password
+  printf "\n[mysqld]\nbind-address =  0.0.0.0\ndefault_authentication_plugin = mysql_native_password\n" | tee -a /etc/mysql/my.cnf
 
   rm -rf /var/lib/mysql
   ln -sf ${MYSQL_DATA_DIR} /var/lib/mysql
@@ -119,7 +121,7 @@ init_mysql() {
     echo "[INFO] MySQL ${SMP_DB_SCHEMA}  not found, creating initial DBs"
 
     echo 'Create smp database'
-    mysql -h localhost -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';drop schema if exists $SMP_DB_SCHEMA;DROP USER IF EXISTS $SMP_DB_USER;  create schema $SMP_DB_SCHEMA;alter database $SMP_DB_SCHEMA charset=utf8; create user $SMP_DB_USER identified by '$SMP_DB_USER_PASSWORD';grant all on $SMP_DB_SCHEMA.* to $SMP_DB_USER;"
+    mysql -h localhost -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';CREATE USER 'root'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';drop schema if exists $SMP_DB_SCHEMA;DROP USER IF EXISTS $SMP_DB_USER;  create schema $SMP_DB_SCHEMA;alter database $SMP_DB_SCHEMA charset=utf8; create user $SMP_DB_USER identified by '$SMP_DB_USER_PASSWORD';grant all on $SMP_DB_SCHEMA.* to $SMP_DB_USER;"
 
     if [ -f "/tmp/custom-data/mysql5innodb.sql" ]; then
       echo "Use custom database script! "
@@ -241,7 +243,7 @@ init_smp_properties() {
     echo "# SMP init parameters"
     echo "smp.security.folder=${DATA_DIR}/smp/"
     echo "smp.libraries.folder=$SMP_HOME/apache-tomcat-$TOMCAT_VERSION/smp-libs"
-    echo "smp.locale.folder=$SMP_HOME/apache-tomcat-$TOMCAT_VERSION/locales"
+    echo "smp.locale.folder=$SMP_HOME/apache-tomcat-$TOMCAT_VERSION/smp/locales"
     echo "bdmsl.integration.logical.address=${SMP_LOGICAL_ADDRESS:-http://localhost:8080/smp/}"
     echo "smp.automation.authentication.external.tls.clientCert.enabled=true"
     echo "bdmsl.integration.enabled=true"
diff --git a/domismp-tests/domismp-docker/images/domismp-weblogic122/properties/init/smp.config.properties b/domismp-tests/domismp-docker/images/domismp-weblogic122/properties/init/smp.config.properties
index beec0400e7fbe65d7c3ab014ea533fe2669c109d..364a4ae8938c66de5e9a464807417767e6ad7daf 100644
--- a/domismp-tests/domismp-docker/images/domismp-weblogic122/properties/init/smp.config.properties
+++ b/domismp-tests/domismp-docker/images/domismp-weblogic122/properties/init/smp.config.properties
@@ -1,5 +1,6 @@
 
 smp.security.folder=/data/smp/security
+smp.locale.folder=/data/smp/locales
 smp.jdbc.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
 smp.datasource.jndi=jdbc/eDeliverySmpDs
 smp.automation.authentication.external.tls.clientCert.enabled=true
diff --git a/domismp-tests/domismp-docker/images/domismp-weblogic141/properties/init/smp.config.properties b/domismp-tests/domismp-docker/images/domismp-weblogic141/properties/init/smp.config.properties
index 78599b119855eadba9e823b491a2f2ffbc09b65a..00f93a596a343421f730175600e0fa8e550ffd92 100644
--- a/domismp-tests/domismp-docker/images/domismp-weblogic141/properties/init/smp.config.properties
+++ b/domismp-tests/domismp-docker/images/domismp-weblogic141/properties/init/smp.config.properties
@@ -1,5 +1,6 @@
 
 smp.security.folder=/data/smp/security
+smp.locale.folder=/data/smp/locales
 smp.jdbc.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
 smp.datasource.jndi=jdbc/eDeliverySmpDs
 smp.automation.authentication.external.tls.clientCert.enabled=true
diff --git a/pom.xml b/pom.xml
index d9ebcc12db2a213b93902792e926e73a89d8e1e1..d25e512ff7aa0902eca1dcc6ecea6a56a4fcffcf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -289,6 +289,11 @@ See the Licence for the specific language governing permissions and limitations
                 <artifactId>spring-core</artifactId>
                 <version>${spring.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-webmvc</artifactId>
+                <version>${spring.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.springframework</groupId>
                 <artifactId>spring-oxm</artifactId>
diff --git a/smp-angular/src/_smp-all-themes.scss b/smp-angular/src/_smp-all-themes.scss
index 6deaa632784c6d80eaf1380dd85d63dc64e3e6ba..cc7ab387dca37b9fa924f041a00ad5097993f5a0 100644
--- a/smp-angular/src/_smp-all-themes.scss
+++ b/smp-angular/src/_smp-all-themes.scss
@@ -6,6 +6,7 @@
 @use 'app/window/sidenav/nav-tree/_nav-tree.component-theme' as nav-tree;
 @use 'app/common/search-table/_search-table.component-theme' as search-table;
 @use 'app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme' as access-token-panel;
+@use 'app/common/panels/expandable-panel-component/expandable-panel.component' as expandable-panel;
 
 @mixin all-component-colors($theme) {
   @include toolbar.set-component-colors($theme);
@@ -13,11 +14,9 @@
   @include nav-tree.set-component-colors($theme);
   @include search-table.set-component-colors($theme);
   @include access-token-panel.set-component-colors($theme);
-
+  @include expandable-panel.set-component-colors($theme);
   /* shared classes*/
-  .smp-data-panel:hover {
-    background-color: smp.get-theme-color($theme, primary, 300);
-  }
+
 
   .datatable-row-odd {
     background-color: smp.get-theme-color($theme, primary, 50, 0.2) !important;
diff --git a/smp-angular/src/_smp-theme-helper.scss b/smp-angular/src/_smp-theme-helper.scss
index 65987b9e58d7afeeda4bb0cdee4a15cb5c88f730..7d4c57de2affec7f8d1ae673b9bf02fb8a16ac94 100644
--- a/smp-angular/src/_smp-theme-helper.scss
+++ b/smp-angular/src/_smp-theme-helper.scss
@@ -2,7 +2,10 @@
 @use 'sass:map';
 @use '@angular/material' as mat;
 
-
+@function get-theme-type($smp-theme ) {
+  $color-config: mat.get-color-config($smp-theme);
+  @return map.get($color-config, type);
+}
 
 @function get-theme-color($smp-theme, $color: primary, $hue: null,  $opacity: null ) {
   $color-config: mat.get-color-config($smp-theme);
diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts
index 9f02ed3493493b08d9f120862c9d834e82e6ada0..3f43c97098c81c9c84da2cbe2d5da39abe814a3d 100644
--- a/smp-angular/src/app/app.module.ts
+++ b/smp-angular/src/app/app.module.ts
@@ -101,7 +101,6 @@ import {NGX_MAT_MOMENT_DATE_ADAPTER_OPTIONS,NGX_MAT_MOMENT_FORMATS, NgxMatMoment
 import {MembershipPanelComponent} from "./common/panels/membership-panel/membership-panel.component";
 import {MemberDialogComponent} from "./common/dialogs/member-dialog/member-dialog.component";
 import {MatAutocompleteModule} from "@angular/material/autocomplete";
-import {MembershipService} from "./common/panels/membership-panel/membership.service";
 import {AdminUserComponent} from "./system-settings/admin-users/admin-user.component";
 import {AdminUserService} from "./system-settings/admin-users/admin-user.service";
 import {UserProfilePanelComponent} from "./common/panels/user-settings-panel/user-profile-panel.component";
@@ -189,9 +188,17 @@ import {
   ReviewDocumentPanelComponent
 } from "./common/panels/review-tasks-panel/review-document-panel/review-document-panel.component";
 import {
-  DocumentMetadataPanelComponent
-} from "./common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component";
+  DocumentConfigurationPanelComponent
+} from "./common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component";
 
+import {MembershipService} from "./common/services/membership.service";
+import {
+  ReferenceDocumentDialogComponent
+} from "./common/dialogs/reference-document-dialog/reference-document-dialog.component";
+import {
+  ReferenceDocumentService
+} from "./common/services/reference-document.service";
+import {MatButtonToggleModule} from "@angular/material/button-toggle";
 
 @NgModule({
   declarations: [
@@ -225,9 +232,9 @@ import {
     DocumentWizardDialogComponent,
     DocumentEditPanelComponent,
     DocumentEventsPanelComponent,
+    DocumentConfigurationPanelComponent,
     DocumentPropertiesPanelComponent,
     DocumentPropertyDialogComponent,
-    DocumentMetadataPanelComponent,
     DocumentVersionsPanelComponent,
     DomainGroupComponent,
     DomainPanelComponent,
@@ -267,6 +274,7 @@ import {
     RowLimiterComponent,
     SaveDialogComponent,
     SearchTableComponent,
+    ReferenceDocumentDialogComponent,
     ReviewDocumentPanelComponent,
     ReviewTasksComponent,
     ReviewTasksPanelComponent,
@@ -323,6 +331,7 @@ import {
     MatToolbarModule,
     MatTooltipModule,
     MatTreeModule,
+    MatButtonToggleModule,
     NgxDatatableModule,
     NgxMatDatetimePickerModule,
     NgxMatMomentModule,
@@ -355,6 +364,7 @@ import {
     MembershipService,
     NavigationService,
     PropertyController,
+    ReferenceDocumentService,
     ResourceFilterOptionsService,
     SecurityEventService,
     SecurityService,
diff --git a/smp-angular/src/app/common/dialogs/credential-dialog/credential-dialog.component.ts b/smp-angular/src/app/common/dialogs/credential-dialog/credential-dialog.component.ts
index 1deb1ae92a62e22ec0bc58de684096588c0c69d3..73f7dfc18d6efb34f85f54f136c0999442f99eb4 100644
--- a/smp-angular/src/app/common/dialogs/credential-dialog/credential-dialog.component.ts
+++ b/smp-angular/src/app/common/dialogs/credential-dialog/credential-dialog.component.ts
@@ -205,7 +205,23 @@ export class CredentialDialogComponent {
     }
     if (this.isCertificateType) {
       credential.certificate = this.certificateData;
+    } else {
+      let dateFrom = this.credentialForm.controls['activeFrom'].value;
+      if (dateFrom) {
+        // make date mutable and the modification
+        dateFrom = new Date(dateFrom);
+        dateFrom.setHours(0, 0, 0, 0);
+      }
+      credential.activeFrom = dateFrom
+      let dateTo = this.credentialForm.controls['expireOn'].value;
+      if (dateTo) {
+        // make date mutable and the modification
+        dateTo = new Date(dateTo);
+        dateTo.setHours(23, 59, 59, 999);
+      }
+      credential.expireOn = dateTo
     }
+
     return credential;
   }
 
diff --git a/smp-angular/src/app/common/dialogs/manage-members-dialog/manage-members-dialog.component.ts b/smp-angular/src/app/common/dialogs/manage-members-dialog/manage-members-dialog.component.ts
index a3b50837f744dbfc7bac631466fea931914f30d5..57286fb2e22aa545117a5ec4013aa2e6aa0b2147 100644
--- a/smp-angular/src/app/common/dialogs/manage-members-dialog/manage-members-dialog.component.ts
+++ b/smp-angular/src/app/common/dialogs/manage-members-dialog/manage-members-dialog.component.ts
@@ -4,7 +4,6 @@ import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
 import {MembershipRoleEnum} from "../../enums/membership-role.enum";
 import {lastValueFrom, Observable} from "rxjs";
 import {SearchUserRo} from "../../model/search-user-ro.model";
-import {MembershipService} from "../../panels/membership-panel/membership.service";
 import {MemberRo} from "../../model/member-ro.model";
 import {DomainRo} from "../../model/domain-ro.model";
 import {MemberTypeEnum} from "../../enums/member-type.enum";
@@ -12,6 +11,7 @@ import {AlertMessageService} from "../../alert-message/alert-message.service";
 import {GroupRo} from "../../model/group-ro.model";
 import {ResourceRo} from "../../model/resource-ro.model";
 import {TranslateService} from "@ngx-translate/core";
+import {MembershipService} from "../../services/membership.service";
 
 
 @Component({
@@ -98,11 +98,9 @@ export class ManageMembersDialogComponent implements OnInit {
       } else {
         this.memberForm.controls['member-user'].disable();
       }
-
       this.memberForm.controls['member-fullName'].setValue(value.fullName);
       this.memberForm.controls['member-memberOf'].setValue(value.memberOf);
       this.memberForm.controls['member-roleType'].setValue(value.roleType);
-
     } else {
       this.memberForm.controls['member-user'].setValue("");
       this.memberForm.controls['member-fullName'].setValue("");
diff --git a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.css b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.css
index bcc42673eca6fe33a199cbaf472eafacce461830..5dad2f2b3dedb32373d4db88f0bc51ab03df1126 100644
--- a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.css
+++ b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.css
@@ -1,6 +1,3 @@
-.form-field-full-width {
-  width: 100%;
-}
 
 .empty-field-label {
   color: gray;
diff --git a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html
index ab7f34ceb5b818fc63ed83ac7127f3bebe57349e..58f9568856d5035c8c277c44a621aeb51a790ff7 100644
--- a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html
+++ b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.html
@@ -31,8 +31,8 @@
       <mat-hint>{{ "member.dialog.hint.choose.role" | translate }}</mat-hint>
     </mat-form-field>
 
-    <mat-form-field class="form-field-full-width" >
-      <mat-checkbox  *ngIf="isResourceMember" formControlName="member-can-review" id="member-user-can-review"
+    <mat-form-field *ngIf="isResourceMember"  class="form-field-full-width" >
+      <mat-checkbox  formControlName="member-can-review" id="member-user-can-review"
                      matTooltip="{{ 'member.dialog.tooltip.permission.review' | translate }}"
       >{{ "member.dialog.label.permission.review" | translate }}
         <!-- This input is used to make the mat-checkbox as form filed   -->
diff --git a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts
index bed709837ab5bd5b8702c3889afa654ef8b23856..a94dc63a6d20184825bf4173dc618752d90aa925 100644
--- a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts
+++ b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts
@@ -4,7 +4,6 @@ import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
 import {MembershipRoleEnum} from "../../enums/membership-role.enum";
 import {lastValueFrom, Observable} from "rxjs";
 import {SearchUserRo} from "../../model/search-user-ro.model";
-import {MembershipService} from "../../panels/membership-panel/membership.service";
 import {MemberRo} from "../../model/member-ro.model";
 import {DomainRo} from "../../model/domain-ro.model";
 import {MemberTypeEnum} from "../../enums/member-type.enum";
@@ -12,6 +11,7 @@ import {AlertMessageService} from "../../alert-message/alert-message.service";
 import {GroupRo} from "../../model/group-ro.model";
 import {ResourceRo} from "../../model/resource-ro.model";
 import {TranslateService} from "@ngx-translate/core";
+import {MembershipService} from "../../services/membership.service";
 
 
 @Component({
@@ -24,9 +24,7 @@ export class MemberDialogComponent implements OnInit {
 
   message: string;
   messageType: string = "alert-error";
-
   formTitle = "";
-
   currentFilter: string;
 
   _currentMember: MemberRo;
diff --git a/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.html b/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.html
index 07ebf260fe3efda685b253d84dd32d758a48f4b4..71059655f3ca439e43b422c46a9d4e2fee0c46ac 100644
--- a/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.html
+++ b/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.html
@@ -49,8 +49,7 @@
     <mat-icon>check_circle</mat-icon>
     <span>{{ "property.details.dialog.button.ok" | translate }}</span>
   </button>
-  <button mat-raised-button color="primary" mat-dialog-close
-      [disabled]="!isDirty" >
+  <button mat-raised-button color="primary" mat-dialog-close>
     <mat-icon>cancel</mat-icon>
     <span>{{ "property.details.dialog.button.cancel" | translate }}</span>
   </button>
diff --git a/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.ts b/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.ts
index 834b77646ad3a054b38188b66ea241eb1ecef493..f766d05fea20387a5582efd4d835df9c5d9c0fe3 100644
--- a/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.ts
+++ b/smp-angular/src/app/common/dialogs/property-details-dialog/property-details-dialog.component.ts
@@ -11,13 +11,13 @@ import {
 } from "@angular/forms";
 import {
   AlertMessageService
-} from "../../../common/alert-message/alert-message.service";
-import {EntityStatus} from "../../../common/enums/entity-status.enum";
+} from "../../alert-message/alert-message.service";
+import {EntityStatus} from "../../enums/entity-status.enum";
 import {SmpConstants} from "../../../smp.constants";
 import {HttpClient} from "@angular/common/http";
 import {
   HttpErrorHandlerService
-} from "../../../common/error/http-error-handler.service";
+} from "../../error/http-error-handler.service";
 import {
   PropertyRo
 } from "../../../system-settings/admin-properties/property-ro.model";
@@ -57,7 +57,7 @@ export class PropertyDetailsDialogComponent implements OnInit {
     this.editMode = data.edit;
     this.propertyType = data.propertyType;
     this.propertyType = !data.propertyType ? PropertySourceEnum.SYSTEM : data.propertyType;
-    (async () => await this.updateFormTitle()) ();
+    (async () => await this.updateFormTitle())();
 
     this.current = this.editMode
       ? {
@@ -80,13 +80,12 @@ export class PropertyDetailsDialogComponent implements OnInit {
       'value': new UntypedFormControl({value: ''}),
       'valuePattern': new UntypedFormControl({value: ''}),
       'errorMessage': new UntypedFormControl({value: ''}),
-      'systemDefault': new UntypedFormControl({value: 'true'}),
+      'systemDefault': new UntypedFormControl({value: false}),
     });
 
     this.propertyForm.controls['property'].setValue(this.current.property);
     this.propertyForm.controls['desc'].setValue(this.current.desc);
     this.propertyForm.controls['type'].setValue(this.current.type);
-    this.propertyForm.controls['value'].setValue(this.valueFromPropertyStringValue(this.current.value, this.current.type));
     this.propertyForm.controls['valuePattern'].setValue(this.current.valuePattern);
     this.propertyForm.controls['systemDefault'].setValue(this.current.systemDefault);
 
@@ -96,8 +95,8 @@ export class PropertyDetailsDialogComponent implements OnInit {
 
   async updateFormTitle() {
     this.formTitle = this.editMode
-        ? await lastValueFrom(this.translateService.get("property.details.dialog.title.edit.mode", {type: this.capitalize(this.propertyType)}))
-        : await lastValueFrom(this.translateService.get("property.details.dialog.title.new.mode", {type: this.capitalize(this.propertyType)}));
+      ? await lastValueFrom(this.translateService.get("property.details.dialog.title.edit.mode", {type: this.capitalize(this.propertyType)}))
+      : await lastValueFrom(this.translateService.get("property.details.dialog.title.new.mode", {type: this.capitalize(this.propertyType)}));
   }
 
   ngOnInit() {
@@ -124,7 +123,6 @@ export class PropertyDetailsDialogComponent implements OnInit {
     let validationObservable = this.http
       .post<PropertyValidationRo>(SmpConstants.REST_INTERNAL_PROPERTY_VALIDATE, request);
 
-
     this.showSpinner = true;
 
     try {
@@ -164,25 +162,32 @@ export class PropertyDetailsDialogComponent implements OnInit {
 
   /**
    * Method casts string value to correct property type for dialog component used for editing.
-   * @param value
-   * @param propertyType
+   * At the moment only BOOLEAN needs to be updated, other types are returned as is.
+   * @param value - string value
+   * @param propertyType - property type
    */
-  public valueFromPropertyStringValue(value: string, propertyType: string) {
-    switch (propertyType) {
-      case 'BOOLEAN':
-        return value === 'true';
-      default:
-        return value;
+  public valueFromPropertyStringValue(value: any, propertyType: string) {
+
+    if (propertyType === 'BOOLEAN') {
+      // make sure that the value is lower case string!
+      const valToString = value?.toString().toLowerCase();
+      return valToString === 'true' || valToString === '1' || valToString === 'yes';
     }
+    return value;
   }
 
+  /**
+   * Method casts value to string for property value. At the moment only BOOLEAN needs to be updated.
+   * @param value - value
+   * @param propertyType - property type
+   */
   public valueToPropertyStringValue(value: string, propertyType: string) {
-    switch (propertyType) {
-      case 'BOOLEAN':
-        return value === 'true';
-      default:
-        return value;
+    if (propertyType === 'BOOLEAN') {
+      // make sure that the value is lower case string!
+      const valToString = value?.toString().toLowerCase();
+      return valToString === 'true' || valToString === '1' || valToString === 'yes' ? 'true' : 'false';
     }
+    return value;
   }
 
   getInputType(propertyType: string) {
@@ -235,7 +240,7 @@ export class PropertyDetailsDialogComponent implements OnInit {
 
   public getCurrent(): PropertyRo {
     this.current.status = EntityStatus.UPDATED;
-    this.current.value = this.propertyForm.value['value'];
+    this.current.value = this.valueToPropertyStringValue(this.propertyForm.value['value'], this.current.type);
     this.current.systemDefault = this.propertyForm.value['systemDefault'];
     return this.current;
   }
@@ -245,21 +250,22 @@ export class PropertyDetailsDialogComponent implements OnInit {
   }
 
   get isSystemDefault(): boolean {
-    let systemDefault = this.propertyForm.value['systemDefault'];
-    return systemDefault;
+    return this.propertyForm.value['systemDefault'];
   }
 
   /**
    * Method updates the state of the value field based on the system default checkbox.
    */
   updateValueState(): void {
+    let value;
     if (!this.isDomainProperty || !this.isSystemDefault) {
+      value = this.valueFromPropertyStringValue(this.current.value, this.current.type);
       this.propertyForm.controls['value'].enable();
-      this.propertyForm.controls['value'].setValue(this.current.value);
     } else {
-      this.propertyForm.controls['value'].setValue(this.current.systemDefaultValue);
+      value = this.valueFromPropertyStringValue(this.current.systemDefaultValue, this.current.type);
       this.propertyForm.controls['value'].disable();
     }
+    this.propertyForm.controls['value'].setValue(value);
   }
 
   get isDomainProperty(): boolean {
diff --git a/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.css b/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.css
new file mode 100644
index 0000000000000000000000000000000000000000..5dad2f2b3dedb32373d4db88f0bc51ab03df1126
--- /dev/null
+++ b/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.css
@@ -0,0 +1,16 @@
+
+.empty-field-label {
+  color: gray;
+}
+
+#custom-file-upload {
+  display: none;
+}
+
+.custom-file-upload {
+  display: inline-block;
+  cursor: pointer;
+}
+#member-user-can-review {
+  max-height: 1.5em
+}
diff --git a/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.html b/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..458142d968e8b15c9aa75d9704e9192f0586ae33
--- /dev/null
+++ b/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.html
@@ -0,0 +1,117 @@
+<h2 mat-dialog-title>{{ dialogTitle }}</h2>
+<mat-dialog-content style="width:1080px;height: 600px">
+  <form [formGroup]="filterForm">
+    <div class="panel" style="flex-direction: column">
+      <div style="display: flex;flex-direction: row;width: 100%">
+        <mat-form-field class="smp-data-panel-field">
+          <mat-label>{{ "reference.document.dialog.label.resource.value" | translate }}</mat-label>
+          <input matInput id="resource-value_id"
+                 formControlName="resourceValue">
+        </mat-form-field>
+        <mat-form-field class="smp-data-panel-field">
+          <mat-label>{{ "reference.document.dialog.label.resource.scheme" | translate }}</mat-label>
+          <input matInput id="resource-scheme_id"
+                 formControlName="resourceScheme">
+        </mat-form-field>
+
+        <mat-form-field  *ngIf="showSubresourceFields"
+          class="smp-data-panel-field">
+          <mat-label>{{ "reference.document.dialog.label.subresource.value" | translate }}</mat-label>
+          <input matInput id="subresource-value_id"
+                 formControlName="subresourceValue">
+        </mat-form-field>
+        <mat-form-field *ngIf="showSubresourceFields"
+          class="smp-data-panel-field">
+          <mat-label>{{ "reference.document.dialog.label.subresource.scheme" | translate }}</mat-label>
+          <input matInput id="subresource-scheme_id"
+                 formControlName="subresourceScheme">
+        </mat-form-field>
+
+      </div>
+      <mat-toolbar-row class="smp-toolbar-row">
+        <button mat-raised-button color="primary" id="searchbutton_id"
+                (click)="onSearchButtonClicked()"
+        >
+          <mat-icon>search</mat-icon>
+          <span>{{ "reference.document.dialog.button.search" | translate }}</span>
+        </button>
+        <button mat-raised-button  id="resetbutton_id"
+                [disabled]="filterForm"
+                (click)="onResetButtonClicked()"
+        >
+          <mat-icon>reset</mat-icon>
+          <span>{{ "reference.document.dialog.button.reset" | translate }}</span>
+        </button>
+      </mat-toolbar-row>
+    </div>
+    <table mat-table style="width: 100%"
+           [dataSource]="dataSource"
+    >
+      <!-- Name Column -->
+      <ng-container matColumnDef="resourceValue">
+        <th mat-header-cell
+            *matHeaderCellDef>{{ "reference.document.dialog.column.resource.value" | translate }}
+        </th>
+        <td mat-cell *matCellDef="let row">{{ row.resourceValue }}</td>
+      </ng-container>
+
+      <!-- Weight Column -->
+      <ng-container matColumnDef="resourceScheme">
+        <th mat-header-cell
+            *matHeaderCellDef>{{ "reference.document.dialog.column.resource.value" | translate }}
+        </th>
+        <td mat-cell *matCellDef="let row">{{ row.resourceScheme }}</td>
+      </ng-container>
+
+      <ng-container matColumnDef="subresourceValue">
+        <th mat-header-cell
+            *matHeaderCellDef>{{ "reference.document.dialog.column.subresource.value" | translate }}
+        </th>
+        <td mat-cell *matCellDef="let row">{{ row.subresourceValue }}</td>
+      </ng-container>
+
+      <!-- Weight Column -->
+      <ng-container matColumnDef="subresourceScheme">
+        <th mat-header-cell
+            *matHeaderCellDef>{{ "reference.document.dialog.column.subresource.scheme" | translate }}
+        </th>
+        <td mat-cell *matCellDef="let row">{{ row.subresourceScheme }}</td>
+      </ng-container>
+
+      <ng-container matColumnDef="urlLinkAction">
+        <th mat-header-cell
+            *matHeaderCellDef>{{ "reference.document.dialog.column.open.url" | translate }}
+        </th>
+        <td mat-cell *matCellDef="let row">
+          <a *ngIf="row.referenceUrl"
+             target="_blank"
+             href="{{createURL(row)}}">{{ "reference.document.dialog.column.open.url" | translate }}</a>
+        </td>
+      </ng-container>
+      <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+      <tr mat-row *matRowDef="let odd = odd; let row; columns: displayedColumns;"
+          (click)="onRowClicked(row)"
+          [ngClass]="{'datatable-row-selected': row==selectedRow,'datatable-row-odd': odd}"
+      ></tr>
+    </table>
+    <mat-paginator class="mat-elevation-z2" id="tokens-paginator"
+                   [hidePageSize]="true"
+                   [pageSize]="10"
+                   attr.aria-label="{{ 'reference.document.dialog.label.select.page' | translate }}"></mat-paginator>
+
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button id="closeDialogButton" mat-raised-button color="primary"
+          (click)="closeDialog()">
+    <mat-icon>cancel</mat-icon>
+    <span>{{ "reference.document.dialog.button.close" | translate }}</span>
+  </button>
+  <button id="saveButton" mat-raised-button (click)="onSaveButtonClicked()"
+          color="primary"
+          [disabled]="submitButtonDisabled">
+    <mat-icon>save</mat-icon>
+    <span>{{ "reference.document.dialog.button.save" | translate }}</span>
+  </button>
+</mat-dialog-actions>
+
diff --git a/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.ts b/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3b043f1b62f977e429c5537e36fcb5738bb47211
--- /dev/null
+++ b/smp-angular/src/app/common/dialogs/reference-document-dialog/reference-document-dialog.component.ts
@@ -0,0 +1,147 @@
+import {Component, Inject, OnInit, ViewChild} from '@angular/core';
+import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
+import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
+import {AlertMessageService} from "../../alert-message/alert-message.service";
+import {TranslateService} from "@ngx-translate/core";
+import {lastValueFrom, Observer} from "rxjs";
+import {MatTableDataSource} from "@angular/material/table";
+import {
+  SearchReferenceDocument
+} from "../../model/search-reference-document-ro.model";
+import {MatPaginator} from "@angular/material/paginator";
+import {
+  ReferenceDocumentService
+} from "../../services/reference-document.service";
+import {
+  EditResourceService
+} from "../../../edit/edit-resources/edit-resource.service";
+import {ResourceRo} from "../../model/resource-ro.model";
+import {DocumentReferenceType} from "../../enums/documetn-reference-type.enum";
+import {TableResult} from "../../model/table-result.model";
+import {SubresourceRo} from "../../model/subresource-ro.model";
+
+/**
+ * Dialog component for searching reference documents
+ *
+ * @since 5.1
+ * @author Joze RIHTARSIC
+ */
+@Component({
+  templateUrl: './reference-document-dialog.component.html',
+  styleUrls: ['./reference-document-dialog.component.css']
+})
+export class ReferenceDocumentDialogComponent implements OnInit {
+  @ViewChild(MatPaginator) paginator: MatPaginator;
+
+  filterForm: FormGroup;
+  dialogTitle = "Search Reference Document";
+  domainList: string[];
+  _resourceDisplayedColumns: string[] = ['resourceValue', 'resourceScheme', 'urlLinkAction'];
+  _subresourceDisplayedColumns: string[] = ['resourceValue', 'resourceScheme', 'subresourceValue', 'subresourceScheme', 'urlLinkAction'];
+  dataSource: MatTableDataSource<SearchReferenceDocument> = new MatTableDataSource();
+  _contextPath: string = location.pathname.substring(0, location.pathname.length - 3); // remove /ui s
+  targetResource: ResourceRo
+  targetSubresource: SubresourceRo
+  targetType: DocumentReferenceType = DocumentReferenceType.RESOURCE;
+  selectedRow: SearchReferenceDocument;
+
+  // ----
+  // defined observers
+  loadReferenceDocumentsObserver: Partial<Observer<TableResult<SearchReferenceDocument>>> = {
+    next: (data) => {
+      this.dataSource.data = data.serviceEntities;
+      this.dataSource.paginator.length = data.count;
+    },
+    error: (error) => {
+      this.alertService.error("Error while searching reference documents");
+    }
+  }
+
+  constructor(@Inject(MAT_DIALOG_DATA) public data: any,
+              private referenceDocumentService: ReferenceDocumentService,
+              public dialogRef: MatDialogRef<ReferenceDocumentDialogComponent>,
+              private alertService: AlertMessageService,
+              private formBuilder: FormBuilder,
+              private translateService: TranslateService,
+              private editResourceService: EditResourceService
+  ) {
+    dialogRef.disableClose = true;//disable default close operation
+    this.filterForm = this.formBuilder.group({
+      'resourceValue': new FormControl({value: null}),
+      'resourceScheme': new FormControl({value: null}),
+      'subresourceValue': new FormControl({value: null}),
+      'subresourceScheme': new FormControl({value: null}),
+    });
+
+    this.filterForm.controls['resourceValue'].setValue("");
+    this.filterForm.controls['resourceScheme'].setValue("");
+    this.filterForm.controls['subresourceValue'].setValue("");
+    this.filterForm.controls['subresourceScheme'].setValue("");
+
+    this.targetResource = data.targetResource
+    this.targetSubresource = data.targetSubresource
+    this.targetType = data.targetType
+  }
+
+  async updateDialogTitle() {
+    this.dialogTitle = await lastValueFrom(this.translateService.get("reference.document.dialog.title"))
+  }
+
+  async ngOnInit() {
+    await this.updateDialogTitle();
+
+  }
+
+  get isDirty(): boolean {
+    return this.filterForm.dirty;
+  }
+
+  get displayedColumns(): string[] {
+    return this.showSubresourceFields ? this._subresourceDisplayedColumns : this._resourceDisplayedColumns;
+  }
+
+  get showSubresourceFields(): boolean {
+    return this.targetType === DocumentReferenceType.SUBRESOURCE;
+  }
+
+  createURL(row: SearchReferenceDocument) {
+    return this._contextPath + row.referenceUrl;
+  }
+
+  ngAfterViewInit() {
+    this.dataSource.paginator = this.paginator;
+  }
+
+  onResetButtonClicked() {
+    this.filterForm.reset();
+  }
+
+  onSearchButtonClicked() {
+    // submit form data as a filter.
+    let filter = this.filterForm.value;
+    if (this.targetType === DocumentReferenceType.RESOURCE) {
+      this.referenceDocumentService.getSearchResourceDocumentReferencesObservable$(filter, this.targetResource)
+        .subscribe(this.loadReferenceDocumentsObserver);
+    } else {
+      this.referenceDocumentService.getSearchSubresourceDocumentReferencesObservable$(filter, this.targetResource, this.targetSubresource)
+        .subscribe(this.loadReferenceDocumentsObserver);
+    }
+  }
+
+  closeDialog() {
+    this.dialogRef.close();
+  }
+
+  onSaveButtonClicked() {
+    this.dialogRef.close(this.selectedRow);
+  }
+
+  get submitButtonDisabled(): boolean {
+    return !this.selectedRow
+  }
+
+  public onRowClicked(row: SearchReferenceDocument) {
+    this.selectedRow = row;
+  }
+
+}
diff --git a/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.html b/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.html
index 593b9c2c81022ae3357d9875baeef579572a6601..e4bfc80e945b3fde7ae9deb0936d12e2fa26bad0 100644
--- a/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.html
+++ b/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.html
@@ -1,6 +1,7 @@
 <h2 mat-dialog-title>{{ "session.expiration.dialog.title" | translate }}</h2>
 <mat-dialog-content>
-  <div innerHTML='{{"session.expiration.dialog.label.session.about.to.expire" | translate:{timeLeft: data.timeLeft, timeout: data.timeout} }}'></div>
+  <div innerHTML='{{"session.expiration.dialog.label.session.about.to.expire" | translate:{timeLeft: data.timeLeft,
+  timeoutMinutes: sessionDurationInMinutes, timeoutSeconds: sessionDurationInMinutesReminder} }}'></div>
 </mat-dialog-content>
 <mat-dialog-actions>
   <button mat-raised-button mat-dialog-close (click)="onLogoutClicked()" tabindex="-1">
diff --git a/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.ts b/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.ts
index 8d459600e665165cdc997b5cdb03b64116044382..403310ef55eaa63f8138bd41aab2633e435b7560 100644
--- a/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.ts
+++ b/smp-angular/src/app/common/dialogs/session-expiration-dialog/session-expiration-dialog.component.ts
@@ -10,6 +10,8 @@ export class SessionExpirationDialogComponent {
   constructor(@Inject(MAT_DIALOG_DATA) public data: any,
               public dialogRef: MatDialogRef<SessionExpirationDialogComponent>,
               public securityService: SecurityService) {
+    // Disable the ability to close the dialog by clicking outside of it
+    dialogRef.disableClose = true;
   }
 
   public onExtendSessionClicked() {
@@ -22,5 +24,13 @@ export class SessionExpirationDialogComponent {
     this.securityService.logout();
     this.dialogRef.close();
   }
+
+  get sessionDurationInMinutes() {
+    return Math.floor(this.data.timeout / 60);
+  }
+
+  get sessionDurationInMinutesReminder() {
+    return this.data.timeout % 60;
+  }
 }
 
diff --git a/smp-angular/src/app/common/enums/documetn-reference-type.enum.ts b/smp-angular/src/app/common/enums/documetn-reference-type.enum.ts
new file mode 100644
index 0000000000000000000000000000000000000000..225d61c2f31dd1d4e37344e356c454b01c552705
--- /dev/null
+++ b/smp-angular/src/app/common/enums/documetn-reference-type.enum.ts
@@ -0,0 +1,4 @@
+export enum DocumentReferenceType {
+  RESOURCE = 'RESOURCE',
+  SUBRESOURCE = 'SUBRESOURCE',
+}
diff --git a/smp-angular/src/app/common/enums/smp-error-code.enum.ts b/smp-angular/src/app/common/enums/smp-error-code.enum.ts
new file mode 100644
index 0000000000000000000000000000000000000000..177211d242a58ec36a61e63031b65358f18194e1
--- /dev/null
+++ b/smp-angular/src/app/common/enums/smp-error-code.enum.ts
@@ -0,0 +1,10 @@
+/**
+ * The used  SMP error codes in the application. The SMP can send different error codes in the repponse,
+ * but the application only uses a subset of them.
+ *
+ * @since 5.1
+ * @author Joze RIHTARSIC
+ */
+export enum SmpErrorCode {
+  ERROR_CODE_INVALID_NEW_PASSWORD = 'SMP:010',
+}
diff --git a/smp-angular/src/app/common/global-lookups.ts b/smp-angular/src/app/common/global-lookups.ts
index cec7984f7dd357fa44dd7091a3a92bbd9ce06b79..d3fa51fa4e4ff0916a5e0f106a84237c55b75f7f 100644
--- a/smp-angular/src/app/common/global-lookups.ts
+++ b/smp-angular/src/app/common/global-lookups.ts
@@ -116,6 +116,12 @@ export class GlobalLookups {
     return result;
   }
 
+  public getDateFormat(): string {
+    let locale = this.getCurrentLocale();
+    locale = locale ? locale : this.DEFAULT_LOCALE;
+    return getLocaleDateFormat(locale, FormatWidth.Short);
+  }
+
   private format(str, opt_values) {
     if (opt_values) {
       str = str.replace(/\{([^}]+)}/g, function (match, key) {
diff --git a/smp-angular/src/app/common/model/document-configuration-ro.model.ts b/smp-angular/src/app/common/model/document-configuration-ro.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..71999050fddb56aefc40e2c173768a30a3668d59
--- /dev/null
+++ b/smp-angular/src/app/common/model/document-configuration-ro.model.ts
@@ -0,0 +1,17 @@
+import {SearchTableEntity} from "../search-table/search-table-entity.model";
+import {ResourceRo} from "./resource-ro.model";
+import {SubresourceRo} from "./subresource-ro.model";
+
+export interface DocumentConfigurationRo extends SearchTableEntity {
+  name?: string;
+  mimeType?: string;
+  sharingEnabled?: boolean;
+  allVersions?: number[];
+  publishedVersion?: number;
+  // optional reference data.
+  referenceDocumentId?: string;
+  referenceDocumentName?: string;
+  referenceDocumentUrl?: string;
+
+}
+
diff --git a/smp-angular/src/app/common/model/document-metadata-ro.model.ts b/smp-angular/src/app/common/model/document-metadata-ro.model.ts
deleted file mode 100644
index af3894c1c5dc1c5db038cc75c4a6492d50d2c390..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/common/model/document-metadata-ro.model.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import {SearchTableEntity} from "../search-table/search-table-entity.model";
-
-export interface DocumentMetadataRo extends SearchTableEntity {
-  name?: string;
-  mimeType?: string;
-  sharingEnabled?: boolean;
-  referenceDocumentId?: string;
-  allVersions?: number[];
-  publishedVersion?: number;
-}
-
diff --git a/smp-angular/src/app/common/model/document-ro.model.ts b/smp-angular/src/app/common/model/document-ro.model.ts
index c1cf99b0cadc8a3baa69afbf440cb4cfc0d7dd70..fe1c227114043ff843ff67e1692399b3dfbe99f4 100644
--- a/smp-angular/src/app/common/model/document-ro.model.ts
+++ b/smp-angular/src/app/common/model/document-ro.model.ts
@@ -6,7 +6,7 @@ import {
 } from "./document-version-ro.model";
 import {DocumentVersionEventRo} from "./document-version-event-ro.model";
 import {DocumentVersionsStatus} from "../enums/document-versions-status.enum";
-import {DocumentMetadataRo} from "./document-metadata-ro.model";
+import {DocumentConfigurationRo} from "./document-configuration-ro.model";
 
 export interface DocumentRo extends SearchTableEntity  {
   mimeType?: string;
@@ -17,11 +17,12 @@ export interface DocumentRo extends SearchTableEntity  {
   payloadVersion?:number;
   payloadCreatedOn?: Date;
   payload?:string;
+  referencePayload?:string;
   payloadStatus: EntityStatus;
   properties?: DocumentPropertyRo[];
   documentVersionStatus?: DocumentVersionsStatus;
   documentVersionEvents?: DocumentVersionEventRo[];
   documentVersions?: DocumentVersionRo[];
-  metadata?: DocumentMetadataRo;
+  documentConfiguration?: DocumentConfigurationRo;
 }
 
diff --git a/smp-angular/src/app/common/model/document-version-event-ro.model.ts b/smp-angular/src/app/common/model/document-version-event-ro.model.ts
index 17ba3452cb5e9845d821fa7fcadb66eb656afc17..89997e43dadc95402b9939001845ebba4addb931 100644
--- a/smp-angular/src/app/common/model/document-version-event-ro.model.ts
+++ b/smp-angular/src/app/common/model/document-version-event-ro.model.ts
@@ -1,4 +1,5 @@
 import {SearchTableEntity} from "../search-table/search-table-entity.model";
+import {DocumentVersionsStatus} from "../enums/document-versions-status.enum";
 
 export interface DocumentVersionEventRo extends SearchTableEntity {
   eventType: string;
@@ -6,5 +7,6 @@ export interface DocumentVersionEventRo extends SearchTableEntity {
   username: string;
   eventSourceType: string;
   details: string;
+  documentVersionStatus?: DocumentVersionsStatus;
 }
 
diff --git a/smp-angular/src/app/common/model/resource-ro.model.ts b/smp-angular/src/app/common/model/resource-ro.model.ts
index 068c333c91d06b8c297a2f9bb98c8f3a8ac984d2..478dc3a397e254c5af6721795144f185ac72a0db 100644
--- a/smp-angular/src/app/common/model/resource-ro.model.ts
+++ b/smp-angular/src/app/common/model/resource-ro.model.ts
@@ -1,18 +1,21 @@
 import {SearchTableEntity} from "../search-table/search-table-entity.model";
 import {VisibilityEnum} from "../enums/visibility.enum";
 
+/**
+ * ResourceRo interface for resource data
+ *
+ * @since 5.0
+ * @author  Joze RIHTARSIC
+ */
 export interface ResourceRo extends SearchTableEntity {
 
   resourceId?: string;
   resourceTypeIdentifier?: string;
-
   identifierValue: string;
-
   identifierScheme?: string;
 
-  smlRegistered: boolean;
-
+  smlRegistered?: boolean;
   reviewEnabled?: boolean;
-
-  visibility: VisibilityEnum;
+  hasCurrentUserReviewPermission?: boolean;
+  visibility?: VisibilityEnum;
 }
diff --git a/smp-angular/src/app/common/model/search-reference-document-ro.model.ts b/smp-angular/src/app/common/model/search-reference-document-ro.model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..60ad9e922ed293218f451f7b9bef6acb3ac1a45d
--- /dev/null
+++ b/smp-angular/src/app/common/model/search-reference-document-ro.model.ts
@@ -0,0 +1,16 @@
+import {SearchTableEntity} from "../search-table/search-table-entity.model";
+import {DocumentReferenceType} from "../enums/documetn-reference-type.enum";
+
+export interface SearchReferenceDocument extends SearchTableEntity  {
+  documentId?: string;
+  documentName?: string;
+
+  referenceType?: DocumentReferenceType;
+  resourceValue?: string;
+  resourceScheme?: string;
+  subesourceValue?: string;
+  subesourceScheme?: string;
+
+  referenceUrl?: string;
+}
+
diff --git a/smp-angular/src/app/common/model/search-user-ro.model.ts b/smp-angular/src/app/common/model/search-user-ro.model.ts
index e47992589e10bfc3c96d4a8ffa5391a8fed9e0c4..ce85fade8bf569fffa809bb60ff3bc18b5d80532 100644
--- a/smp-angular/src/app/common/model/search-user-ro.model.ts
+++ b/smp-angular/src/app/common/model/search-user-ro.model.ts
@@ -4,6 +4,5 @@ export interface SearchUserRo extends SearchTableEntity {
   userId: string,
   username: string;
   fullName: string;
-
 }
 
diff --git a/smp-angular/src/app/common/model/subresource-ro.model.ts b/smp-angular/src/app/common/model/subresource-ro.model.ts
index 807e40d4bcdd1bab99c65915a95f0e066a0917d1..7f8f864257613ecd27ff8a4e915dfbd1a6511753 100644
--- a/smp-angular/src/app/common/model/subresource-ro.model.ts
+++ b/smp-angular/src/app/common/model/subresource-ro.model.ts
@@ -1,7 +1,12 @@
 import {SearchTableEntity} from "../search-table/search-table-entity.model";
 
+/**
+ * SubresourceRo interface for subresource data
+ *
+ * @since 5.0
+ * @author  Joze RIHTARSIC
+ */
 export interface SubresourceRo extends SearchTableEntity {
-
   subresourceId?: string;
   subresourceTypeIdentifier?: string;
   identifierValue: string;
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.html b/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..489eb3c6b2401445d7ed1ef5a1c3f4b8fdc6adfb
--- /dev/null
+++ b/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.html
@@ -0,0 +1,75 @@
+<div id="document-configuration-panel"
+     [formGroup]="documentConfigurationForm">
+
+  <mat-form-field class="form-field-full-width"
+                  subscriptSizing="dynamic"
+                  appearance="fill">
+    <mat-label>{{ "document.configuration.panel.label.name" | translate }}</mat-label>
+    <input matInput id="name_id"
+           formControlName="name"
+           >
+  </mat-form-field>
+  <mat-form-field class="form-field-full-width"
+                  subscriptSizing="dynamic"
+                  appearance="fill">
+    <mat-label>{{ "document.configuration.panel.label.mimetype" | translate }}</mat-label>
+    <input matInput id="mimeType_id"
+           formControlName="mimeType"
+           readonly>
+  </mat-form-field>
+
+  <mat-form-field class="form-field-full-width"
+                  subscriptSizing="dynamic"
+                  appearance="fill">
+    <mat-label>{{ "document.configuration.panel.label.published.version" | translate }}</mat-label>
+    <input matInput id="publishedVersion_id"
+           formControlName="publishedVersion"
+           readonly>
+  </mat-form-field>
+  <mat-checkbox formControlName="sharingEnabled"
+                (change)="onSharingEnabledChanged()"
+                matTooltip="{{ 'document.configuration.panel.tooltip.sharing.enabled' | translate }}"
+                id="sharingEnabled_id">
+    {{ "document.configuration.panel.label.sharing.enabled" | translate }}
+  </mat-checkbox>
+
+  <mat-toolbar class="mat-elevation-z2">
+    <mat-toolbar-row class="smp-toolbar-row">
+      <button mat-raised-button
+              mat-flat-button color="primary"
+              (click)="onShowSearchDialogClicked()"
+              [disabled]="disableShowReferenceDocumentButton"
+      >{{ "document.configuration.panel.button.reference.select" | translate }}
+      </button>
+
+      <button mat-raised-button
+              color="primary"
+              [disabled]="!hasReferenceDocument"
+              (click)="onClearReferenceDocument()">
+        <mat-icon>delete</mat-icon>
+        <span>{{ "document.configuration.panel.button.reference.clear" | translate }}</span>
+      </button>
+    </mat-toolbar-row>
+  </mat-toolbar>
+
+  <div class="panel" *ngIf="hasReferenceDocument;else noDataFound">
+    <mat-form-field class="form-field-full-width"
+                    subscriptSizing="dynamic"
+                    appearance="fill">
+      <mat-label>{{ "document.configuration.panel.label.reference.document.name" | translate }}</mat-label>
+      <input matInput id="reference-document-name_id"
+             formControlName="referenceDocumentName"
+             readonly>
+    </mat-form-field>
+    <a *ngIf="hasReferenceDocumentUrl"
+       target="_blank"
+       href="{{getReferencePartialURL()}}">{{ "document.configuration.panel.label.reference.document.open.url" | translate }}</a>
+
+  </div>
+  <ng-template #noDataFound>
+    <div id="no_document-reference_id" style="padding: 1em 0.4px ">
+      {{ "document.configuration.panel.label.reference.document.not.selected" | translate }}
+    </div>
+  </ng-template>
+</div>
+
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.scss b/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.scss
similarity index 75%
rename from smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.scss
rename to smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.scss
index 1742cb8ef27597392c89a83b3a84af4803125af5..4c9833c1926ed9bd3d6c4ad3ac0d4f8b1d60cabd 100644
--- a/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.scss
+++ b/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.scss
@@ -1,4 +1,4 @@
-#document-metadata-panel {
+#document-configuration-panel {
   display: flex;
   flex-direction: column;
   flex-grow: 1;
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.ts b/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..13977bc1f8033ac3db4af77060a678eec7ab1ffc
--- /dev/null
+++ b/smp-angular/src/app/common/panels/document-edit-panel/document-configuration-panel/document-configuration-panel.component.ts
@@ -0,0 +1,251 @@
+/*-
+ * #START_LICENSE#
+ * smp-webapp
+ * %%
+ * Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
+ * %%
+ * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
+ * versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ *
+ * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
+ * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ * #END_LICENSE#
+ */
+import {
+  AfterViewInit,
+  Component,
+  forwardRef,
+  Input,
+  OnInit,
+  ViewChild,
+} from '@angular/core';
+import {
+  ControlContainer,
+  ControlValueAccessor,
+  FormBuilder,
+  FormControl,
+  FormControlDirective,
+  FormGroup,
+  NG_VALUE_ACCESSOR
+} from "@angular/forms";
+import {MatDialog} from "@angular/material/dialog";
+import {
+  BeforeLeaveGuard
+} from "../../../../window/sidenav/navigation-on-leave-guard";
+import {
+  DocumentConfigurationRo
+} from "../../../model/document-configuration-ro.model";
+import {
+  ReferenceDocumentDialogComponent
+} from "../../../dialogs/reference-document-dialog/reference-document-dialog.component";
+import {
+  DocumentReferenceType
+} from "../../../enums/documetn-reference-type.enum";
+import {ResourceRo} from "../../../model/resource-ro.model";
+import {SubresourceRo} from "../../../model/subresource-ro.model";
+import {
+  SearchReferenceDocument
+} from "../../../model/search-reference-document-ro.model";
+
+/**
+ * Component to display the properties of a document in a table. The properties can be edited and saved.
+ * @author Joze Rihtarsic
+ * @since 5.1
+ */
+@Component({
+  selector: 'document-configuration-panel',
+  templateUrl: './document-configuration-panel.component.html',
+  styleUrls: ['./document-configuration-panel.component.scss'],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => DocumentConfigurationPanelComponent),
+      multi: true
+    }
+  ]
+})
+export class DocumentConfigurationPanelComponent implements OnInit, AfterViewInit, BeforeLeaveGuard, ControlValueAccessor {
+
+  private onChangeCallback: (_: any) => void = () => {
+  };
+
+  _contextPath: string = location.pathname.substring(0, location.pathname.length - 3); // remove /ui s
+  _documentConfiguration: DocumentConfigurationRo;
+  documentConfigurationForm: FormGroup;
+  @ViewChild(FormControlDirective, {static: true})
+  formControlDirective: FormControlDirective;
+  @Input() formControl: FormControl;
+  @Input() formControlName: string;
+  @Input() resource: ResourceRo;
+  @Input() subresource: SubresourceRo;
+
+  constructor(
+    public dialog: MatDialog,
+    private controlContainer: ControlContainer,
+    private formBuilder: FormBuilder) {
+
+    this.documentConfigurationForm = this.formBuilder.group({
+      'name': new FormControl({value: null}),
+      'mimeType': new FormControl({value: null}),
+      'publishedVersion': new FormControl({value: null}),
+      'sharingEnabled': new FormControl({value: null}),
+      'allVersions': new FormControl({value: null}),
+      'referenceDocumentId': new FormControl({value: null}),
+      'referenceDocumentName': new FormControl({value: null}),
+      'referenceDocumentUrl': new FormControl({value: null}),
+    });
+  }
+
+  ngOnInit(): void {
+    // subscribe to form changes and propagate them to the parent
+    this.documentConfigurationForm.valueChanges.subscribe(() => {
+      this.onChangeCallback(this.documentConfiguration);
+    });
+  }
+
+
+  get control() {
+    return this.formControl || this.controlContainer.control.get(this.formControlName);
+  }
+
+  /**
+   * Implementation of the ControlValueAccessor method to  write value to the component.
+   * @param eventList
+   */
+  writeValue(data: DocumentConfigurationRo): void {
+    this.documentConfiguration = data;
+    this.updateShareCheckboxStatus();
+  }
+
+  ngAfterViewInit() {
+
+  }
+
+
+  isDirty(): boolean {
+    return this.documentConfigurationForm.dirty;
+  }
+
+  registerOnChange(fn: any): void {
+    this.onChangeCallback = fn;
+
+  }
+
+  registerOnTouched(fn: any): void {
+    // not implemented
+  }
+
+  setDisabledState(isDisabled: boolean): void {
+    // not implemented
+  }
+
+
+  @Input() set documentConfiguration(value: DocumentConfigurationRo) {
+    this._documentConfiguration = value;
+    this.documentConfigurationForm.disable();
+
+    if (!!value) {
+      this.documentConfigurationForm.controls['name'].setValue(value.name);
+      this.documentConfigurationForm.controls['mimeType'].setValue(value.mimeType);
+      this.documentConfigurationForm.controls['publishedVersion'].setValue(value.publishedVersion);
+      this.documentConfigurationForm.controls['allVersions'].setValue(value.allVersions);
+      this.documentConfigurationForm.controls['sharingEnabled'].setValue(value.sharingEnabled);
+
+      this.documentConfigurationForm.controls['referenceDocumentId'].setValue(value.referenceDocumentId);
+      this.documentConfigurationForm.controls['referenceDocumentName'].setValue(value.referenceDocumentName);
+      this.documentConfigurationForm.controls['referenceDocumentUrl'].setValue(value.referenceDocumentUrl);
+
+      // allow to change name and sharing attribute
+      this.documentConfigurationForm.controls['name'].enable();
+      this.documentConfigurationForm.controls['sharingEnabled'].enable();
+    } else {
+      this.documentConfigurationForm.controls['name'].setValue("");
+      this.documentConfigurationForm.controls['mimeType'].setValue("");
+      this.documentConfigurationForm.controls['publishedVersion'].setValue("");
+      this.documentConfigurationForm.controls['allVersions'].setValue([]);
+      this.documentConfigurationForm.controls['sharingEnabled'].setValue(false);
+      this.documentConfigurationForm.controls['referenceDocumentId'].setValue("");
+      this.documentConfigurationForm.controls['referenceDocumentName'].setValue("");
+      this.documentConfigurationForm.controls['referenceDocumentUrl'].setValue("");
+    }
+    this.documentConfigurationForm.markAsPristine();
+  }
+
+  get documentConfiguration(): DocumentConfigurationRo {
+    let docConf: DocumentConfigurationRo = {...this._documentConfiguration};
+
+    // set new updated values
+    docConf.sharingEnabled = this.documentConfigurationForm.controls['sharingEnabled'].value;
+    docConf.name = this.documentConfigurationForm.controls['name'].value;
+    docConf.referenceDocumentId = this.documentConfigurationForm.controls['referenceDocumentId'].value;
+    docConf.referenceDocumentName = this.documentConfigurationForm.controls['referenceDocumentName'].value;
+    docConf.referenceDocumentUrl = this.documentConfigurationForm.controls['referenceDocumentUrl'].value;
+
+    return docConf;
+  }
+
+  get hasReferenceDocument(): boolean {
+    let val = this.documentConfigurationForm.controls['referenceDocumentId']?.value;
+    return !!val && val.length > 0;
+  }
+
+  get hasReferenceDocumentUrl(): boolean {
+    return !!this.documentConfigurationForm.controls['referenceDocumentUrl']?.value;
+  }
+
+  getReferencePartialURL() {
+    if (this.hasReferenceDocumentUrl) {
+      return this._contextPath + this.documentConfigurationForm.controls['referenceDocumentUrl'].value;
+    }
+    return "";
+  }
+
+
+  onShowSearchDialogClicked() {
+    this.dialog.open(ReferenceDocumentDialogComponent, {
+      data: {
+        targetType: !this.subresource? DocumentReferenceType.RESOURCE:DocumentReferenceType.SUBRESOURCE,
+        targetResource: this.resource,
+        targetSubresource: this.subresource,
+      }
+    }).afterClosed().subscribe((value: SearchReferenceDocument) => {
+      if (!!value) {
+        this.documentConfigurationForm.controls['referenceDocumentId'].setValue(value.documentId);
+        this.documentConfigurationForm.controls['referenceDocumentName'].setValue(value.documentName);
+        this.documentConfigurationForm.controls['referenceDocumentUrl'].setValue(value.referenceUrl);
+        this.onChangeCallback(this.documentConfiguration);
+        this.updateShareCheckboxStatus();
+      }
+    });
+  }
+
+  onSharingEnabledChanged() {
+    this.updateShareCheckboxStatus();
+  }
+
+  updateShareCheckboxStatus() {
+    if (this.hasReferenceDocument) {
+      this.documentConfigurationForm.controls['sharingEnabled'].setValue(false);
+      this.documentConfigurationForm.controls['sharingEnabled'].disable();
+    } else {
+      this.documentConfigurationForm.controls['sharingEnabled'].enable();
+    }
+  }
+
+  onClearReferenceDocument(): void {
+    this.documentConfigurationForm.controls['referenceDocumentId'].setValue("");
+    this.documentConfigurationForm.controls['referenceDocumentName'].setValue("");
+    this.documentConfigurationForm.controls['referenceDocumentUrl'].setValue("");
+    this.updateShareCheckboxStatus()
+  }
+
+  get disableShowReferenceDocumentButton(): boolean {
+    return this.hasReferenceDocument || this.documentConfigurationForm.controls['sharingEnabled'].value;
+  }
+
+}
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.html b/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.html
index 421cf2232f40b91bd5844b77996c33f13032edc3..816fbf35c532eb3090eccff247a303df6150631a 100644
--- a/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.html
+++ b/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.html
@@ -8,15 +8,16 @@
               mat-raised-button
               color="primary"
               matTooltip="{{ 'document.edit.panel.tooltip.version.new' | translate }}"
-              [disabled]="emptyDocument"
+              [disabled]="newVersionButtonDisabled || showReference"
               (click)="onNewDocumentVersionButtonClicked()">
         <mat-icon>add_circle</mat-icon>
         <span>{{ "document.edit.panel.button.version.new" | translate }}</span>
       </button>
       <button id="validateResource_id" mat-raised-button
+              *ngIf="isNotReviewMode"
               color="primary"
               matTooltip="{{ 'document.edit.panel.tooltip.validate' | translate }}"
-              [disabled]="emptyDocument"
+              [disabled]="!documentEditable"
               (click)="onDocumentValidateButtonClicked()">
         <mat-icon>check_circle</mat-icon>
         <span>{{ "document.edit.panel.button.validate" | translate }}</span>
@@ -48,56 +49,91 @@
        style="display: flex;flex-direction: row;flex-grow: 1; ">
     <div
       style="display:flex; overflow: auto;flex: 2;align-self: stretch; flex-direction: column;">
+      <ng-container *ngIf="hasDocumentReference && isNotReviewMode; else selectedDocumentVersionDataTemplate" >
+        <div style="display:flex;  flex-direction: row;align-items: center;">
+          <mat-form-field style="min-width: 250px"
+                          subscriptSizing="dynamic"
+                          appearance="fill">
+            <mat-label>{{ "document.edit.panel.label.show.document.type" | translate }}</mat-label>
+          <mat-select style="width: 250px;"
+                      formControlName="selectDocumentSource"
+                      (selectionChange)="updateTextToEditor()">
+            <mat-option value="TARGET_DOCUMENT">{{ "document.edit.panel.select.item.current"  | translate }}</mat-option>
+            <mat-option value="REFERENCE_DOCUMENT" >{{ "document.edit.panel.select.item.reference" | translate }}</mat-option>
+          </mat-select>
+          </mat-form-field>
+        <ng-container *ngIf="showReference; else selectedDocumentVersionDataTemplate" >
+          <div style="padding: 0 1em;display: flex;flex-direction: row;align-items: center;">
+          <mat-form-field style="min-width: 250px"
+                          subscriptSizing="dynamic"
+                          appearance="fill">
+            <mat-label>{{ "document.edit.panel.label.reference.name" | translate }}</mat-label>
+            <input matInput id="reference-name_id"
+                   formControlName="documentReferenceName">
+          </mat-form-field>
+          <a *ngIf="hasReferenceDocumentUrl"
+             target="_blank"
+             href="{{getReferencePartialURL()}}">{{ "document.configuration.panel.label.reference.document.open.url" | translate }}</a>
+          </div>
+        </ng-container>
+        </div>
+      </ng-container>
 
-      <div style="display: flex;flex-direction: row">
-        <mat-form-field style="min-width: 140px"
-                        subscriptSizing="dynamic"
-                        appearance="fill"
-        >
-          <mat-label>{{ "document.edit.panel.label.selected.version" | translate }}</mat-label>
-          <mat-select
+      <ng-template #selectedDocumentVersionDataTemplate>
+        <div style="display: flex;flex-direction: row">
+          <mat-form-field style="min-width: 140px"
+                          subscriptSizing="dynamic"
+                          appearance="fill"
+          >
+            <mat-label>{{ "document.edit.panel.label.selected.version" | translate }}</mat-label>
+            <mat-select
+
+              placeholder="{{ 'document.edit.panel.placeholder.version' | translate }}"
+              matTooltip="{{ 'document.edit.panel.tooltip.version' | translate }}"
+              id="document-version_id"
+              formControlName="payloadVersion"
+              (selectionChange)="onSelectionDocumentVersionChanged()">
+              <mat-option *ngFor="let version of getDocumentVersions"
+                          [value]="version">
+                {{ version }}
+              </mat-option>
+            </mat-select>
+          </mat-form-field>
+
+          <mat-form-field style="min-width: 180px"
+                          subscriptSizing="dynamic"
+                          appearance="fill">
+            <mat-label>{{ "document.edit.panel.label.selected.status" | translate }}</mat-label>
+            <input matInput id="status_id"
+                   formControlName="documentVersionStatus"
+                   readonly>
+          </mat-form-field>
+          <mat-form-field style="width:100%"
+                          subscriptSizing="dynamic"
+                          appearance="fill">
+            <mat-label>{{ "document.edit.panel.label.selected.created.on" | translate }}</mat-label>
+            <input id="payloadCreatedOn_id"
+                   matInput [ngxMatDatetimePicker]="payloadCreatedOnPicker"
+                   formControlName="payloadCreatedOn"
+                   readonly>
+            <mat-datepicker-toggle matSuffix [for]="payloadCreatedOnPicker"
+                                   style="visibility: hidden"></mat-datepicker-toggle>
+            <ngx-mat-datetime-picker #payloadCreatedOnPicker [showSpinners]="true"
+                                     [showSeconds]="false"
+                                     [hideTime]="false"></ngx-mat-datetime-picker>
+          </mat-form-field>
+        </div>
+      </ng-template>
 
-            placeholder="{{ 'document.edit.panel.placeholder.version' | translate }}"
-            matTooltip="{{ 'document.edit.panel.tooltip.version' | translate }}"
-            id="document-version_id"
-            formControlName="payloadVersion"
-            (selectionChange)="onSelectionDocumentVersionChanged()">
-            <mat-option *ngFor="let version of getDocumentVersions"
-                        [value]="version">
-              {{ version }}
-            </mat-option>
-          </mat-select>
-        </mat-form-field>
 
-        <mat-form-field style="min-width: 180px"
-                        subscriptSizing="dynamic"
-                        appearance="fill">
-          <mat-label>{{ "document.edit.panel.label.selected.status" | translate }}</mat-label>
-          <input matInput id="status_id"
-                 formControlName="documentVersionStatus"
-                 readonly>
-        </mat-form-field>
-        <mat-form-field style="width:100%"
-                        subscriptSizing="dynamic"
-                        appearance="fill">
-          <mat-label>{{ "document.edit.panel.label.selected.created.on" | translate }}</mat-label>
-          <input id="payloadCreatedOn_id"
-                 matInput [ngxMatDatetimePicker]="payloadCreatedOnPicker"
-                 formControlName="payloadCreatedOn"
-                 readonly>
-          <mat-datepicker-toggle matSuffix [for]="payloadCreatedOnPicker"
-                                 style="visibility: hidden"></mat-datepicker-toggle>
-          <ngx-mat-datetime-picker #payloadCreatedOnPicker [showSpinners]="true"
-                                   [showSeconds]="false"
-                                   [hideTime]="false"></ngx-mat-datetime-picker>
-        </mat-form-field>
-      </div>
       <div
         style="display:block; overflow: auto;flex: 2;align-self: stretch; flex-direction: column;border: ridge 3px #b0bec5"
         (click)="onEditPanelClick()">
-        <smp-editor #smpDocumentEditor formControlName="payload"
+        <smp-editor #smpDocumentEditor
+                    formControlName="editorText"
                     ngDefaultControl></smp-editor>
 
+
       </div>
       <smp-warning-panel *ngIf="!documentEditable"
                          icon="info"
@@ -106,13 +142,25 @@
       </smp-warning-panel>
     </div>
     <expandable-panel>
-      <expandable-item icon="description"
-                       title="{{'document.metadata.panel.tab.title' | translate }}"
-                       buttonLabel="{{'document.metadata.panel.tab.button.properties' | translate }}">
-        <document-metadata-panel formControlName="documentMetadata"
-                                 ngDefaultControl></document-metadata-panel>
+      <!-- The document version panels -->
+      <expandable-item icon="event"
+                       showButtonSpacer="true"
+                       title="{{'document.events.panel.tab.title' | translate }}"
+                       buttonLabel="{{'document.events.panel.tab.button.events' | translate }}">
+        <document-events-panel formControlName="documentVersionEvents"
+                               ngDefaultControl></document-events-panel>
       </expandable-item>
+      <!-- The document panels -->
       <expandable-item icon="settings"
+                       showButtonSpacer="true"
+                       title="{{'document.configuration.panel.tab.title' | translate }}"
+                       buttonLabel="{{'document.configuration.panel.tab.button.properties' | translate }}">
+        <document-configuration-panel formControlName="documentConfiguration"
+                                 [resource]="resource"
+                                 [subresource]="subresource"
+                                 ngDefaultControl></document-configuration-panel>
+      </expandable-item>
+      <expandable-item icon="description"
                        title="{{'document.properties.panel.tab.title' | translate }}"
                        buttonLabel="{{'document.properties.panel.tab.button.properties' | translate }}">
         <document-properties-panel formControlName="properties"
@@ -124,17 +172,12 @@
                        title="{{'document.versions.panel.tab.title' | translate }}"
                        buttonLabel="{{'document.versions.panel.tab.button.versions' | translate }}">
         <document-versions-panel
-                              formControlName="documentVersions"
-                                [selectedVersion]="currentDocumentVersion"
-                                 (selectedVersionChange) = "loadDocumentForVersion($event)"
-                                 ngDefaultControl></document-versions-panel>
-      </expandable-item>
-      <expandable-item icon="event"
-                       title="{{'document.events.panel.tab.title' | translate }}"
-                       buttonLabel="{{'document.events.panel.tab.button.events' | translate }}">
-        <document-events-panel formControlName="documentVersionEvents"
-                               ngDefaultControl></document-events-panel>
+          formControlName="documentVersions"
+          [selectedVersion]="currentDocumentVersion"
+          (selectedVersionChange)="loadDocumentForVersion($event)"
+          ngDefaultControl></document-versions-panel>
       </expandable-item>
+
     </expandable-panel>
   </div>
 
@@ -175,33 +218,35 @@
         <mat-icon>publish</mat-icon>
         <span>{{ "document.edit.panel.button.version.publish" | translate }}</span>
       </button>
-      <tool-button-spacer></tool-button-spacer>
-      <button *ngIf="reviewEnabled && isNotReviewMode" id="reviewResource_id" mat-raised-button
-              color="primary"
-              matTooltip="{{ 'document.edit.panel.tooltip.version.review' | translate }}"
-              [disabled]="reviewButtonDisabled"
-              (click)="onReviewRequestButtonClicked()">
-        <mat-icon>task</mat-icon>
-        <span>{{ "document.edit.panel.button.version.review" | translate }}</span>
-      </button>
-      <button mat-raised-button
-              *ngIf="!isNotReviewMode || reviewEnabled"
-              color="primary"
-              matTooltip="{{ 'document.edit.panel.tooltip.version.approve' | translate }}"
-              [disabled]="reviewActionButtonDisabled"
-              (click)="onApproveButtonClicked()">
-        <mat-icon>check_circle</mat-icon>
-        <span>{{ "document.edit.panel.button.version.approve" | translate }}</span>
-      </button>
-      <button mat-raised-button
-              *ngIf="!isNotReviewMode || reviewEnabled"
-              color="primary"
-              matTooltip="{{ 'document.edit.panel.tooltip.version.reject' | translate }}"
-              [disabled]="reviewActionButtonDisabled"
-              (click)="onRejectButtonClicked()">
-        <mat-icon>unpublished</mat-icon>
-        <span>{{ "document.edit.panel.button.version.reject" | translate }}</span>
-      </button>
+      <ng-container *ngIf="reviewEnabled">
+        <tool-button-spacer></tool-button-spacer>
+        <button *ngIf="isNotReviewMode" id="reviewResource_id"
+                mat-raised-button
+                color="primary"
+                matTooltip="{{ 'document.edit.panel.tooltip.version.request.review' | translate }}"
+                [disabled]="reviewButtonDisabled"
+                (click)="onReviewRequestButtonClicked()">
+          <mat-icon>task</mat-icon>
+          <span>{{ "document.edit.panel.button.version.review.request" | translate }}</span>
+        </button>
+        <button mat-raised-button
+                *ngIf="!isNotReviewMode || hasReviewPermission"
+                color="primary"
+                matTooltip="{{ 'document.edit.panel.tooltip.version.review.approve' | translate }}"
+                [disabled]="reviewActionButtonDisabled"
+                (click)="onApproveButtonClicked()">
+          <mat-icon>check_circle</mat-icon>
+          <span>{{ "document.edit.panel.button.version.review.approve" | translate }}</span>
+        </button>
+        <button mat-raised-button
+                color="primary"
+                matTooltip="{{ 'document.edit.panel.tooltip.version.review.reject' | translate }}"
+                [disabled]="reviewActionButtonDisabled"
+                (click)="onRejectButtonClicked()">
+          <mat-icon>unpublished</mat-icon>
+          <span>{{ "document.edit.panel.button.version.review.reject" | translate }}</span>
+        </button>
+      </ng-container>
     </mat-toolbar-row>
   </mat-toolbar>
 </div>
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.ts b/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.ts
index b6533c56d648be2faae7fa0d0a251f49dd921404..121058383b02a6aef1c8e2897d8937aa9253fd02 100644
--- a/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.ts
+++ b/smp-angular/src/app/common/panels/document-edit-panel/document-edit-panel.component.ts
@@ -67,6 +67,11 @@ export enum SmpReviewDocumentTarget {
   SUBRESOURCE = "SUBRESOURCE",
 }
 
+export enum SmpShowDocumentType {
+  REFERENCE_DOCUMENT = "REFERENCE_DOCUMENT",
+  TARGET_DOCUMENT = "TARGET_DOCUMENT",
+}
+
 /**
  * Component edit panel for document and document version management.
  * Please not the document version management can change the document (version) entities only
@@ -99,10 +104,15 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
   readonly reviewAllowedStatusList: DocumentVersionsStatus[] = [DocumentVersionsStatus.DRAFT, DocumentVersionsStatus.REJECTED, DocumentVersionsStatus.RETIRED];
   readonly editableDocStatusList: DocumentVersionsStatus[] = [DocumentVersionsStatus.DRAFT, DocumentVersionsStatus.REJECTED, DocumentVersionsStatus.RETIRED];
   readonly publishableDocStatusList: DocumentVersionsStatus[] = [DocumentVersionsStatus.DRAFT, DocumentVersionsStatus.APPROVED, DocumentVersionsStatus.RETIRED];
-  private resource: ResourceRo;
-  private subresource: SubresourceRo;
+
+  protected resource: ResourceRo;
+  protected subresource: SubresourceRo;
   private reviewDocument: ReviewDocumentVersionRo;
-  private isResourceDocument:boolean = true;
+
+  protected isResourceDocument: boolean = true;
+  private isEditorReferencePayload: boolean = false;
+  private resetVersionOnNewDocument: number;
+  _contextPath: string = location.pathname.substring(0, location.pathname.length - 3); // remove /ui s
 
   _document: DocumentRo;
   @Input() private group: GroupRo;
@@ -180,7 +190,9 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       } else {
         this.alertService.success(await lastValueFrom(this.translateService.get("document.edit.panel.success.generate")))
         this.documentForm.controls['payload'].setValue(doc.payload);
+        this.updateTextToEditor()
         this.documentForm.controls['payload'].markAsDirty();
+        this.documentForm.controls['editorText'].markAsDirty();
       }
     },
     error: (err: any) => {
@@ -206,17 +218,24 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       'payloadCreatedOn': new FormControl({value: null}),
       'payloadVersion': new FormControl({value: null}),
       'payload': new FormControl({value: null}),
+      'referencePayload': new FormControl({value: null}),
       'properties': new FormControl({value: null}),
       'documentVersionStatus': new FormControl({value: null}),
       'documentVersionEvents': new FormControl({value: null}),
       'documentVersions': new FormControl({value: null}),
-      'documentMetadata': new FormControl({value: null}),
+      'documentConfiguration': new FormControl({value: null}),
+      "documentReferenceName": new FormControl({value: null}),
+      // additional fields
+      "editorText": new FormControl({value: null}),
+      "toggleReferenceDocument": new FormControl({value: null}),
+      "selectDocumentSource": new FormControl({value: null}),
     });
 
     this.resource = editResourceService.selectedResource;
     this.subresource = editResourceService.selectedSubresource;
     this.reviewDocument = editResourceService.selectedReviewDocument;
     this.documentForm.controls['payload'].setValue("")
+    this.documentForm.controls['editorText'].setValue("")
   }
 
   /**
@@ -256,7 +275,6 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
     } else {
       this.isResourceDocument = this.editorMode === SmpDocumentEditorType.RESOURCE_EDITOR;
     }
-
     if (this.editorMode === SmpDocumentEditorType.REVIEW_EDITOR && !this.reviewDocument
       || this.editorMode !== SmpDocumentEditorType.REVIEW_EDITOR && !this.resource) {
       this.alertService.errorForTranslation("document.edit.panel.error.document.null");
@@ -267,13 +285,24 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       this.loadDocumentForVersion(this.reviewDocument.version);
     } else {
       this.loadDocumentForVersion();
+      // show reference by default
+      this.documentForm.controls['selectDocumentSource'].setValue(SmpShowDocumentType.REFERENCE_DOCUMENT);
     }
+    this.documentForm.controls['editorText'].valueChanges.subscribe(() => {
+      // disable change back option
+      if (this.documentEditable) {
+        this.documentForm.controls['selectDocumentSource'].disable();
+      } else {
+        this.documentForm.controls['selectDocumentSource'].enable();
+      }
+    });
   }
 
 
   @Input() set document(value: DocumentRo) {
     this._document = value;
     this.documentForm.disable();
+    // always enable the reference in title
     if (!!value) {
       this.documentEditor.mimeType = value.mimeType;
       this.documentForm.controls['mimeType'].setValue(value.mimeType);
@@ -282,49 +311,124 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       this.documentForm.controls['payloadVersion'].setValue(value.payloadVersion);
       this.documentForm.controls['payloadCreatedOn'].setValue(value.payloadCreatedOn);
       this.documentForm.controls['payload'].setValue(value.payload);
+      this.documentForm.controls['editorText'].setValue(value.payload);
+      this.documentForm.controls['referencePayload'].setValue(value.referencePayload);
       this.documentForm.controls['properties'].setValue(value.properties);
       this.documentForm.controls['documentVersionStatus'].setValue(value.documentVersionStatus);
       this.documentForm.controls['documentVersionEvents'].setValue(value.documentVersionEvents);
       this.documentForm.controls['documentVersions'].setValue(value.documentVersions);
-      this.documentForm.controls['documentMetadata'].setValue(value.metadata);
+      this.documentForm.controls['documentConfiguration'].setValue(value.documentConfiguration);
+      this.documentForm.controls['documentReferenceName'].setValue(value.documentConfiguration?.referenceDocumentName);
       // the method documentVersionsExists already uses the current value to check if versions exists
-
-      if (this.documentVersionsExists && this.isNotReviewMode) {
+      if (this.documentVersionsExists && this.isNotReviewMode && !this.isNewDocumentVersion) {
         this.documentForm.controls['payloadVersion'].enable();
       }
-      if (this.documentEditable) {
-        this.documentForm.controls['payload'].enable();
+      if (!this.documentEditable && !this.isNewDocumentVersion) {
+        this.documentForm.controls['selectDocumentSource'].enable();
       }
+      this.updateTextToEditor()
+      this.documentForm.markAsPristine();
     } else {
+      this.documentForm.controls['selectDocumentSource'].setValue(SmpShowDocumentType.TARGET_DOCUMENT);
+      this.documentForm.controls['mimeType'].setValue("");
       this.documentForm.controls['name'].setValue("");
       this.documentForm.controls['currentResourceVersion'].setValue("");
       this.documentForm.controls['payloadVersion'].setValue("");
       this.documentForm.controls['payloadCreatedOn'].setValue("");
       this.documentForm.controls['payload'].setValue("");
+      this.documentForm.controls['editorText'].setValue("");
+      this.documentForm.controls['referencePayload'].setValue("");
       this.documentForm.controls['properties'].setValue([]);
       this.documentForm.controls['documentVersionStatus'].setValue("");
       this.documentForm.controls['documentVersionEvents'].setValue([]);
       this.documentForm.controls['documentVersions'].setValue([]);
-      this.documentForm.controls['documentMetadata'].setValue(null);
+      this.documentForm.controls['documentConfiguration'].setValue(null);
+      this.documentForm.markAsPristine();
     }
-    this.documentForm.markAsPristine();
   }
 
+  /**
+   * Methods returns a clone of the document object with the current values from the form
+   * to be submitted to the server for, create, update, delete or other actions.
+   */
   get document(): DocumentRo {
     let doc: DocumentRo = {...this._document};
-    if (this.documentForm.controls['payload'].dirty) {
+
+    console.log("show reference: " + this.showReference + " payload dirty: " + this.documentForm.controls['payload'].dirty
+      + " editor dirty: " + this.documentForm.controls['editorText'].dirty)
+
+    if (this.showReference !== true && this.documentForm.controls['editorText'].dirty === true) {
+      console.log("Set payload from the text editor")
+      doc.payload = this.documentForm.controls['editorText'].value;
+      console.log("Set payload from the text editor: " + doc.payload)
+      doc.payloadStatus = EntityStatus.UPDATED;
+    } else if (this.showReference === true && this.documentForm.controls['payload'].dirty === true) {
       doc.payload = this.documentForm.controls['payload'].value;
+      console.log("Set payload from the payload control valuer")
       doc.payloadStatus = EntityStatus.UPDATED;
     } else {
       // no need to send payload if not changed
+      console.log("No need to send  payload if not changed")
       doc.payload = null;
+
     }
+    // no need to send reference payload if not changed
+    doc.referencePayload = null;
+
     // set new properties
     doc.properties = this.documentForm.controls['properties'].value;
-    doc.metadata = this.documentForm.controls['documentMetadata'].value;
+    doc.documentConfiguration = this.documentForm.controls['documentConfiguration'].value;
     return doc;
   }
 
+  /**
+   * When document is changed the method updates the editor text. If it contains a referemce and
+   * is showing then, reference payload is shown in the editor, otherwise the payload is shown.
+   */
+  updateTextToEditor() {
+
+    // set data
+    if (this.showReference) {
+      if (this.isEditorReferencePayload) {
+        // the reference is already displayed
+        this.updateSourceSelectionComponent();
+        return;
+      }
+      if (this.documentForm.controls['editorText'].dirty) {
+        this.documentForm.controls['payload'].setValue(this.documentForm.controls['editorText'].value);
+      }
+      this.documentForm.controls['editorText'].setValue(this.documentForm.controls['referencePayload'].value);
+      this.documentForm.controls['editorText'].disable();
+      this.documentForm.controls['editorText'].markAsPristine();
+      this.isEditorReferencePayload = true;
+    } else {
+      //
+      this.documentForm.controls['editorText'].setValue(this.documentForm.controls['payload'].value);
+      this.documentForm.controls['editorText'].markAsPristine();
+      if (this.documentEditable) {
+        this.documentForm.controls['editorText'].enable();
+      } else {
+        this.documentForm.controls['editorText'].disable();
+      }
+      this.isEditorReferencePayload = false;
+    }
+    this.updateSourceSelectionComponent();
+  }
+
+  /**
+   * Method to update the source selection component
+   */
+  private updateSourceSelectionComponent() {
+    // reset the control selectDocumentSource because it most not affect the
+    // documentForm form
+    this.documentForm.controls['selectDocumentSource'].markAsPristine();
+    if (!this.showReference && this.documentForm.controls['editorText'].dirty) {
+      this.documentForm.controls['selectDocumentSource'].disable();
+    } else {
+      this.documentForm.controls['selectDocumentSource'].enable();
+    }
+  }
+
   onBackButtonClicked(): void {
     this.navigationService.navigateUp();
   }
@@ -343,17 +447,19 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
   }
 
   resetChanges() {
-    let currentVersion = this._document?.payloadVersion;
+    let currentVersion = this.isNewDocumentVersion ?
+      this.resetVersionOnNewDocument : this._document?.payloadVersion;
     if (!currentVersion) {
       this.documentForm.controls['payload'].setValue("");
       this.documentForm.markAsPristine();
+      this.updateTextToEditor()
     } else {
       this.loadDocumentForVersion(currentVersion);
     }
   }
 
   get currentDocumentVersion(): number {
-    return this.isNotReviewMode? this.documentForm.controls['payloadVersion']?.value:
+    return this.isNotReviewMode ? this.documentForm.controls['payloadVersion']?.value :
       this.reviewDocument?.version;
   }
 
@@ -365,6 +471,7 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
   }
 
   onReviewRequestButtonClicked(): void {
+
     // create lightweight document object
     let docRequest: DocumentRo = {
       documentId: this._document.documentId,
@@ -378,7 +485,21 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
     onReviewRequestObservable.subscribe(this.loadDocumentObserver);
   }
 
-  onApproveButtonClicked(): void {
+
+  async onApproveButtonClicked() {
+    this.dialog.open(ConfirmationDialogComponent, {
+      data: {
+        title: await lastValueFrom(this.translateService.get("document.edit.panel.review.dialog.confirmation.title")),
+        description: await lastValueFrom(this.translateService.get("document.edit.panel.review.dialog.confirmation.approve.description"))
+      }
+    }).afterClosed().subscribe(result => {
+      if (result) {
+        this.submitReviewApproveAction()
+      }
+    });
+  }
+
+  private submitReviewApproveAction() {
     // create lightweight document object
     let docRequest: DocumentRo = {
       documentId: this._document.documentId,
@@ -390,9 +511,27 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       this.editResourceService.reviewApproveForSubresourceDocumentObservable(this.subresource, this.resource, docRequest);
     // request review
     onReviewRequestObservable.subscribe(this.reviewActionDocumentObserver);
+
+    if (!this.isNotReviewMode) {
+      this.onBackButtonClicked();
+    }
   }
 
-  onRejectButtonClicked(): void {
+
+  async onRejectButtonClicked() {
+    this.dialog.open(ConfirmationDialogComponent, {
+      data: {
+        title: await lastValueFrom(this.translateService.get("document.edit.panel.review.dialog.confirmation.title")),
+        description: await lastValueFrom(this.translateService.get("document.edit.panel.review.dialog.confirmation.reject.description"))
+      }
+    }).afterClosed().subscribe(result => {
+      if (result) {
+        this.submitReviewRejectAction()
+      }
+    });
+  }
+
+  private submitReviewRejectAction() {
     // create lightweight document object
     let docRequest: DocumentRo = {
       documentId: this._document.documentId,
@@ -404,13 +543,30 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       this.editResourceService.reviewRejectSubresourceDocumentObservable(this.subresource, this.resource, docRequest);
     // request review
     onReviewRequestObservable.subscribe(this.reviewActionDocumentObserver);
+    if (!this.isNotReviewMode) {
+      this.onBackButtonClicked();
+    }
   }
 
   /**
    * Publish the current document version
    *
    */
-  onPublishButtonClicked(): void {
+
+  async onPublishButtonClicked() {
+    this.dialog.open(ConfirmationDialogComponent, {
+      data: {
+        title: await lastValueFrom(this.translateService.get("document.edit.panel.dialog.confirmation.publish.title")),
+        description: await lastValueFrom(this.translateService.get("document.edit.panel.dialog.confirmation.publish.description"))
+      }
+    }).afterClosed().subscribe(result => {
+      if (result) {
+        this.submitPublishAction()
+      }
+    });
+  }
+
+  private submitPublishAction() {
     // create lightweight document object
     let docRequest: DocumentRo = {
       documentId: this._document.documentId,
@@ -449,9 +605,8 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
     });
     formRef.afterClosed().subscribe(result => {
       if (result) {
-        let val = formRef.componentInstance.getExtensionXML();
-        this.documentForm.controls['payload'].setValue(val);
-        this.documentForm.controls['payload'].markAsDirty();
+        let value = formRef.componentInstance.getExtensionXML();
+        this.updateDocumentPayload(value);
       }
     });
   }
@@ -467,10 +622,8 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       processIdentifier: '',
       processScheme: '',
       transportProfile: 'bdxr-transport-ebms3-as4-v1p0', // default value for oasis AS4
-
       endpointUrl: '',
       endpointCertificate: '',
-
       serviceDescription: '',
       technicalContactUrl: '',
 
@@ -481,13 +634,23 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
     });
     formRef.afterClosed().subscribe(result => {
       if (result) {
-        let smw: SubresourceWizardRo = formRef.componentInstance.getCurrent();
-        this.documentForm.controls['payload'].setValue(smw.contentXML);
-        this.documentForm.controls['payload'].markAsDirty();
+        let value: SubresourceWizardRo = formRef.componentInstance.getCurrent();
+        this.updateDocumentPayload(value.contentXML);
       }
     });
   }
 
+  private updateDocumentPayload(newContent: string) {
+    if (this.showReference) {
+      this.documentForm.controls['payload'].setValue(newContent);
+      this.documentForm.controls['payload'].markAsDirty();
+    } else {
+      this.documentForm.controls['editorText'].setValue(newContent)
+      this.documentForm.controls['editorText'].markAsDirty();
+
+    }
+  }
+
   /**
    * 'loadDocumentForVersion' load the document for the given version
    * @param version
@@ -504,9 +667,12 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
    * Submit the current document for validation to the server
    */
   validateCurrentDocument(): void {
+    let docRequest: DocumentRo = this.document;
+    // set the payload from the current editor text
+    docRequest.payload = this.documentForm.controls['editorText'].value;
     let validateObservable = this.isResourceDocument ?
-      this.editResourceService.validateResourceDocumentObservable(this.resource, this.document) :
-      this.editResourceService.validateSubresourceDocumentObservable(this.subresource, this.resource, this.document);
+      this.editResourceService.validateResourceDocumentObservable(this.resource, docRequest) :
+      this.editResourceService.validateSubresourceDocumentObservable(this.subresource, this.resource, docRequest);
     validateObservable.subscribe(this.validateDocumentObserver);
   }
 
@@ -516,22 +682,29 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
   }
 
   onNewDocumentVersionButtonClicked(): void {
+
+    this.resetVersionOnNewDocument = this.currentDocumentVersion;
     // create a new version of the document
     let docRequest: DocumentRo = {
+      documentId: this._document.documentId,
       documentVersionStatus: DocumentVersionsStatus.DRAFT,
       payloadStatus: EntityStatus.NEW,
       status: EntityStatus.UPDATED,
+      payloadVersion: null,
+      payloadCreatedOn: null,
       payload: this.documentForm.controls['payload'].value,
+      currentResourceVersion: this.documentForm.controls['currentResourceVersion'].value,
       allVersions: this.getDocumentVersions,
       // set from current document
       documentVersions: this.documentForm.controls['documentVersions'].value,
       properties: this.documentForm.controls['properties'].value,
-      metadata: this.documentForm.controls['documentMetadata'].value,
+      documentConfiguration: this.documentForm.controls['documentConfiguration'].value,
     } as DocumentRo;
     // set as current
     this.document = docRequest;
     this.documentForm.markAsDirty();
     this.documentForm.controls['payload'].markAsDirty();
+    this.documentForm.controls['editorText'].markAsDirty();
   }
 
   onSelectionDocumentVersionChanged(): void {
@@ -594,9 +767,17 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
       !this.publishableDocStatusList.find(i => i === status)
   }
 
+  get newVersionButtonDisabled(): boolean {
+    return this.isNewDocumentVersion
+  }
+
+  get isNewDocumentVersion(): boolean {
+    return this._document?.payloadStatus === EntityStatus.NEW
+  }
+
   get documentEditable(): boolean {
     let status = this.documentForm.controls['documentVersionStatus']?.value
-    return !!this.editableDocStatusList.find(i => i === status)
+    return !!this.editableDocStatusList.find(i => i === status) && !this.showReference;
   }
 
   get documentSubmitReviewAllowed(): boolean {
@@ -612,6 +793,31 @@ export class DocumentEditPanelComponent implements BeforeLeaveGuard, OnInit {
     return this.editorMode !== SmpDocumentEditorType.REVIEW_EDITOR;
   }
 
+  get hasReviewPermission(): boolean {
+    return this.resource?.hasCurrentUserReviewPermission;
+  }
+
+  get hasDocumentReference(): boolean {
+    return !!this._document?.documentConfiguration?.referenceDocumentId;
+  }
+
+  get showReference(): boolean {
+    return this.hasDocumentReference && this.documentForm.controls['selectDocumentSource'].value === SmpShowDocumentType.REFERENCE_DOCUMENT;
+  }
+
+
+  get hasReferenceDocumentUrl(): boolean {
+    return this.hasDocumentReference && !!this._document?.documentConfiguration?.referenceDocumentUrl;
+  }
+
+  getReferencePartialURL() {
+    if (this.hasReferenceDocumentUrl) {
+      return this._contextPath + this._document?.documentConfiguration?.referenceDocumentUrl;
+    }
+    return "";
+  }
+
+
   isDirty(): boolean {
     return this.documentForm.dirty
   }
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.html b/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.html
deleted file mode 100644
index 7f4a335ff614bee6f9952c3e2f7c2e398745c2f4..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.html
+++ /dev/null
@@ -1,35 +0,0 @@
-<div id="document-metadata-panel"
-     [formGroup]="documentMetadataForm">
-
-  <mat-form-field style="min-width: 180px"
-                  subscriptSizing="dynamic"
-                  appearance="fill">
-    <mat-label>{{ "document.metadata.panel.label.name" | translate }}</mat-label>
-    <input matInput id="name_id"
-           formControlName="name"
-           readonly>
-  </mat-form-field>
-  <mat-form-field style="min-width: 180px"
-                  subscriptSizing="dynamic"
-                  appearance="fill">
-    <mat-label>{{ "document.metadata.panel.label.mimetype" | translate }}</mat-label>
-    <input matInput id="mimeType_id"
-           formControlName="mimeType"
-           readonly>
-  </mat-form-field>
-
-  <mat-form-field style="min-width: 180px"
-                  subscriptSizing="dynamic"
-                  appearance="fill">
-    <mat-label>{{ "document.metadata.panel.label.published.version" | translate }}</mat-label>
-    <input matInput id="publishedVersion_id"
-           formControlName="publishedVersion"
-           readonly>
-  </mat-form-field>
-  <mat-checkbox formControlName="sharingEnabled"
-                matTooltip="{{ 'document.metadata.panel.label.sharing.enabled' | translate }}"
-                id="sharingEnabled_id">
-    {{ "document.metadata.panel.label.sharing.enabled" | translate }}
-  </mat-checkbox>
-</div>
-
diff --git a/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.ts b/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.ts
deleted file mode 100644
index 8d1437d96717284cf1019d6b568e8f87f01adb93..0000000000000000000000000000000000000000
--- a/smp-angular/src/app/common/panels/document-edit-panel/document-metadata-panel/document-metadata-panel.component.ts
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-
- * #START_LICENSE#
- * smp-webapp
- * %%
- * Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
- * %%
- * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
- * versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- *
- * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
- * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and limitations under the Licence.
- * #END_LICENSE#
- */
-import {
-  AfterViewInit,
-  Component,
-  forwardRef,
-  Input,
-  ViewChild,
-} from '@angular/core';
-import {
-  ControlContainer,
-  ControlValueAccessor,
-  FormBuilder,
-  FormControl,
-  FormControlDirective,
-  FormGroup,
-  NG_VALUE_ACCESSOR
-} from "@angular/forms";
-import {MatDialog} from "@angular/material/dialog";
-import {
-  BeforeLeaveGuard
-} from "../../../../window/sidenav/navigation-on-leave-guard";
-import {GlobalLookups} from "../../../global-lookups";
-import {TranslateService} from "@ngx-translate/core";
-import {
-  HttpErrorHandlerService
-} from "../../../error/http-error-handler.service";
-import {DocumentMetadataRo} from "../../../model/document-metadata-ro.model";
-
-/**
- * Component to display the properties of a document in a table. The properties can be edited and saved.
- * @author Joze Rihtarsic
- * @since 5.1
- */
-@Component({
-  selector: 'document-metadata-panel',
-  templateUrl: './document-metadata-panel.component.html',
-  styleUrls: ['./document-metadata-panel.component.scss'],
-  providers: [
-    {
-      provide: NG_VALUE_ACCESSOR,
-      useExisting: forwardRef(() => DocumentMetadataPanelComponent),
-      multi: true
-    }
-  ]
-})
-export class DocumentMetadataPanelComponent implements AfterViewInit, BeforeLeaveGuard, ControlValueAccessor {
-
-  dataChanged = false;
-  private onChangeCallback: (_: any) => void = () => {
-  };
-
-  _documentMetadata: DocumentMetadataRo;
-  documentMetadataForm: FormGroup;
-
-  constructor(
-    private globalLookups: GlobalLookups,
-    public dialog: MatDialog,
-    private controlContainer: ControlContainer,
-    private formBuilder: FormBuilder,
-    private translateService: TranslateService,
-    private httpErrorHandlerService: HttpErrorHandlerService) {
-
-    this.documentMetadataForm = formBuilder.group({
-      'name': new FormControl({value: null}),
-      'mimeType': new FormControl({value: null}),
-      'publishedVersion': new FormControl({value: null}),
-      'sharingEnabled': new FormControl({value: null}),
-      'allVersions': new FormControl({value: null}),
-      'referenceDocumentId': new FormControl({value: null}),
-    });
-  }
-
-
-  @ViewChild(FormControlDirective, {static: true})
-  formControlDirective: FormControlDirective;
-  @Input()
-  formControl: FormControl;
-
-  @Input()
-  formControlName: string;  /* get hold of FormControl instance no matter formControl or    formControlName is given. If formControlName is given, then this.controlContainer.control is the parent FormGroup (or FormArray) instance. */
-  get control() {
-    return this.formControl || this.controlContainer.control.get(this.formControlName);
-  }
-
-  /**
-   * Implementation of the ControlValueAccessor method to  write value to the component.
-   * @param eventList
-   */
-  writeValue(data: DocumentMetadataRo): void {
-    this.documentMetadata = data;
-  }
-
-  ngAfterViewInit() {
-
-  }
-
-
-  isDirty(): boolean {
-    return this.documentMetadataForm.dirty;
-  }
-
-  registerOnChange(fn: any): void {
-    this.onChangeCallback = fn;
-
-  }
-
-  registerOnTouched(fn: any): void {
-    // not implemented
-  }
-
-  setDisabledState(isDisabled: boolean): void {
-    // not implemented
-  }
-
-
-  @Input() set documentMetadata(value: DocumentMetadataRo) {
-    this._documentMetadata = value;
-    this.documentMetadataForm.disable();
-
-    if (!!value) {
-      this.documentMetadataForm.controls['name'].setValue(value.name);
-      this.documentMetadataForm.controls['mimeType'].setValue(value.mimeType);
-      this.documentMetadataForm.controls['publishedVersion'].setValue(value.publishedVersion);
-      this.documentMetadataForm.controls['allVersions'].setValue(value.allVersions);
-      this.documentMetadataForm.controls['referenceDocumentId'].setValue(value.referenceDocumentId);
-      this.documentMetadataForm.controls['sharingEnabled'].setValue(value.sharingEnabled);
-    } else {
-      this.documentMetadataForm.controls['name'].setValue("");
-      this.documentMetadataForm.controls['mimeType'].setValue("");
-      this.documentMetadataForm.controls['publishedVersion'].setValue("");
-      this.documentMetadataForm.controls['allVersions'].setValue([]);
-      this.documentMetadataForm.controls['referenceDocumentId'].setValue("");
-      this.documentMetadataForm.controls['sharingEnabled'].setValue(false);
-      this.documentMetadataForm.controls['properties'].setValue([]);
-    }
-    this.documentMetadataForm.markAsPristine();
-  }
-
-  get documentMetadata(): DocumentMetadataRo {
-    let docMetadata: DocumentMetadataRo = {...this._documentMetadata};
-
-    // set new properties
-    docMetadata.sharingEnabled = this.documentMetadataForm.controls['sharingEnabled'].value;
-    docMetadata.name = this.documentMetadataForm.controls['name'].value;
-    docMetadata.referenceDocumentId = this.documentMetadataForm.controls['referenceDocumentId'].value;
-    return docMetadata;
-  }
-}
diff --git a/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.html b/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.html
index 595803b18bee6c38ec1ab5f23f31667a9cfcbfc9..0b3de0563bfe94b1b4b92e71fc0c323b4dda7f62 100644
--- a/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.html
+++ b/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.html
@@ -23,6 +23,12 @@
         </th>
         <td mat-cell *matCellDef="let row">{{ row.eventType }}</td>
       </ng-container>
+      <ng-container matColumnDef="status">
+        <th mat-header-cell *matHeaderCellDef
+            mat-sort-header>{{ "document.events.panel.label.status" | translate }}
+        </th>
+        <td mat-cell *matCellDef="let row">{{ row.documentVersionStatus }}</td>
+      </ng-container>
 
       <ng-container matColumnDef="username">
         <th mat-header-cell *matHeaderCellDef
@@ -50,7 +56,7 @@
       </tr>
     </table>
   </div>
-  <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons
+  <mat-paginator [pageSizeOptions]="[5, 10, 15, 20]" showFirstLastButtons
                  [pageSize]="10" [length]="eventDataSource.data?.length"
                  attr.aria-label="{{ 'document.events.panel.label.select.page' | translate }}"></mat-paginator>
 
diff --git a/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.ts b/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.ts
index c22cc2a6298b302fc024799744238fe8e47348ee..afcd2c325b2ef1f30ed0ecc3fbefbae7b67cc8f3 100644
--- a/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.ts
+++ b/smp-angular/src/app/common/panels/document-events-panel/document-events-panel.component.ts
@@ -34,7 +34,9 @@ import {
 import {MatSort} from "@angular/material/sort";
 import {MatDialog} from "@angular/material/dialog";
 import {MatPaginator} from "@angular/material/paginator";
-import {DocumentVersionEventRo} from "../../model/document-version-event-ro.model";
+import {
+  DocumentVersionEventRo
+} from "../../model/document-version-event-ro.model";
 import {
   BeforeLeaveGuard
 } from "../../../window/sidenav/navigation-on-leave-guard";
@@ -60,7 +62,7 @@ import {GlobalLookups} from "../../global-lookups";
 export class DocumentEventsPanelComponent implements AfterViewInit, BeforeLeaveGuard, ControlValueAccessor {
 
 
-  displayedColumns: string[] = [ 'date', 'eventType', 'username', 'eventSource'];
+  displayedColumns: string[] = ['date', 'eventType', 'status','username', 'eventSource'];
   private onChangeCallback: (_: any) => void = () => {
   };
   eventDataSource: MatTableDataSource<DocumentVersionEventRo> = new MatTableDataSource();
@@ -72,8 +74,8 @@ export class DocumentEventsPanelComponent implements AfterViewInit, BeforeLeaveG
 
   constructor(
     private globalLookups: GlobalLookups,
-           public dialog: MatDialog,
-              private controlContainer: ControlContainer) {
+    public dialog: MatDialog,
+    private controlContainer: ControlContainer) {
   }
 
   get dateTimeFormat(): string {
@@ -103,6 +105,14 @@ export class DocumentEventsPanelComponent implements AfterViewInit, BeforeLeaveG
   ngAfterViewInit() {
     this.eventDataSource.paginator = this.paginator;
     this.eventDataSource.sort = this.sort;
+    // add custom filter to exclude filtering on  event description
+    this.eventDataSource.filterPredicate = (data: DocumentVersionEventRo, filter: string) => {
+      return data.eventType?.toLowerCase().includes(filter)
+        || data.username?.toLowerCase().includes(filter)
+        || data.documentVersionStatus?.toLowerCase().includes(filter)
+        || data.eventSourceType?.toLowerCase().includes(filter)
+        || data.eventOn?.toLocaleString().toLowerCase().includes(filter);
+    };
   }
 
   applyFilter(event: Event) {
diff --git a/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.html b/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.html
index f1dc9a7eab8c8f754220293913435c77df8fbe89..c99f7010c32968eabcdbcf6a32b7e3a87bb2bc44 100644
--- a/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.html
+++ b/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.html
@@ -64,7 +64,7 @@
           </tr>
         </table>
       </div>
-      <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons
+      <mat-paginator [pageSizeOptions]="[5, 10, 15, 20]" showFirstLastButtons
                      [pageSize]="10" [length]="propertyDataSource.data?.length"
                      attr.aria-label="{{ 'document.properties.panel.label.select.page' | translate }}"></mat-paginator>
 
diff --git a/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.ts b/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.ts
index 5c346cf7ce0b54b4fd422a03f3802c50d54c92b2..3018ff24e512dd100ad12999a3b1bad39081273b 100644
--- a/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.ts
+++ b/smp-angular/src/app/common/panels/document-properties-panel/document-properties-panel.component.ts
@@ -231,12 +231,6 @@ export class DocumentPropertiesPanelComponent implements AfterViewInit, BeforeLe
     this.onChangeCallback(this.propertyDataSource.data);
   }
 
-
-  public onSaveButtonClicked() {
-    // submit list of properties to the backend
-
-  }
-
   /*
     * reset/reload properties from the server
    */
diff --git a/smp-angular/src/app/common/panels/document-versions-panel/document-versions-panel.component.html b/smp-angular/src/app/common/panels/document-versions-panel/document-versions-panel.component.html
index 888070643239c2374d704d1dae8e81343e0a52b0..47c26cb674f6bbbb0516def7ab5e332364f809de 100644
--- a/smp-angular/src/app/common/panels/document-versions-panel/document-versions-panel.component.html
+++ b/smp-angular/src/app/common/panels/document-versions-panel/document-versions-panel.component.html
@@ -51,7 +51,7 @@
       </tr>
     </table>
   </div>
-  <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons
+  <mat-paginator [pageSizeOptions]="[5, 10, 15, 20]" showFirstLastButtons
                  [pageSize]="10" [length]="versionDataSource.data?.length"
                  attr.aria-label="{{ 'document.versions.panel.label.select.page' | translate }}"></mat-paginator>
 
diff --git a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-item-component/expandable-item.component.ts b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-item-component/expandable-item.component.ts
index ab38db9e37fdbec975e79c843ec94bcbc7dc665f..d046c4d20f5f7274e7b3f712f333a4a6e1ddc93f 100644
--- a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-item-component/expandable-item.component.ts
+++ b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-item-component/expandable-item.component.ts
@@ -16,7 +16,13 @@
  * See the Licence for the specific language governing permissions and limitations under the Licence.
  * #END_LICENSE#
  */
-import {Component, Input, ViewChild,} from '@angular/core';
+import {
+  Component,
+  EventEmitter,
+  Input,
+  Output,
+  ViewChild,
+} from '@angular/core';
 
 
 /**
@@ -31,6 +37,8 @@ import {Component, Input, ViewChild,} from '@angular/core';
 })
 export class ExpandableItemComponent {
 
+  //
+  @Input() showButtonSpacer: boolean = false;
   @Input() title: string;
   @Input() buttonLabel: string;
   @Input() icon: string;
@@ -45,6 +53,4 @@ export class ExpandableItemComponent {
   showItem(show: boolean) {
     this.expandableItem.nativeElement.style.display = show ? 'block' : 'none';
   }
-
-
 }
diff --git a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.html b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.html
index d73712f802c86499f80d393d5ae48514ba4a6340..97e7dd58cc30df1655fcf2283f745d71f29e10b3 100644
--- a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.html
+++ b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.html
@@ -3,23 +3,24 @@
     <ng-content></ng-content>
   </div>
   <!-- table Toolbar -->
-  <div style="width: 42px">
-    <button mat-mini-fab
+  <div style="width: 32px">
+    <button class="button-deselected"
             attr.aria-label="{{ 'expandable.panel.label.expand.collapse' | translate }}"
             matTooltip="{{ 'document.properties.panel.tooltip.expand.collapse' | translate }}"
             (click)="onToggleExpandButtonClicked()">
       <mat-icon *ngIf="expandPanel">chevron_left</mat-icon>
       <mat-icon *ngIf="!expandPanel">chevron_right</mat-icon>
     </button>
-    <tool-button-spacer [vertical]="false"></tool-button-spacer>
-    <button *ngFor="let item of expandableItems; let i = index;"
-            [class]="getButtonClass(i)"
+    <ng-container *ngFor="let item of expandableItems; let i = index;">
+      <tool-button-spacer *ngIf="item.showButtonSpacer" [vertical]="false"></tool-button-spacer>
+      <button [class]="getButtonClass(i)"
             (click)="selectItem(item, i)"
-            [matTooltip]="item.title"
-    >
+            (dblclick)="onDoubleClick(item, i)"
+            [matTooltip]="item.title">
       <mat-icon *ngIf="item.icon">{{ item.icon }}</mat-icon>
       <span *ngIf="showButtonLabel"
-            class="vertical-button-label">{{item.buttonLabel}}</span>
+            class="vertical-button-label">{{ item.buttonLabel }}</span>
     </button>
+    </ng-container>
   </div>
 </div>
diff --git a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.scss b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.scss
index dcc099038e537562550909e7c49f647368335edf..0c2c84087ed89e523ff91169ddcc68f085e43705 100644
--- a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.scss
+++ b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.scss
@@ -1,3 +1,31 @@
+@use '../../../../_smp-theme-helper' as smp;
+
+@mixin set-component-colors($theme) {
+
+  .button-selected {
+    padding: 3px 3px !important;
+    border-radius: 15%;
+    background-color: smp.get-theme-color($theme, primary, 500) !important;
+    box-shadow: 0 1px 2px 0 rgba(0,0,0,0.2), 0 1px 2px 0 rgba(0,0,0,0.2);
+    color: smp.get-theme-color($theme, primary, 500-contrast) !important;
+    border-style: none;
+  }
+
+  .button-deselected :hover {
+    background-color: smp.get-theme-color($theme, primary, 800, 0.5) !important;
+    color: smp.get-theme-color($theme, primary, 500-contrast) !important;
+  }
+
+  .button-deselected {
+    padding: 1px 3px !important;
+    border-radius: 15%;
+    background: transparent;
+    color: smp.get-theme-color($theme, primary, 500-contrast) !important;
+    border-style: none;
+  }
+
+}
+
 #expand-panel_id {
   display: flex;
   flex-direction: column;
@@ -12,9 +40,5 @@
   writing-mode: vertical-rl;
 }
 
-.button-deselected {
-  margin: 1px 3px !important;
-  background: transparent;
-  border-style: none;
-}
+
 
diff --git a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.ts b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.ts
index d91ada553e0fd249111c8bb55eb987fb4b1bdbd4..a8652284650a9acdda3f41705909eff5e4d5a9f1 100644
--- a/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.ts
+++ b/smp-angular/src/app/common/panels/expandable-panel-component/expandable-panel.component.ts
@@ -19,8 +19,8 @@
 import {
   AfterViewInit,
   Component,
-  ContentChildren,
-  Input,
+  ContentChildren, EventEmitter,
+  Input, Output,
   QueryList,
 } from '@angular/core';
 import {
@@ -38,8 +38,9 @@ import {
   styleUrls: ['./expandable-panel.component.scss'],
 })
 export class ExpandablePanelComponent implements AfterViewInit {
-
   @ContentChildren(ExpandableItemComponent) private _expandableItems: QueryList<ExpandableItemComponent>;
+
+  @Output() onButtonDoubleClickEvent: EventEmitter<number> = new EventEmitter();
   @Input() showButtonLabel: boolean = false;
   expandPanel: boolean = true;
   selectedIndex: number = 0;
@@ -76,7 +77,11 @@ export class ExpandablePanelComponent implements AfterViewInit {
   }
 
   getButtonClass(index: number) {
-    return index === this.selectedIndex ? 'mat-raised-button' : 'mat-raised-button button-deselected';
+    return index === this.selectedIndex ? 'button-selected' : 'button-deselected';
   }
 
+  onDoubleClick(item: ExpandableItemComponent, index: number) {
+    this.onButtonDoubleClickEvent.emit(index);
+    this.onToggleExpandButtonClicked();
+  }
 }
diff --git a/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts b/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts
index c3ea322dfeec2a4a5f1a4bb6f4c440c26d8a675c..e6fec36a8dba9b3c2003464bdd94f581c80c7d6d 100644
--- a/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts
+++ b/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts
@@ -9,7 +9,6 @@ import {MemberRo} from "../../model/member-ro.model";
 import {finalize} from "rxjs/operators";
 import {TableResult} from "../../model/table-result.model";
 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";
 import {GroupRo} from "../../model/group-ro.model";
@@ -18,6 +17,7 @@ import {SearchTableResult} from "../../search-table/search-table-result.model";
 import {ConfirmationDialogComponent} from "../../dialogs/confirmation-dialog/confirmation-dialog.component";
 import {ResourceRo} from "../../model/resource-ro.model";
 import {TranslateService} from "@ngx-translate/core";
+import {MembershipService} from "../../services/membership.service";
 
 
 @Component({
diff --git a/smp-angular/src/app/common/panels/membership-panel/membership.service.ts b/smp-angular/src/app/common/services/membership.service.ts
similarity index 90%
rename from smp-angular/src/app/common/panels/membership-panel/membership.service.ts
rename to smp-angular/src/app/common/services/membership.service.ts
index b8a021288cb16bcaee07f2d4a73dec4cfb6b7834..778c6e4d18d3ead17196f1fd4a5a6e6183788841 100644
--- a/smp-angular/src/app/common/panels/membership-panel/membership.service.ts
+++ b/smp-angular/src/app/common/services/membership.service.ts
@@ -1,17 +1,18 @@
 import {Injectable} from '@angular/core';
 import {Observable} from 'rxjs';
-import {SearchTableResult} from "../../search-table/search-table-result.model";
-import {User} from "../../../security/user.model";
 import {HttpClient, HttpParams} from "@angular/common/http";
-import {SmpConstants} from "../../../smp.constants";
-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 "../../model/search-user-ro.model";
-import {ResourceRo} from "../../model/resource-ro.model";
-import {GroupRo} from "../../model/group-ro.model";
-import {DomainRo} from "../../model/domain-ro.model";
+import {SecurityService} from "../../security/security.service";
+import {AlertMessageService} from "../alert-message/alert-message.service";
+import {SearchTableResult} from "../search-table/search-table-result.model";
+import {User} from "../../security/user.model";
+import {SmpConstants} from "../../smp.constants";
+import {MemberRo} from "../model/member-ro.model";
+import {TableResult} from "../model/table-result.model";
+import {ResourceRo} from "../model/resource-ro.model";
+import {GroupRo} from "../model/group-ro.model";
+import {DomainRo} from "../model/domain-ro.model";
+import {SearchUserRo} from "../model/search-user-ro.model";
+
 
 
 @Injectable()
@@ -140,7 +141,6 @@ export class MembershipService {
 
   deleteMemberFromResource(resource:ResourceRo, group:GroupRo, domain: DomainRo, member: MemberRo): Observable<MemberRo> {
     const currentUser: User = this.securityService.getCurrentUser();
-
     return this.http.delete<MemberRo>(SmpConstants.REST_EDIT_RESOURCE_MEMBER_DELETE
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
       .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId)
diff --git a/smp-angular/src/app/common/services/reference-document.service.ts b/smp-angular/src/app/common/services/reference-document.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bd942cad231e4230960c230d88963facdad837f9
--- /dev/null
+++ b/smp-angular/src/app/common/services/reference-document.service.ts
@@ -0,0 +1,37 @@
+import {Injectable} from "@angular/core";
+import {HttpClient} from "@angular/common/http";
+import {Observable} from "rxjs";
+import {SmpConstants} from "../../smp.constants";
+import {
+  SearchReferenceDocument
+} from "../model/search-reference-document-ro.model";
+import {TableResult} from "../model/table-result.model";
+import {User} from "../../security/user.model";
+import {SecurityService} from "../../security/security.service";
+import {ResourceRo} from "../model/resource-ro.model";
+import {SubresourceRo} from "../model/subresource-ro.model";
+
+@Injectable()
+export class ReferenceDocumentService {
+
+  constructor(private http: HttpClient,
+              private securityService: SecurityService) {
+  }
+
+  getSearchResourceDocumentReferencesObservable$(filter: SearchReferenceDocument, resource: ResourceRo): Observable<TableResult<SearchReferenceDocument>> {
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.post<TableResult<SearchReferenceDocument>>(SmpConstants.REST_EDIT_DOCUMENT_RESOURCE_SEARCH_REFERENCES
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+        .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource?.resourceId),
+      filter);
+  }
+
+  getSearchSubresourceDocumentReferencesObservable$(filter: SearchReferenceDocument, resource: ResourceRo, subresource: SubresourceRo): Observable<TableResult<SearchReferenceDocument>> {
+    const currentUser: User = this.securityService.getCurrentUser();
+    return this.http.post<TableResult<SearchReferenceDocument>>(SmpConstants.REST_EDIT_DOCUMENT_SUBRESOURCE_SEARCH_REFERENCES
+        .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId)
+        .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource?.resourceId)
+        .replace(SmpConstants.PATH_PARAM_ENC_SUBRESOURCE_ID, subresource?.subresourceId),
+      filter);
+  }
+}
diff --git a/smp-angular/src/app/common/services/user.service.ts b/smp-angular/src/app/common/services/user.service.ts
index e5b633f5c2f5ca0637b16f747f2540d3c2f21c75..3fc6acdb46e2385735b9c74afe5e6d5d82b88e3f 100644
--- a/smp-angular/src/app/common/services/user.service.ts
+++ b/smp-angular/src/app/common/services/user.service.ts
@@ -4,10 +4,11 @@ import {SmpConstants} from "../../smp.constants";
 import {User} from "../../security/user.model";
 import {AlertMessageService} from "../alert-message/alert-message.service";
 import {SecurityService} from "../../security/security.service";
-import {Observable, Subject} from "rxjs";
+import {lastValueFrom, Observable, Subject} from "rxjs";
 import {CredentialRo} from "../../security/credential.model";
 import {AccessTokenRo} from "../model/access-token-ro.model";
 import {HttpErrorHandlerService} from "../error/http-error-handler.service";
+import {TranslateService} from "@ngx-translate/core";
 
 /**
  * Class handle current user settings such-as profile, credentials, DomiSMP settings... ,
@@ -31,6 +32,7 @@ export class UserService {
     private httpErrorHandlerService: HttpErrorHandlerService,
     private securityService: SecurityService,
     private alertService: AlertMessageService,
+    protected translateService: TranslateService
   ) {
   }
 
@@ -52,13 +54,15 @@ export class UserService {
     }
     this.http.get<CredentialRo>(SmpConstants.REST_PUBLIC_USER_CREDENTIAL_STATUS
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId))
-      .subscribe((response: CredentialRo) => {
-        this.notifyPwdStatusUpdated(response)
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: (response: CredentialRo) => {
+          this.notifyPwdStatusUpdated(response)
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
       });
   }
 
@@ -69,13 +73,15 @@ export class UserService {
     }
     this.http.get<CredentialRo[]>(SmpConstants.REST_PUBLIC_USER_ACCESS_TOKEN_CREDENTIALS
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId))
-      .subscribe((response: CredentialRo[]) => {
-        this.notifyAccessTokensUpdated(response)
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: (response: CredentialRo[]) => {
+          this.notifyAccessTokensUpdated(response)
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
       });
   }
 
@@ -87,14 +93,16 @@ export class UserService {
     this.http.delete<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_ACCESS_TOKEN_CREDENTIAL
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)
       .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId))
-      .subscribe((response: CredentialRo) => {
-        this.notifyAccessTokenUpdated(response)
-        this.alertService.success("Access token ["+response.name+"] has been deleted!")
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: async (response: CredentialRo) => {
+          this.notifyAccessTokenUpdated(response)
+          this.alertService.success(await lastValueFrom(this.translateService.get("user.access.tokens.success.deleted", {credentialName: response.name})))
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
       });
   }
 
@@ -106,14 +114,16 @@ export class UserService {
     this.http.post<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_ACCESS_TOKEN_CREDENTIAL
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)
       .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId), credential)
-      .subscribe((response: CredentialRo) => {
-        this.notifyAccessTokenUpdated(response)
-        this.alertService.success("Access token ["+response.name+"] has been updated!")
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: async (response: CredentialRo) => {
+          this.notifyAccessTokenUpdated(response)
+          this.alertService.success(await lastValueFrom(this.translateService.get("user.access.tokens.success.updated", {credentialName: response.name})))
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
       });
   }
 
@@ -125,14 +135,16 @@ export class UserService {
     this.http.post<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_CERTIFICATE_CREDENTIAL
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)
       .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId), credential)
-      .subscribe((response: CredentialRo) => {
-        this.notifyCertificateUpdated(response)
-        this.alertService.success("Certificate ["+response.name+"] has been updated!")
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: async (response: CredentialRo) => {
+          this.notifyCertificateUpdated(response)
+          this.alertService.success(await lastValueFrom(this.translateService.get("user.certificate.success.updated", {credentialName: response.name})))
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
       });
   }
 
@@ -144,14 +156,16 @@ export class UserService {
     this.http.delete<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_CERTIFICATE_CREDENTIAL
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)
       .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId))
-      .subscribe((response: CredentialRo) => {
-        this.notifyCertificateUpdated(response)
-        this.alertService.success("Certificate ["+response.name+"] has been deleted!")
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: async (response: CredentialRo) => {
+          this.notifyCertificateUpdated(response)
+          this.alertService.success(await lastValueFrom(this.translateService.get("user.certificate.success.deleted", {credentialName: response.name})))
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
       });
   }
 
@@ -174,15 +188,16 @@ export class UserService {
     this.http.put<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_CERTIFICATE_CREDENTIAL
       .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)
       .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId), credential)
-      .subscribe((response: CredentialRo) => {
-        this.notifyCertificateUpdated(response)
-        this.alertService.success("Certificate ["+response.name+"] has been successfully uploaded!")
-      }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
-          return;
+      .subscribe({
+        next: async (response: CredentialRo) => {
+          this.notifyCertificateUpdated(response)
+          this.alertService.success(await lastValueFrom(this.translateService.get("user.certificate.success.uploaded", {credentialName: response.name})))
+        }, error: (error: any) => {
+          if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+            return;
+          }
+          this.alertService.error(error.error?.errorDescription)
         }
-        this.alertService.error(error.error?.errorDescription)
-
       });
   }
 
@@ -199,7 +214,7 @@ export class UserService {
       .subscribe((response: CredentialRo[]) => {
         this.notifyCertificatesUpdated(response)
       }, error => {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){
+        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
           return;
         }
         this.alertService.error(error.error?.errorDescription)
diff --git a/smp-angular/src/app/common/utils/string-utils.ts b/smp-angular/src/app/common/utils/string-utils.ts
index 59b99a34d3c9566b59418d605571dc5b93b65215..488110918fabb9157a871943df074f5f5ce14004 100644
--- a/smp-angular/src/app/common/utils/string-utils.ts
+++ b/smp-angular/src/app/common/utils/string-utils.ts
@@ -32,4 +32,11 @@ export default class StringUtils {
   static isEmpty(str): boolean {
     return (!str || 0 === str.length);
   }
+
+  /**
+   * Method to check if a string is null or empty and return an empty string if it is null
+   * */
+  static toEmpty(str): string {
+    return !str ?"": str;
+  }
 }
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
index d231650c1ffa3495f680654bdcc587e6caeeee66..ae7dfe7e81bf293dd0de58083656bf912d162183 100644
--- 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
@@ -7,6 +7,8 @@
       <input id="name_id" type="text" matInput formControlName="name"
              required>
       <mat-hint >{{ "group.dialog.hint.group.name" | translate }}</mat-hint>
+      <smp-field-error  *ngIf="inputDataError('name', 'maxlength')">{{ "group.dialog.error.group.name.length" | translate }}
+      </smp-field-error >
     </mat-form-field>
 
     <mat-form-field  style="width: 100%">
@@ -14,6 +16,8 @@
       <input id="description_id" type="text" matInput
              formControlName="description"
              >
+      <smp-field-error  *ngIf="inputDataError('description', 'maxlength')">{{ "group.dialog.error.group.description.length" | translate }}
+      </smp-field-error >
     </mat-form-field>
 
 
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
index 3a887d49be5811aae83684de9f4b448ba368bcfe..6f24f1b9b81c12356f7607c3f3227dce511b99c8 100644
--- 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
@@ -1,6 +1,6 @@
 import {Component, Inject, Input} from '@angular/core';
 import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
-import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
+import {FormBuilder, FormControl, FormGroup, Validators} 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";
@@ -38,8 +38,8 @@ export class GroupDialogComponent {
     this._currentDomain = data.domain;
 
     this.groupForm = formBuilder.group({
-      'name': new FormControl({value: null}),
-      'description': new FormControl({value: null}),
+      'name': new FormControl({value: null},  Validators.maxLength(512)),
+      'description': new FormControl({value: null}, Validators.maxLength(1024)),
       'visibility': new FormControl({value: null}),
       '': new FormControl({value: null})
     });
@@ -117,7 +117,10 @@ export class GroupDialogComponent {
     }, (error) => {
       this.alertService.error(error.error?.errorDescription)
     });
+  }
 
+  public inputDataError = (controlName: string, errorName: string) => {
+    return this.groupForm.controls[controlName].hasError(errorName);
   }
 
   public saveGroup(group: GroupRo) {
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 a6f65dc6942e8d0b8fe1f467cd600546993c01b2..4e826849b4f868a5c9f31d23607f79c654cd1c52 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
@@ -1,16 +1,20 @@
 import {AfterViewInit, Component, OnInit, ViewChild} from '@angular/core';
 import {MatTableDataSource} from "@angular/material/table";
 import {EditDomainService} from "./edit-domain.service";
-import {AlertMessageService} from "../../common/alert-message/alert-message.service";
 import {MatDialog} from "@angular/material/dialog";
 import {BeforeLeaveGuard} from "../../window/sidenav/navigation-on-leave-guard";
 import {DomainRo} from "../../common/model/domain-ro.model";
-import {CancelDialogComponent} from "../../common/dialogs/cancel-dialog/cancel-dialog.component";
+import {
+  CancelDialogComponent
+} from "../../common/dialogs/cancel-dialog/cancel-dialog.component";
 import {MatPaginator} from "@angular/material/paginator";
 import {MatSort} from "@angular/material/sort";
 import {MatTabGroup} from "@angular/material/tabs";
 import {MemberTypeEnum} from "../../common/enums/member-type.enum";
 import {firstValueFrom} from "rxjs";
+import {
+  HttpErrorHandlerService
+} from "../../common/error/http-error-handler.service";
 
 @Component({
   templateUrl: './edit-domain.component.html',
@@ -18,7 +22,7 @@ import {firstValueFrom} from "rxjs";
 })
 export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGuard {
 
-  membershipType:MemberTypeEnum = MemberTypeEnum.DOMAIN;
+  membershipType: MemberTypeEnum = MemberTypeEnum.DOMAIN;
   displayedColumns: string[] = ['domainCode'];
   dataSource: MatTableDataSource<DomainRo> = new MatTableDataSource();
   selected: DomainRo;
@@ -33,12 +37,11 @@ export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGu
   @ViewChild('domainTabs') domainTabs: MatTabGroup;
 
   constructor(private domainService: EditDomainService,
-              private alertService: AlertMessageService,
+              private httpErrorHandlerService: HttpErrorHandlerService,
               private dialog: MatDialog) {
     this.refreshDomains();
   }
 
-
   ngOnInit(): void {
     // filter predicate for search the domain
     this.dataSource.filterPredicate =
@@ -47,7 +50,7 @@ export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGu
       };
   }
 
-  ngAfterViewInit():void {
+  ngAfterViewInit(): void {
     this.dataSource.paginator = this.paginator;
     this.dataSource.sort = this.sort;
     // MatTab has only onTabChanged which is a bit to late. Register new listener to  internal
@@ -59,12 +62,14 @@ export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGu
   refreshDomains() {
     this.loading = true;
     this.domainService.getDomainsForDomainAdminUserObservable()
-      .subscribe((result: DomainRo[]) => {
-        this.updateDomainList(result)
-        this.loading = false;
-      }, (error: any) => {
-        this.loading = false;
-        this.alertService.error(error.error?.errorDescription)
+      .subscribe({
+        next: (result: DomainRo[]) => {
+          this.updateDomainList(result)
+          this.loading = false;
+        }, error: (error: any) => {
+          this.loading = false;
+          this.httpErrorHandlerService.handleHttpError(error);
+        }
       });
   }
 
@@ -118,7 +123,6 @@ export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGu
   }
 
 
-
   public domainSelected(domainSelected: DomainRo) {
     if (this.selected === domainSelected) {
       return;
@@ -139,8 +143,9 @@ export class EditDomainComponent implements OnInit, AfterViewInit, BeforeLeaveGu
   isCurrentTabDirty(): boolean {
     return false;
   }
+
   isDirty(): boolean {
-    return  this.isCurrentTabDirty();
+    return this.isCurrentTabDirty();
   }
 
   get canNotDelete(): boolean {
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
index 7f54299e6fc68d7595f76698da775be493d1dd1f..7a6a9c5a5ce6b4dba40e36f5eac50ed26273cd3e 100644
--- a/smp-angular/src/app/edit/edit-group/edit-group.component.ts
+++ b/smp-angular/src/app/edit/edit-group/edit-group.component.ts
@@ -1,13 +1,25 @@
-import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
+import {
+  Component,
+  EventEmitter,
+  Input,
+  OnInit,
+  Output,
+  ViewChild
+} from '@angular/core';
 import {BeforeLeaveGuard} from "../../window/sidenav/navigation-on-leave-guard";
 import {MatPaginator} from "@angular/material/paginator";
-import {AlertMessageService} from "../../common/alert-message/alert-message.service";
 import {EditDomainService} from "../edit-domain/edit-domain.service";
 import {DomainRo} from "../../common/model/domain-ro.model";
 import {EditGroupService} from "./edit-group.service";
 import {GroupRo} from "../../common/model/group-ro.model";
 import {MemberTypeEnum} from "../../common/enums/member-type.enum";
-import {ResourceDefinitionRo} from "../../system-settings/admin-extension/resource-definition-ro.model";
+import {
+  ResourceDefinitionRo
+} from "../../system-settings/admin-extension/resource-definition-ro.model";
+import {
+  HttpErrorHandlerService
+} from "../../common/error/http-error-handler.service";
+
 @Component({
   templateUrl: './edit-group.component.html',
   styleUrls: ['./edit-group.component.css']
@@ -36,7 +48,6 @@ export class EditGroupComponent implements OnInit, BeforeLeaveGuard {
       this.groupList = [];
       this._selectedDomainResourceDef = [];
     }
-
   };
 
   get selectedGroup(): GroupRo {
@@ -54,7 +65,7 @@ export class EditGroupComponent implements OnInit, BeforeLeaveGuard {
 
   constructor(private domainService: EditDomainService,
               private groupService: EditGroupService,
-              private alertService: AlertMessageService) {
+              private httpErrorHandlerService: HttpErrorHandlerService) {
 
   }
 
@@ -65,11 +76,13 @@ export class EditGroupComponent implements OnInit, BeforeLeaveGuard {
   refreshDomains() {
     this.loading = true;
     this.domainService.getDomainsForGroupAdminUserObservable()
-      .subscribe((result: DomainRo[]) => {
-        this.updateDomainList(result)
-      }, (error: any) => {
-        this.loading = false;
-        this.alertService.error(error.error?.errorDescription)
+      .subscribe({
+        next: (result: DomainRo[]) => {
+          this.updateDomainList(result)
+        }, error: (error: any) => {
+          this.loading = false;
+          this.httpErrorHandlerService.handleHttpError(error);
+        }
       });
   }
 
@@ -81,20 +94,24 @@ export class EditGroupComponent implements OnInit, BeforeLeaveGuard {
     }
     this.loading = true;
     this.groupService.getDomainGroupsForGroupAdminObservable(this.selectedDomain)
-      .subscribe((result: GroupRo[]) => {
-        this.updateGroupList(result)
-      }, (error: any) => {
-        this.alertService.error(error.error?.errorDescription)
-        this.loading = false;
+      .subscribe({
+        next: (result: GroupRo[]) => {
+          this.updateGroupList(result)
+        }, error: (error: any) => {
+          this.httpErrorHandlerService.handleHttpError(error);
+          this.loading = false;
+        }
       });
   }
 
   refreshDomainsResourceDefinitions() {
     this.domainService.getDomainResourceDefinitionsObservable(this.selectedDomain)
-      .subscribe((result: ResourceDefinitionRo[]) => {
-        this._selectedDomainResourceDef = result
-      }, (error: any) => {
-        this.alertService.error(error.error?.errorDescription)
+      .subscribe({
+        next: (result: ResourceDefinitionRo[]) => {
+          this._selectedDomainResourceDef = result
+        }, error: (error: any) => {
+          this.httpErrorHandlerService.handleHttpError(error);
+        }
       });
   }
 
@@ -111,7 +128,7 @@ export class EditGroupComponent implements OnInit, BeforeLeaveGuard {
     this.groupList = list
     if (!!this.groupList && this.groupList.length > 0) {
       this.selectedGroup = this.groupList[0];
-    }else {
+    } else {
       this.loading = false;
     }
   }
diff --git a/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts b/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts
index 0d1e10640502ba438e2be1c9aa2a7a6749f466ae..3be5967830805df5b8902c8a5c72327d37bafe8f 100644
--- a/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts
+++ b/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts
@@ -19,6 +19,7 @@ import {
 import {MemberTypeEnum} from "../../../common/enums/member-type.enum";
 import {TranslateService} from "@ngx-translate/core";
 import {lastValueFrom} from "rxjs";
+import StringUtils from "../../../common/utils/string-utils";
 
 
 @Component({
@@ -168,7 +169,7 @@ export class GroupResourcePanelComponent implements BeforeLeaveGuard {
       data: {
         title: await lastValueFrom(this.translateService.get("group.resource.panel.delete.confirmation.dialog.title")),
         description: await lastValueFrom(this.translateService.get("group.resource.panel.delete.confirmation.dialog.description", {
-          identifierScheme: this.selected.identifierScheme,
+          identifierScheme: StringUtils.toEmpty(this.selected.identifierScheme),
           identifierValue: this.selected.identifierValue
         }))
       }
@@ -187,16 +188,16 @@ export class GroupResourcePanelComponent implements BeforeLeaveGuard {
           this.refresh();
           this.isLoadingResults = false;
         }))
-      .subscribe(async (result: ResourceRo) => {
+      .subscribe({next:async (result: ResourceRo) => {
           if (result) {
             this.alertService.success(await lastValueFrom(this.translateService.get("group.resource.panel.success.delete", {
-              identifierScheme: this.selected.identifierScheme,
+              identifierScheme: StringUtils.toEmpty(this.selected.identifierScheme),
               identifierValue: this.selected.identifierValue
             })));
           }
-        }, (error)=> {
+        }, error: (error:any)=> {
           this.alertService.error(error.error?.errorDescription);
-        }
+        }}
       );
   }
 
diff --git a/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.html b/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.html
index 2cbf4607ea9242d3deda34245839cc057b8c9367..ee2aca4c7b830624d5a14771b97c73bc94d91777 100644
--- a/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.html
+++ b/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.html
@@ -37,8 +37,7 @@
       <mat-label>{{ "resource.dialog.label.resource.scheme" | translate }}</mat-label>
       <input id="identifierScheme_id" type="text" matInput
              formControlName="identifierScheme"
-             maxlength="255"
-             >
+             maxlength="255">
       <div
         *ngIf="(newMode && resourceForm.controls['identifierScheme'].touched ) &&  resourceForm.controls['identifierScheme'].hasError('required')"
         style="color:red; font-size: 70%">
@@ -48,7 +47,7 @@
         *ngIf="(newMode && resourceForm.controls['identifierScheme'].touched ) &&
                resourceForm.controls['identifierScheme'].hasError('pattern')"
         style="color:red; font-size: 70%">
-        {{participantSchemeMessage}}
+        {{resourceSchemeMessage}}
       </div>
     </mat-form-field>
     <mat-checkbox formControlName="reviewEnabled"
diff --git a/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.ts b/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.ts
index 1c4d4153fb15e16be026dcae266d7ec863075996..b2595a6a3cefd8b5e3affed7e8275d8e6e5cd04d 100644
--- a/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.ts
+++ b/smp-angular/src/app/edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component.ts
@@ -1,4 +1,11 @@
-import {Component, ElementRef, Inject, Input, ViewChild} from '@angular/core';
+import {
+  Component,
+  ElementRef,
+  Inject,
+  Input,
+  OnInit,
+  ViewChild
+} from '@angular/core';
 import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
 import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms";
 import {
@@ -16,13 +23,24 @@ import {GlobalLookups} from "../../../../common/global-lookups";
 import {
   EditResourceService
 } from "../../../edit-resources/edit-resource.service";
+import {EditDomainService} from "../../../edit-domain/edit-domain.service";
+import {
+  HttpErrorHandlerService
+} from "../../../../common/error/http-error-handler.service";
+import {
+  DomainPropertyRo
+} from "../../../../common/model/domain-property-ro.model";
+import {Subscription} from "rxjs";
 
 
 @Component({
   templateUrl: './resource-dialog.component.html',
   styleUrls: ['./resource-dialog.component.css']
 })
-export class ResourceDialogComponent {
+export class ResourceDialogComponent implements OnInit {
+  readonly PROPERTY_RESOURCE_SCHEME_VALIDATION_REGEXP_VAL: string = 'identifiersBehaviour.ParticipantIdentifierScheme.validationRegex';
+  readonly PROPERTY_RESOURCE_SCHEME_VALIDATION_REGEXP_MSG: string = 'identifiersBehaviour.ParticipantIdentifierScheme.validationRegexMessage';
+  readonly PROPERTY_RESOURCE_SCHEME_MANDATORY: string = 'identifiersBehaviour.scheme.mandatory';
 
   readonly groupVisibilityOptions = Object.keys(VisibilityEnum)
     .map(el => {
@@ -37,11 +55,11 @@ export class ResourceDialogComponent {
   _resource: ResourceRo
   domain: DomainRo;
   domainResourceDefs: ResourceDefinitionRo[];
-
-  participantSchemePattern = '^[a-z0-9]+-[a-z0-9]+-[a-z0-9]+$';
-  participantSchemeMessage: string;
+  resourceSchemePattern = '^[a-z0-9]+-[a-z0-9]+-[a-z0-9]+$';
+  resourceSchemeMessage: string;
+  resourceSchemeMandatory: boolean = false;
   submitInProgress: boolean = false;
-
+  private domainPropertyUpdatedEventSub: Subscription = Subscription.EMPTY;
   @ViewChild('identifierValue', {static: false}) identifierValue: ElementRef;
 
   constructor(@Inject(MAT_DIALOG_DATA) public data: any,
@@ -50,37 +68,46 @@ export class ResourceDialogComponent {
               private editGroupService: EditGroupService,
               private editResourceService: EditResourceService,
               private alertService: AlertMessageService,
+              private httpErrorHandlerService: HttpErrorHandlerService,
+              private editDomainService: EditDomainService,
               private formBuilder: FormBuilder
   ) {
 
     if (this.lookups.cachedApplicationConfig) {
-      this.participantSchemePattern = this.lookups.cachedApplicationConfig.participantSchemaRegExp != null ?
+      this.resourceSchemePattern = this.lookups.cachedApplicationConfig.participantSchemaRegExp != null ?
         this.lookups.cachedApplicationConfig.participantSchemaRegExp : ".*"
-
-      this.participantSchemeMessage = this.lookups.cachedApplicationConfig.participantSchemaRegExpMessage;
+      this.resourceSchemeMessage = this.lookups.cachedApplicationConfig.participantSchemaRegExpMessage;
     }
-
     dialogRef.disableClose = true;//disable default close operation
     this.formTitle = data.formTitle;
 
 
     this.resourceForm = formBuilder.group({
       'identifierValue': new FormControl({value: null},),
-      'identifierScheme': new FormControl({value: null}, [Validators.pattern(this.participantSchemePattern)]),
+      'identifierScheme': new FormControl({value: null},),
       'visibility': new FormControl({value: null}),
       'reviewEnabled': new FormControl({value: null}),
       'resourceTypeIdentifier': new FormControl({value: null}),
       '': new FormControl({value: null})
     });
-    if (!!lookups.cachedApplicationConfig.partyIDSchemeMandatory) {
-      this.resourceForm.controls['identifierScheme'].addValidators(Validators.required);
-    }
+    this.resourceSchemeMandatory = !!lookups.cachedApplicationConfig.partyIDSchemeMandatory
+
     this.resource = data.resource;
     this.group = data.group;
     this.domain = data.domain;
     this.domainResourceDefs = data.domainResourceDefs;
+    this.updateControlSchemeValidation();
+  }
 
-
+  ngOnInit(): void {
+    // subscribe to domain property update event to update
+    // registered domain properties for regexp validation
+    this.domainPropertyUpdatedEventSub = this.editDomainService.onDomainPropertyUpdatedEvent()
+      .subscribe((updateDomainList: DomainPropertyRo[]): void => {
+          this.updateDomainPropertyList(updateDomainList);
+        }
+      );
+    this.editDomainService.getDomainProperties(this.domain);
   }
 
   get newMode(): boolean {
@@ -93,6 +120,7 @@ export class ResourceDialogComponent {
     resource.identifierScheme = this.resourceForm.get('identifierScheme').value;
     resource.resourceTypeIdentifier = this.resourceForm.get('resourceTypeIdentifier').value;
     resource.visibility = this.resourceForm.get('visibility').value;
+    resource.reviewEnabled = this.resourceForm.get('reviewEnabled').value;
     return resource;
   }
 
@@ -129,6 +157,43 @@ export class ResourceDialogComponent {
     this.resourceForm.markAsPristine();
   }
 
+  /**
+   * Update registered domain properties for regexp validation of the participant scheme
+   *
+   * @param updateDomainList
+   */
+  public updateDomainPropertyList(updateDomainList: DomainPropertyRo[]): void {
+    if (!updateDomainList) {
+      return;
+    }
+    updateDomainList.forEach((element: DomainPropertyRo) => {
+      if (element.property === this.PROPERTY_RESOURCE_SCHEME_VALIDATION_REGEXP_VAL) {
+        let value = element.systemDefault ? element.systemDefaultValue : element.value;
+        this.resourceSchemePattern = value;
+      } else if (element.property === this.PROPERTY_RESOURCE_SCHEME_VALIDATION_REGEXP_MSG) {
+        let value = element.systemDefault ? element.systemDefaultValue : element.value;
+        this.resourceSchemeMessage = value;
+      } else if (element.property === this.PROPERTY_RESOURCE_SCHEME_MANDATORY) {
+        let value = element.systemDefault ? element.systemDefaultValue : element.value;
+        this.resourceSchemeMandatory = value === 'true';
+      }
+    });
+    this.updateControlSchemeValidation();
+  }
+
+  /**
+   * Update the validation of the participant scheme control
+   */
+  private updateControlSchemeValidation(): void {
+    let schemeControl = this.resourceForm.controls['identifierScheme'];
+    schemeControl.clearValidators();
+    schemeControl.addValidators([Validators.pattern(this.resourceSchemePattern)]);
+    if (this.resourceSchemeMandatory) {
+      schemeControl.addValidators([Validators.required]);
+    }
+    schemeControl.updateValueAndValidity();
+  }
+
   clearAlert() {
     this.message = null;
     this.messageType = null;
@@ -156,16 +221,17 @@ export class ResourceDialogComponent {
   public createResource(resource: ResourceRo) {
 
     this.submitInProgress = true;
-    this.editGroupService.createResourceForGroup(this.resource, this.group, this.domain).subscribe((result: ResourceRo) => {
-      if (!!result) {
-        this.closeDialog();
+    this.editGroupService.createResourceForGroup(this.resource, this.group, this.domain).subscribe({
+      next: (result: ResourceRo) => {
+        if (!!result) {
+          this.closeDialog();
+        }
+        this.submitInProgress = false;
+      }, error: (error) => {
+        this.httpErrorHandlerService.handleHttpError(error);
+        this.submitInProgress = false;
       }
-      this.submitInProgress = false;
-    }, (error) => {
-      this.alertService.error(error.error?.errorDescription)
-      this.submitInProgress = false;
     });
-
   }
 
   public saveResource(resource: ResourceRo): void {
@@ -176,8 +242,8 @@ export class ResourceDialogComponent {
           this.closeDialog();
         }
         this.submitInProgress = false;
-      }, error: (err: any): void => {
-        this.alertService.error(err.error?.errorDescription)
+      }, error: (error: any): void => {
+        this.httpErrorHandlerService.handleHttpError(error);
         this.submitInProgress = false;
       }
     });
diff --git a/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts b/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts
index 9d18d5531cb38f50ee4148dec62df5680b11e3b7..2457d3bddc8e16e18e9aa3e1c79c064634da49d5 100644
--- a/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts
+++ b/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts
@@ -4,7 +4,9 @@ import {MatPaginator, PageEvent} from "@angular/material/paginator";
 import {DomainRo} from "../../common/model/domain-ro.model";
 import {GroupRo} from "../../common/model/group-ro.model";
 import {MemberTypeEnum} from "../../common/enums/member-type.enum";
-import {ResourceDefinitionRo} from "../../system-settings/admin-extension/resource-definition-ro.model";
+import {
+  ResourceDefinitionRo
+} from "../../system-settings/admin-extension/resource-definition-ro.model";
 import {ResourceRo} from "../../common/model/resource-ro.model";
 import {EditResourceController} from "./edit-resource.controller";
 import {MatTableDataSource} from "@angular/material/table";
@@ -24,17 +26,21 @@ export class EditResourceComponent implements OnInit, BeforeLeaveGuard {
   @ViewChild("resourcePaginator") paginator: MatPaginator;
 
   constructor(private editResourceController: EditResourceController) {
-    this.dataSource  = editResourceController;
+    this.dataSource = editResourceController;
   }
 
   ngOnInit() {
     console.log("EditResourceComponent: ngOnInit")
     if (!this.selectedResource) {
       this.editResourceController.refreshDomains();
+    } else {
+      // always refresh resources when selected resource is set
+      this.editResourceController.refreshResources();
     }
   }
 
-  ngAfterViewInit():void {
+
+  ngAfterViewInit(): void {
     // bind data to resource controller
     this.dataSource.paginator = this.paginator;
   }
@@ -47,6 +53,7 @@ export class EditResourceComponent implements OnInit, BeforeLeaveGuard {
   get hasResources(): boolean {
     return this.editResourceController.data?.length > 0;
   }
+
   get domainList(): DomainRo[] {
     return this.editResourceController.domainList;
   };
diff --git a/smp-angular/src/app/edit/edit-resources/edit-resource.controller.ts b/smp-angular/src/app/edit/edit-resources/edit-resource.controller.ts
index a9b699b438544fa229e9fdafc10800f173aed114..7332599da2c305c2b284ccc5b21905fc9be2f022 100644
--- a/smp-angular/src/app/edit/edit-resources/edit-resource.controller.ts
+++ b/smp-angular/src/app/edit/edit-resources/edit-resource.controller.ts
@@ -3,12 +3,17 @@ import {GroupRo} from "../../common/model/group-ro.model";
 import {ResourceRo} from "../../common/model/resource-ro.model";
 import {TableResult} from "../../common/model/table-result.model";
 import {DomainRo} from "../../common/model/domain-ro.model";
-import {ResourceDefinitionRo} from "../../system-settings/admin-extension/resource-definition-ro.model";
+import {
+  ResourceDefinitionRo
+} from "../../system-settings/admin-extension/resource-definition-ro.model";
 import {EditResourceService} from "./edit-resource.service";
 import {EditDomainService} from "../edit-domain/edit-domain.service";
 import {EditGroupService} from "../edit-group/edit-group.service";
-import {AlertMessageService} from "../../common/alert-message/alert-message.service";
+import {
+  AlertMessageService
+} from "../../common/alert-message/alert-message.service";
 import {MatTableDataSource} from "@angular/material/table";
+import {SecurityEventService} from "../../security/security-event.service";
 
 /**
  * The purpose of the EditResourceController is to  control the data of edit resource components when navigating
@@ -18,7 +23,7 @@ import {MatTableDataSource} from "@angular/material/table";
  * @since 5.1
  */
 @Injectable()
-export class EditResourceController extends MatTableDataSource<ResourceRo>{
+export class EditResourceController extends MatTableDataSource<ResourceRo> {
 
   domainList: DomainRo[] = [];
   groupList: GroupRo[] = [];
@@ -39,8 +44,30 @@ export class EditResourceController extends MatTableDataSource<ResourceRo>{
     private groupService: EditGroupService,
     private resourceService: EditResourceService,
     private alertService: AlertMessageService,
+    private securityEventService: SecurityEventService
   ) {
     super();
+    this.securityEventService.onLogoutSuccessEvent().subscribe(value => {
+      this.clearSelectedData();
+    });
+    this.securityEventService.onLoginSuccessEvent().subscribe(value => {
+      this.clearSelectedData();
+    });
+  }
+
+
+  private clearSelectedData() {
+    this.domainList = [];
+    this.groupList = [];
+    this._selectedDomain = null;
+    this._selectedGroup = null;
+    this._selectedResource = null;
+    this._selectedDomainResourceDefs = [];
+    this.pageIndex = 0;
+    this.pageSize = 10;
+    this.resourcesFilter = {};
+    this.isLoadingResults = false;
+    super.data = [];
   }
 
   get selectedDomain(): DomainRo {
@@ -77,6 +104,20 @@ export class EditResourceController extends MatTableDataSource<ResourceRo>{
     return this._selectedResource;
   };
 
+  selectedResourceUpdated(resource: ResourceRo) {
+    // find current resource from list by resource id
+    if (resource.resourceId == this._selectedResource.resourceId) {
+      this._selectedResource.resourceTypeIdentifier = resource.resourceTypeIdentifier;
+      this._selectedResource.identifierScheme = resource.identifierScheme;
+      this._selectedResource.identifierValue = resource.identifierValue;
+      this._selectedResource.visibility = resource.visibility;
+      this._selectedResource.reviewEnabled = resource.reviewEnabled
+    } else {
+      console.log('selected resource not found')
+      this.selectedResource = resource;
+    }
+  }
+
   @Input() set selectedResource(resource: ResourceRo) {
     this._selectedResource = resource;
   };
@@ -88,12 +129,14 @@ export class EditResourceController extends MatTableDataSource<ResourceRo>{
   refreshDomains() {
     this.isLoadingResults = true;
     this.domainService.getDomainsForResourceAdminUserObservable()
-      .subscribe({next: (result: DomainRo[]) => {
-        this.updateDomainList(result)
-      }, error: (err: any) => {
-        this.alertService.error(err.error?.errorDescription)
-        this.isLoadingResults = false;
-      }});
+      .subscribe({
+        next: (result: DomainRo[]) => {
+          this.updateDomainList(result)
+        }, error: (err: any) => {
+          this.alertService.error(err.error?.errorDescription)
+          this.isLoadingResults = false;
+        }
+      });
   }
 
   refreshGroups() {
@@ -104,11 +147,13 @@ export class EditResourceController extends MatTableDataSource<ResourceRo>{
     }
     this.isLoadingResults = true;
     this.groupService.getDomainGroupsForResourceAdminObservable(this.selectedDomain)
-      .subscribe((result: GroupRo[]) => {
-        this.updateGroupList(result)
-      }, (error: any) => {
-        this.isLoadingResults = false;
-        this.alertService.error(error.error?.errorDescription)
+      .subscribe({
+        next: (result: GroupRo[]) => {
+          this.updateGroupList(result)
+        }, error: (error: any) => {
+          this.isLoadingResults = false;
+          this.alertService.error(error.error?.errorDescription)
+        }
       });
   }
 
@@ -121,21 +166,25 @@ export class EditResourceController extends MatTableDataSource<ResourceRo>{
     this.isLoadingResults = true;
     this.resourceService.getGroupResourcesForResourceAdminObservable(this.selectedGroup, this.selectedDomain,
       this.resourcesFilter, this.pageIndex, this.pageSize)
-      .subscribe((result: TableResult<ResourceRo>) => {
-        this.updateResourceList(result.serviceEntities)
-        this.isLoadingResults = false;
-      }, (error: any) => {
-        this.isLoadingResults = false;
-        this.alertService.error(error.error?.errorDescription)
+      .subscribe({
+        next: (result: TableResult<ResourceRo>) => {
+          this.updateResourceList(result.serviceEntities)
+          this.isLoadingResults = false;
+        }, error: (error: any) => {
+          this.isLoadingResults = false;
+          this.alertService.error(error.error?.errorDescription)
+        }
       });
   }
 
   refreshDomainsResourceDefinitions() {
     this.domainService.getDomainResourceDefinitionsObservable(this.selectedDomain)
-      .subscribe((result: ResourceDefinitionRo[]) => {
-        this._selectedDomainResourceDefs = result
-      }, (error: any) => {
-        this.alertService.error(error.error?.errorDescription)
+      .subscribe({
+        next: (result: ResourceDefinitionRo[]) => {
+          this._selectedDomainResourceDefs = result
+        }, error: (error: any) => {
+          this.alertService.error(error.error?.errorDescription)
+        }
       });
   }
 
@@ -158,11 +207,21 @@ export class EditResourceController extends MatTableDataSource<ResourceRo>{
   }
 
   updateResourceList(list: ResourceRo[]) {
+    let currR: ResourceRo = this.selectedResource;
+    this.selectedResource = null;
     this.data = list;
-    // select first resource by default
-    if (!!list && list.length > 0) {
+
+    if (!!currR) {
+      this.selectedResource = list.find(r =>
+        r.identifierScheme == currR.identifierScheme &&
+        r.identifierValue == currR.identifierValue);
+    }
+
+    if (!this.selectedResource && !!list && list.length > 0) {
       this.selectedResource = list[0];
     }
+
+
   }
 
   applyResourceFilter(event: Event) {
diff --git a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html
index fe07b3bbaf6f3cd3c246f2637f779d53c0c98419..0418cd9753bbb420d4bc4c1971411d87d2971612 100644
--- a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html
+++ b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.html
@@ -1,7 +1,6 @@
 <div id="edit-resource-panel" class="mat-elevation-z2">
   <mat-toolbar class="mat-elevation-z2">
     <mat-toolbar-row class="smp-toolbar-row">
-
       <button id="showResource" mat-raised-button
               color="primary"
               matTooltip="{{ 'resource.details.panel.tooltip.show.resource' | translate }}"
@@ -41,10 +40,15 @@
       >
     </mat-form-field>
     <mat-checkbox formControlName="reviewEnabled"
+                  (click)="onReviewEnabledChanged($event)"
                   matTooltip="{{ 'resource.details.panel.label.resource.review.enabled' | translate }}"
                   id="reviewEnabled_id">
       {{ "resource.details.panel.tooltip.resource.review.enabled" | translate }}
     </mat-checkbox>
+    <smp-warning-panel *ngIf="showReviewEnabledHint"
+                       type="warning"
+                       icon="warning"
+    label="{{ 'resource.details.panel.review.disabled.confirmation.dialog.description' | translate }}"></smp-warning-panel>
     <mat-form-field style="width:100%">
       <mat-label>{{ "resource.details.panel.label.resource.visibility" | translate }}</mat-label>
       <select matNativeControl formControlName="visibility"
@@ -76,5 +80,4 @@
       [label]="visibilityDescription"
     ></smp-warning-panel>
   </form>
-
 </div>
diff --git a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts
index 0329de97e2d1b94e2fd4e178365c61d26f24ecee..62bb3c2a895157ae7d51d3042e2ccba1ed486ad9 100644
--- a/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts
+++ b/smp-angular/src/app/edit/edit-resources/resource-details-panel/resource-details-panel.component.ts
@@ -25,6 +25,9 @@ import {
   WindowSpinnerService
 } from "../../../common/services/window-spinner.service";
 import {EditResourceController} from "../edit-resource.controller";
+import {
+  ConfirmationDialogComponent
+} from "../../../common/dialogs/confirmation-dialog/confirmation-dialog.component";
 
 
 @Component({
@@ -33,7 +36,6 @@ import {EditResourceController} from "../edit-resource.controller";
   styleUrls: ['./resource-details-panel.component.scss']
 })
 export class ResourceDetailsPanelComponent implements BeforeLeaveGuard {
-
   readonly groupVisibilityOptions = Object.keys(VisibilityEnum)
     .map(el => {
       return {key: el, value: VisibilityEnum[el]}
@@ -157,8 +159,8 @@ export class ResourceDetailsPanelComponent implements BeforeLeaveGuard {
         try {
           if (!!result) {
             this.alertService.successForTranslation("resource.details.panel.alert.resource.saved");
-            this.editResourceController.selectedResource = result;
-            this._resource = result;
+            this.editResourceController.selectedResourceUpdated(result);
+            this.resource = result;
             this.resourceForm.markAsPristine();
           }
         } finally {
@@ -174,4 +176,30 @@ export class ResourceDetailsPanelComponent implements BeforeLeaveGuard {
   public onResetButtonClicked() {
     this.resourceForm.reset(this._resource);
   }
+
+  async onReviewEnabledChanged(event: any) {
+    let newReviewEnabled: boolean = event.target.checked;
+    let showWarning: boolean = this._resource?.reviewEnabled && !newReviewEnabled;
+
+
+    if (showWarning) {
+      this.dialog.open(ConfirmationDialogComponent, {
+        data: {
+          title: await lastValueFrom(this.translateService.get("resource.details.panel.review.disabled.confirmation.dialog.title")),
+          description: await lastValueFrom(this.translateService.get("resource.details.panel.review.disabled.confirmation.dialog.description"))
+        }
+      }).afterClosed().subscribe(result => {
+        if (!result) {
+          // prevent default does not work in case of "async"
+          this.resourceForm.controls['reviewEnabled'].setValue(true);
+          this.resourceForm.controls['reviewEnabled'].markAsPristine();
+        }
+      });
+    }
+  }
+
+  get showReviewEnabledHint(): boolean {
+    return this._resource?.reviewEnabled === true
+      && this.resourceForm.get('reviewEnabled').value !== true;
+  }
 }
diff --git a/smp-angular/src/app/edit/edit-resources/subresource-panel/subresource-panel.component.ts b/smp-angular/src/app/edit/edit-resources/subresource-panel/subresource-panel.component.ts
index 3caf86a4909283bca50cf7a5373f5627d15ff280..679751f4676838d1bc66d0c2b9186b7c9c76b379 100644
--- a/smp-angular/src/app/edit/edit-resources/subresource-panel/subresource-panel.component.ts
+++ b/smp-angular/src/app/edit/edit-resources/subresource-panel/subresource-panel.component.ts
@@ -1,4 +1,4 @@
-import {AfterViewInit, Component, Input, OnInit, ViewChild,} from '@angular/core';
+import {AfterViewInit, Component, Input, ViewChild,} from '@angular/core';
 import {MatDialog} from "@angular/material/dialog";
 import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard";
 import {MatPaginator} from "@angular/material/paginator";
@@ -17,6 +17,7 @@ import {SubresourceDefinitionRo} from "../../../system-settings/admin-extension/
 import {NavigationNode, NavigationService} from "../../../window/sidenav/navigation-model.service";
 import {TranslateService} from "@ngx-translate/core";
 import {lastValueFrom} from "rxjs";
+import StringUtils from "../../../common/utils/string-utils";
 
 
 @Component({
@@ -185,7 +186,7 @@ export class SubresourcePanelComponent implements AfterViewInit, BeforeLeaveGuar
       data: {
         title: await lastValueFrom(this.translateService.get("subresource.panel.delete.confirmation.dialog.title")),
         description: await lastValueFrom(this.translateService.get("subresource.panel.delete.confirmation.dialog.description", {
-          identifierScheme: this.selected.identifierScheme,
+          identifierScheme: StringUtils.toEmpty(this.selected.identifierScheme),
           identifierValue: this.selected.identifierValue
         }))
       }
@@ -208,7 +209,7 @@ export class SubresourcePanelComponent implements AfterViewInit, BeforeLeaveGuar
       .subscribe(async (result: SubresourceRo) => {
           if (result) {
             this.alertService.success(await lastValueFrom(this.translateService.get("subresource.panel.success.delete", {
-              identifierScheme: this.selected.identifierScheme,
+              identifierScheme: StringUtils.toEmpty(this.selected.identifierScheme),
               identifierValue: this.selected.identifierValue
             })));
             this.selected = null;
@@ -217,10 +218,8 @@ export class SubresourcePanelComponent implements AfterViewInit, BeforeLeaveGuar
           this.alertService.error(error.error?.errorDescription);
         }
       );
-
   }
 
-
   public onResourceSelected(resource: ResourceRo) {
     this.selected = resource;
   }
diff --git a/smp-angular/src/app/http/http-session-interceptor.ts b/smp-angular/src/app/http/http-session-interceptor.ts
index d3cd24c4fb91786ec07936f6f4871a78cd8c7214..2e6a7f1cde465472910665a655097406c53b34fa 100644
--- a/smp-angular/src/app/http/http-session-interceptor.ts
+++ b/smp-angular/src/app/http/http-session-interceptor.ts
@@ -7,6 +7,7 @@ import {MatDialog} from "@angular/material/dialog";
 import {
   SessionExpirationDialogComponent
 } from "../common/dialogs/session-expiration-dialog/session-expiration-dialog.component";
+import {TranslateService} from "@ngx-translate/core";
 
 /*
  * A custom interceptor that handles session expiration before it happens.
@@ -26,6 +27,8 @@ export class HttpSessionInterceptor implements HttpInterceptor {
   private timerToLogoutId: number;
 
   constructor(public securityService: SecurityService,
+              private alertService: AlertMessageService,
+              private translateService: TranslateService,
               private dialog: MatDialog) {
   }
 
@@ -33,7 +36,7 @@ export class HttpSessionInterceptor implements HttpInterceptor {
     clearTimeout(this.timerId);
     clearTimeout(this.timerToLogoutId);
     let user = this.securityService.getCurrentUser();
-    if (user && user.sessionMaxIntervalTimeoutInSeconds && user.sessionMaxIntervalTimeoutInSeconds > this.TIME_BEFORE_EXPIRATION_IN_SECONDS) {
+    if (user?.sessionMaxIntervalTimeoutInSeconds && user.sessionMaxIntervalTimeoutInSeconds > this.TIME_BEFORE_EXPIRATION_IN_SECONDS) {
       let timeout = Math.min((user.sessionMaxIntervalTimeoutInSeconds - this.TIME_BEFORE_EXPIRATION_IN_SECONDS) * 1000, this.MAXIMUM_TIMEOUT_VALUE);
       this.timerId = setTimeout(() => this.sessionExpiringSoon(user.sessionMaxIntervalTimeoutInSeconds), timeout);
     }
@@ -44,6 +47,7 @@ export class HttpSessionInterceptor implements HttpInterceptor {
     // Logout the user after the session expires
     this.timerToLogoutId = setTimeout(() => {
       this.securityService.logout();
+      this.alertService.errorForTranslation("session.alert.message.logout.expired", true);
     }, this.TIME_BEFORE_EXPIRATION_IN_SECONDS * 1000);
 
     this.dialog.open(SessionExpirationDialogComponent, {
diff --git a/smp-angular/src/app/login/login.component.html b/smp-angular/src/app/login/login.component.html
index 6c01f9a9be280877a8ed690bf84030faa0ae8464..df99e9706fdce776d3c40e5a0d0759d1115fbdb9 100644
--- a/smp-angular/src/app/login/login.component.html
+++ b/smp-angular/src/app/login/login.component.html
@@ -29,7 +29,7 @@
 
 
 <ng-template #loginFormContainer>
-  <div [formGroup]="loginForm" class="form-control">
+  <div [formGroup]="loginForm" class="form-control" (ngSubmit)="login()" (keydown.enter)="onLoginFormEnterKeyDown($event)">
     <mat-form-field style="width: 100%">
       <mat-label>{{ "login.label.login.username" | translate }}</mat-label>
       <input matInput id="username_id"
@@ -40,6 +40,7 @@
     <mat-form-field style="width: 100%">
       <mat-label>{{ "login.label.password" | translate }}</mat-label>
       <input matInput id="password_id" type="password"
+
              formControlName="password" required>
     </mat-form-field>
     <button mat-raised-button color="primary" id="loginbutton_id" [disabled]="!loginForm.valid"
diff --git a/smp-angular/src/app/login/login.component.ts b/smp-angular/src/app/login/login.component.ts
index e0a10aac6a273d0817bb736ebf2a948f8089fc87..5a5ce8703232adc20767213aab17e2dedd3bb113 100644
--- a/smp-angular/src/app/login/login.component.ts
+++ b/smp-angular/src/app/login/login.component.ts
@@ -1,22 +1,33 @@
 import {Component, OnDestroy, OnInit} from '@angular/core';
 import {ActivatedRoute, Router} from '@angular/router';
 import {SecurityService} from '../security/security.service';
-import {AlertMessageService} from '../common/alert-message/alert-message.service';
+import {
+  AlertMessageService
+} from '../common/alert-message/alert-message.service';
 import {SecurityEventService} from '../security/security-event.service';
 import {User} from '../security/user.model';
 import {MatDialog} from '@angular/material/dialog';
-import {DefaultPasswordDialogComponent} from 'app/security/default-password-dialog/default-password-dialog.component';
 import {lastValueFrom, Subscription} from 'rxjs';
 import {
   ExpiredPasswordDialogComponent
 } from '../common/dialogs/expired-password-dialog/expired-password-dialog.component';
 import {GlobalLookups} from "../common/global-lookups";
-import {PasswordChangeDialogComponent} from "../common/dialogs/password-change-dialog/password-change-dialog.component";
-import {InformationDialogComponent} from "../common/dialogs/information-dialog/information-dialog.component";
+import {
+  PasswordChangeDialogComponent
+} from "../common/dialogs/password-change-dialog/password-change-dialog.component";
+import {
+  InformationDialogComponent
+} from "../common/dialogs/information-dialog/information-dialog.component";
 import {formatDate} from "@angular/common";
-import {EntityStatus} from "../common/enums/entity-status.enum";
-import {FormControl, FormGroup, Validators} from "@angular/forms";
+import {
+  FormGroup,
+  UntypedFormBuilder,
+  UntypedFormControl,
+  UntypedFormGroup,
+  Validators
+} from "@angular/forms";
 import {TranslateService} from "@ngx-translate/core";
+import {WindowSpinnerService} from "../common/services/window-spinner.service";
 
 @Component({
   templateUrl: './login.component.html',
@@ -24,8 +35,8 @@ import {TranslateService} from "@ngx-translate/core";
 })
 export class LoginComponent implements OnInit, OnDestroy {
 
-  loginForm: FormGroup;
-  resetForm: FormGroup;
+  loginForm: UntypedFormGroup;
+  resetForm: UntypedFormGroup;
   loading = false;
   returnUrl: string;
   sub: Subscription;
@@ -39,17 +50,28 @@ export class LoginComponent implements OnInit, OnDestroy {
               private alertService: AlertMessageService,
               private securityEventService: SecurityEventService,
               private dialog: MatDialog,
-              private translateService: TranslateService) {
+              private translateService: TranslateService,
+              private fb: UntypedFormBuilder,
+              private windowSpinnerService: WindowSpinnerService) {
+    this.loginForm = fb.group({
+      'username': new UntypedFormControl({value: ''}, [Validators.required]),
+      'password': new UntypedFormControl({value: ''}, [Validators.required]),
+    });
+    this.resetForm = new FormGroup({
+      'resetUsername': new UntypedFormControl({value: ''}, [Validators.required]),
+    });
+    this.loginForm.controls['username'].setValue('');
+    this.loginForm.controls['password'].setValue('');
+    this.resetForm.controls['resetUsername'].setValue('');
   }
 
 
   ngOnInit() {
-    this.initForm();
     this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
-
+    // make reference to this to be available in async functions where ''this'' is something else
     this.sub = this.securityEventService.onLoginSuccessEvent().subscribe(
       user => {
-        if (user && user.passwordExpired) {
+        if (user?.passwordExpired) {
           if (user.forceChangeExpiredPassword) {
             this.dialog.open(PasswordChangeDialogComponent, {
               data: {
@@ -82,10 +104,10 @@ export class LoginComponent implements OnInit, OnDestroy {
         switch (error.status) {
           case HTTP_UNAUTHORIZED:
             message = error.error.errorDescription;
-            this.loginForm['password'].setValue('');
+            this.loginForm.controls['password'].setValue('');
             break;
           case HTTP_FORBIDDEN:
-            const forbiddenCode = error.message;
+            const forbiddenCode = error?.message;
             switch (forbiddenCode) {
               case USER_INACTIVE:
                 message = await lastValueFrom(this.translateService.get("login.error.inactive.user"));
@@ -93,7 +115,7 @@ export class LoginComponent implements OnInit, OnDestroy {
               default:
                 message = await lastValueFrom(this.translateService.get("login.error.invalid.credentials", {errorStatus: error.status}));
                 // clear the password
-                this.loginForm['password'].setValue('');
+                this.loginForm.controls['password'].setValue('');
                 break;
             }
             break;
@@ -109,24 +131,21 @@ export class LoginComponent implements OnInit, OnDestroy {
       });
   }
 
-  private initForm() {
-    this.loginForm = new FormGroup({
-      username: new FormControl('', Validators.required),
-      password: new FormControl('', Validators.required),
-    });
-
-    this.resetForm = new FormGroup({
-      resetUsername: new FormControl('', Validators.required),
-    });
-
+  onLoginFormEnterKeyDown(event: KeyboardEvent) {
+    if (this.loginForm.valid
+      && !this.windowSpinnerService.showSpinner) {
+      event.preventDefault();
+      this.login();
+    }
   }
 
   async login() {
+
     this.alertService.clearAlert();
     if (this.loginForm.valid) {
       this.securityService.login(
-        this.loginForm.get('username').value,
-        this.loginForm.get('password').value
+        this.loginForm.controls['username'].value,
+        this.loginForm.controls['password'].value
       );
     } else {
       this.alertService.error(await lastValueFrom(this.translateService.get("login.error.invalid.username.or.password")));
@@ -137,7 +156,7 @@ export class LoginComponent implements OnInit, OnDestroy {
     this.alertService.clearAlert();
     if (this.resetForm.valid) {
       this.securityService.requestCredentialReset(
-        this.resetForm.get('resetUsername').value
+        this.resetForm.controls['resetUsername'].value
       );
     } else {
       this.alertService.error(await lastValueFrom(this.translateService.get("login.error.invalid.username")));
diff --git a/smp-angular/src/app/resource-search/resource-search-controller.ts b/smp-angular/src/app/resource-search/resource-search-controller.ts
index 44695c9b9b02352f79dcfe8b2881effa371a343f..097b3865186a9bd4a4cb7750f866598d3c94b1c8 100644
--- a/smp-angular/src/app/resource-search/resource-search-controller.ts
+++ b/smp-angular/src/app/resource-search/resource-search-controller.ts
@@ -1,13 +1,22 @@
-import {SearchTableController} from '../common/search-table/search-table-controller';
-import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
+import {
+  SearchTableController
+} from '../common/search-table/search-table-controller';
+import {MatDialog, MatDialogRef} from '@angular/material/dialog';
 import {ResourceSearchRo} from './resource-search-ro.model';
 import {of} from "rxjs/internal/observable/of";
-import {SearchTableValidationResult} from "../common/search-table/search-table-validation-result.model";
-import {SearchTableEntity} from "../common/search-table/search-table-entity.model";
+import {
+  SearchTableValidationResult
+} from "../common/search-table/search-table-validation-result.model";
+import {
+  SearchTableEntity
+} from "../common/search-table/search-table-entity.model";
 
 export class ResourceSearchController implements SearchTableController {
 
-  constructor(public dialog: MatDialog) { }
+  constructor(public dialog: MatDialog) {
+
+
+  }
 
   public showDetails(row): MatDialogRef<any> {
     return null;
@@ -20,7 +29,8 @@ export class ResourceSearchController implements SearchTableController {
     return null;
   }
 
-  public delete(row: any) { }
+  public delete(row: any) {
+  }
 
   newDialog(config): MatDialogRef<any> {
     if (config && config.data && config.data.edit) {
@@ -34,10 +44,11 @@ export class ResourceSearchController implements SearchTableController {
     return null;
   }
 
-  public dataSaved() {}
+  public dataSaved() {
+  }
 
-  validateDeleteOperation(rows: Array<SearchTableEntity>){
-    return of( this.newValidationResult(true) );
+  validateDeleteOperation(rows: Array<SearchTableEntity>) {
+    return of(this.newValidationResult(true));
   }
 
   public newValidationResult(result: boolean, message?: string): SearchTableValidationResult {
@@ -54,7 +65,7 @@ export class ResourceSearchController implements SearchTableController {
 
   isRecordChanged(oldModel, newModel): boolean {
     for (var property in oldModel) {
-      const isEqual = this.isEqual(newModel[property],oldModel[property]);
+      const isEqual = this.isEqual(newModel[property], oldModel[property]);
       if (!isEqual) {
         return true; // Property has changed
       }
diff --git a/smp-angular/src/app/resource-search/resource-search.component.ts b/smp-angular/src/app/resource-search/resource-search.component.ts
index b447010189c2927373b70cf8df2bf0d001720701..c8a85b61666de30b0e01c4f64e36196d79ff1da6 100644
--- a/smp-angular/src/app/resource-search/resource-search.component.ts
+++ b/smp-angular/src/app/resource-search/resource-search.component.ts
@@ -10,18 +10,27 @@ import {
 } from '@angular/core';
 import {ColumnPicker} from '../common/column-picker/column-picker.model';
 import {MatDialog} from '@angular/material/dialog';
-import {AlertMessageService} from '../common/alert-message/alert-message.service';
+import {
+  AlertMessageService
+} from '../common/alert-message/alert-message.service';
 import {ResourceSearchController} from './resource-search-controller';
 import {HttpClient} from '@angular/common/http';
 import {SmpConstants} from "../smp.constants";
 import {GlobalLookups} from "../common/global-lookups";
-import {SearchTableComponent} from "../common/search-table/search-table.component";
+import {
+  SearchTableComponent
+} from "../common/search-table/search-table.component";
 import {ResourceSearchRo} from "./resource-search-ro.model";
 import {SubresourceSearchRo} from "./subresource-search-ro.model";
-import {ResourceFilterOptionsService} from "../common/services/resource-filter-options.service";
-import {ResourceFilterOptionsRo} from "../common/model/resource-filter-options-ro.model";
+import {
+  ResourceFilterOptionsService
+} from "../common/services/resource-filter-options.service";
+import {
+  ResourceFilterOptionsRo
+} from "../common/model/resource-filter-options-ro.model";
 import {TranslateService} from "@ngx-translate/core";
 import {lastValueFrom} from "rxjs";
+import {SecurityEventService} from "../security/security-event.service";
 
 @Component({
   templateUrl: './resource-search.component.html',
@@ -47,9 +56,14 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView
               public dialog: MatDialog,
               private changeDetector: ChangeDetectorRef,
               private resourceFilterOptionsService: ResourceFilterOptionsService,
-              private translateService: TranslateService) {
+              private translateService: TranslateService,
+              private securityEventService: SecurityEventService) {
 
     this.baseUrl = SmpConstants.REST_PUBLIC_SEARCH_RESOURCE;
+    this.securityEventService.onLogoutSuccessEvent().subscribe(value => {
+      // refresh the search table pn logout
+      this.searchTable.search();
+    });
   }
 
   ngOnInit() {
@@ -64,6 +78,7 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView
         this.alertService.exception(await lastValueFrom(this.translateService.get("resource.search.error.fetch.resource.metadata")), err);
       }
     });
+
   }
 
   async initColumns() {
@@ -127,15 +142,15 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView
   }
 
   createResourceURL(row: ResourceSearchRo) {
-    return (!row?.domainCode? "" : row.domainCode+ '/')
-          + (!row?.resourceDefUrlSegment?"" : row.resourceDefUrlSegment + '/')
-          + encodeURIComponent((!row.participantScheme ? '' : row.participantScheme) + '::' + row.participantIdentifier);
+    return (!row?.domainCode ? "" : row.domainCode + '/')
+      + (!row?.resourceDefUrlSegment ? "" : row.resourceDefUrlSegment + '/')
+      + encodeURIComponent((!row.participantScheme ? '' : row.participantScheme) + '::' + row.participantIdentifier);
   }
 
   createServiceMetadataURL(row: ResourceSearchRo, rowSMD: SubresourceSearchRo) {
     return this.createResourceURL(row)
-            + '/' + rowSMD.subresourceDefUrlSegment + '/'
-            + encodeURIComponent((!rowSMD.documentIdentifierScheme ? '' : rowSMD.documentIdentifierScheme) + '::' + rowSMD.documentIdentifier);
+      + '/' + rowSMD.subresourceDefUrlSegment + '/'
+      + encodeURIComponent((!rowSMD.documentIdentifierScheme ? '' : rowSMD.documentIdentifierScheme) + '::' + rowSMD.documentIdentifier);
   }
 
   details(row: any) {
diff --git a/smp-angular/src/app/security/security.service.ts b/smp-angular/src/app/security/security.service.ts
index 4e8d97adba684e3ee75bdc559bd8157eb8b45385..b1e82dc40b2d2ce166d737040c49a1478adf3cd5 100644
--- a/smp-angular/src/app/security/security.service.ts
+++ b/smp-angular/src/app/security/security.service.ts
@@ -15,6 +15,7 @@ import {MatDialog} from "@angular/material/dialog";
 import {Router} from "@angular/router";
 import {TranslateService} from "@ngx-translate/core";
 import {WindowSpinnerService} from "../common/services/window-spinner.service";
+import {SmpErrorCode} from "../common/enums/smp-error-code.enum";
 
 @Injectable()
 export class SecurityService {
@@ -38,6 +39,7 @@ export class SecurityService {
   }
 
   login(username: string, password: string) {
+    this.windowSpinnerService.showSpinner = true;
     let headers: HttpHeaders = new HttpHeaders({'Content-Type': 'application/json'});
     return this.http.post<User>(SmpConstants.REST_PUBLIC_SECURITY_AUTHENTICATION,
       JSON.stringify({
@@ -51,9 +53,14 @@ export class SecurityService {
           this.securityEventService.notifyLoginSuccessEvent(response);
         },
         error: (error: any) => {
+          this.windowSpinnerService.showSpinner = false
           this.alertService.error(error.error?.errorDescription)
           this.securityEventService.notifyLoginErrorEvent(error);
+
+        }, complete: () => {
+          this.windowSpinnerService.showSpinner = false
         }
+
       });
   }
 
@@ -119,12 +126,16 @@ export class SecurityService {
         complete: () => {
           this.windowSpinnerService.showSpinner = false;
           this.router.navigate(['/login']);
-          }, // completeHandler
+        }, // completeHandler
         error: (error: any) => {
           this.windowSpinnerService.showSpinner = false;
-          this.router.navigate(['/login']);
+          // if the error is not related to the password, we redirect to the login page
+          console
+          if (error.error?.errorCode !== SmpErrorCode.ERROR_CODE_INVALID_NEW_PASSWORD) {
+            this.router.navigate(['/login']);
+          }
           this.alertService.error(error);
-          },    // errorHandler
+        },    // errorHandler
         next: async () => {
           this.alertService.success(await lastValueFrom(this.translateService.get("reset.credentials.success.password.reset")), true, -1);
         }
@@ -194,13 +205,15 @@ export class SecurityService {
     let subject = new ReplaySubject<boolean>();
     if (callServer) {
       //we get the username from the server to trigger the redirection to the login screen in case the user is not authenticated
-      this.getCurrentUsernameFromServer().subscribe((user: User) => {
-        if (!user) {
-          this.clearLocalStorage();
+      this.getCurrentUsernameFromServer().subscribe({
+        next: (user: User) => {
+          if (!user) {
+            this.clearLocalStorage();
+          }
+          subject.next(user !== null);
+        }, error: (user: any) => {
+          subject.next(false);
         }
-        subject.next(user !== null);
-      }, (user: string) => {
-        subject.next(false);
       });
 
     } else {
diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts
index 8d8947ec3da841882c0c42840dc2a0ca19462e94..db9ae842a9f48524a8f296b14dea8c4f429c40fe 100644
--- a/smp-angular/src/app/smp.constants.ts
+++ b/smp-angular/src/app/smp.constants.ts
@@ -17,6 +17,7 @@ export class SmpConstants {
   public static readonly PATH_ACTION_REVIEW_APPROVE: string = 'review-approve';
   public static readonly PATH_ACTION_REVIEW_REJECT: string = 'review-reject';
   public static readonly PATH_ACTION_VALIDATE: string = 'validate';
+  public static readonly PATH_ACTION_SEARCH_REFERENCE_DOCUMENTS: string  = "reference-documents";
   public static readonly PATH_ACTION_PUT: string = 'put';
   public static readonly PATH_ACTION_RETRIEVE: string = 'retrieve';
   public static readonly PATH_ACTION_SEARCH: string = 'search';
@@ -72,6 +73,7 @@ export class SmpConstants {
   public static readonly REST_EDIT_DOCUMENT_RESOURCE_REVIEW_REQUEST = SmpConstants.REST_EDIT_DOCUMENT_RESOURCE + '/' + SmpConstants.PATH_ACTION_REVIEW_REQUEST;
   public static readonly REST_EDIT_DOCUMENT_RESOURCE_REVIEW_APPROVE = SmpConstants.REST_EDIT_DOCUMENT_RESOURCE + '/' + SmpConstants.PATH_ACTION_REVIEW_APPROVE;
   public static readonly REST_EDIT_DOCUMENT_RESOURCE_REVIEW_REJECT = SmpConstants.REST_EDIT_DOCUMENT_RESOURCE + '/' + SmpConstants.PATH_ACTION_REVIEW_REJECT;
+  public static readonly REST_EDIT_DOCUMENT_RESOURCE_SEARCH_REFERENCES = SmpConstants.REST_EDIT_DOCUMENT_RESOURCE + '/' + SmpConstants.PATH_ACTION_SEARCH_REFERENCE_DOCUMENTS;
 
   public static readonly REST_EDIT_DOCUMENT_SUBRESOURCE = SmpConstants.REST_EDIT_RESOURCE_SHORT + '/' + SmpConstants.PATH_RESOURCE_TYPE_SUBRESOURCE + '/' + SmpConstants.PATH_PARAM_ENC_SUBRESOURCE_ID
     + '/' + SmpConstants.PATH_RESOURCE_TYPE_DOCUMENT;
@@ -81,16 +83,15 @@ export class SmpConstants {
   public static readonly REST_EDIT_DOCUMENT_SUBRESOURCE_REVIEW_REQUEST = SmpConstants.REST_EDIT_DOCUMENT_SUBRESOURCE + '/' + SmpConstants.PATH_ACTION_REVIEW_REQUEST;
   public static readonly REST_EDIT_DOCUMENT_SUBRESOURCE_REVIEW_APPROVE = SmpConstants.REST_EDIT_DOCUMENT_SUBRESOURCE + '/' + SmpConstants.PATH_ACTION_REVIEW_APPROVE;
   public static readonly REST_EDIT_DOCUMENT_SUBRESOURCE_REVIEW_REJECT = SmpConstants.REST_EDIT_DOCUMENT_SUBRESOURCE + '/' + SmpConstants.PATH_ACTION_REVIEW_REJECT;
+  public static readonly REST_EDIT_DOCUMENT_SUBRESOURCE_SEARCH_REFERENCES = SmpConstants.REST_EDIT_DOCUMENT_SUBRESOURCE + '/' + SmpConstants.PATH_ACTION_SEARCH_REFERENCE_DOCUMENTS;
 
   public static readonly REST_EDIT_SUBRESOURCE = SmpConstants.REST_EDIT_RESOURCE_SHORT + '/' + SmpConstants.PATH_RESOURCE_TYPE_SUBRESOURCE;
   public static readonly REST_EDIT_SUBRESOURCE_DELETE = SmpConstants.REST_EDIT_SUBRESOURCE + '/' + SmpConstants.PATH_PARAM_ENC_SUBRESOURCE_ID
     + '/' + SmpConstants.PATH_ACTION_DELETE;
   public static readonly REST_EDIT_SUBRESOURCE_CREATE = SmpConstants.REST_EDIT_SUBRESOURCE + '/' + SmpConstants.PATH_ACTION_CREATE;
 
-
   public static readonly REST_EDIT_REVIEW_TASK = SmpConstants.REST_EDIT + SmpConstants.PATH_RESOURCE_TYPE_REVIEW +  '/'
 
-
   /* Public services */
   public static readonly REST_PUBLIC_SEARCH_RESOURCE = SmpConstants.REST_PUBLIC + SmpConstants.PATH_ACTION_SEARCH;
   public static readonly REST_PUBLIC_SEARCH_RESOURCE_METADATA = SmpConstants.REST_PUBLIC + SmpConstants.PATH_ACTION_SEARCH + "/metadata";
diff --git a/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts b/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts
index f4f95cd9aa99d9dd07e371d84f2868a1921d4994..dca44484f4f361ba20a59801033a1161a0aaabaa 100644
--- a/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/admin-domain.component.ts
@@ -249,6 +249,7 @@ export class AdminDomainComponent implements OnInit, OnDestroy, AfterViewInit, B
       status: EntityStatus.NEW,
       smlRegistered: false,
       smlClientCertAuth: false,
+      adminMemberCount: 0,
     }
   }
 
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 afd05698d7bd6cdfe390d3adb443a1dfd174849a..fe2db960c9ab76e15d68def2c8fe8aa136e3cd44 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
@@ -8,7 +8,7 @@
                        type="warning"
                        [htmlContent]="warningMessage"></smp-warning-panel>
     <mat-form-field style="width:100%">
-      <mat-label>{{ "domain.panel.label.domain" | translate: {value: domainForm.controls['adminMemberCount'].value} }}</mat-label>
+      <mat-label>{{ "domain.panel.label.domain" | translate }}</mat-label>
       <input matInput
              id="domainCode_id" #domainCode
              matTooltip="{{ 'domain.panel.tooltip.domain' | translate }}"
diff --git a/smp-angular/src/app/system-settings/admin-domain/domain-properties-panel/domain-properties-panel.component.ts b/smp-angular/src/app/system-settings/admin-domain/domain-properties-panel/domain-properties-panel.component.ts
index 06b7b6799d95b34c034d6d5fdcbf23ff2921cdd9..1bdddb0c4b008360b9d8ad139246c5954261dc6b 100644
--- a/smp-angular/src/app/system-settings/admin-domain/domain-properties-panel/domain-properties-panel.component.ts
+++ b/smp-angular/src/app/system-settings/admin-domain/domain-properties-panel/domain-properties-panel.component.ts
@@ -32,10 +32,7 @@ export class DomainPropertiesPanelComponent implements OnInit, OnDestroy, Before
   _domain: DomainRo = null;
   selected?: DomainPropertyRo;
   dataChanged: boolean = false
-
-
   private domainPropertyUpdatedEventSub: Subscription = Subscription.EMPTY;
-
   propertyDataSource: MatTableDataSource<DomainPropertyRo> = new MatTableDataSource();
 
   constructor(private domainService: AdminDomainService,
@@ -74,7 +71,6 @@ export class DomainPropertiesPanelComponent implements OnInit, OnDestroy, Before
     if (!!this._domain) {
       if (!this.systemAdminService) {
         this.editDomainService.getDomainProperties(this._domain);
-
       } else {
         this.domainService.getDomainProperties(this._domain);
       }
diff --git a/smp-angular/src/app/system-settings/admin-extension/extension.component.ts b/smp-angular/src/app/system-settings/admin-extension/extension.component.ts
index b1e3431433909e7220b75f4535d3044f087503df..f010b54b3b9d8f6e9202f96af5b830658e9093a4 100644
--- a/smp-angular/src/app/system-settings/admin-extension/extension.component.ts
+++ b/smp-angular/src/app/system-settings/admin-extension/extension.component.ts
@@ -20,7 +20,6 @@ export class ExtensionComponent implements OnInit, AfterViewInit, BeforeLeaveGua
   @ViewChild(MatSort) sort: MatSort;
 
   constructor(extensionService: ExtensionService) {
-
     extensionService.onExtensionsUpdatesEvent().subscribe(updatedExtensions => {
         this.updateExtensions(updatedExtensions);
       }
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 ef5e6c12d7c84e1ba4f4d2f1314b10393cbe52eb..ed5684d53955b4f32d0c1e6fddf386166b4f82f9 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
@@ -151,74 +151,81 @@ export class AdminUserComponent implements AfterViewInit, BeforeLeaveGuard {
   }
 
   updateUserData(user: UserRo) {
+
+    // capture this to variable because of async call 'this' inside targets the wrong object
+    const thatAdminUserComponent = this;
     // change only allowed data
     this.adminUserService.updateManagedUser(user).subscribe({
       async next(user: UserRo) {
         if (user) {
-          this.selected = null;
-          this.managedUserData = null;
-          this.loadTableData(user.username);
-          this.alertService.success(await lastValueFrom(this.translateService.get("admin.user.success.update", {username: user.username})));
+          thatAdminUserComponent.selected = null;
+          thatAdminUserComponent.managedUserData = null;
+          thatAdminUserComponent.loadTableData(user.username);
+          thatAdminUserComponent.alertService.success(await lastValueFrom(thatAdminUserComponent.translateService.get("admin.user.success.update", {username: user.username})));
 
         }
       }, error(error) {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+        if (thatAdminUserComponent.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
           return;
         }
-        this.alertService.error(error.error?.errorDescription)
+        thatAdminUserComponent.alertService.error(error.error?.errorDescription)
       }
     });
   }
 
   createUserData(user: UserRo) {
     // change only allowed data
+    // capture this to variable because of async call 'this' inside targets the wrong object
+    const thatAdminUserComponent = this;
     this.adminUserService.createManagedUser(user).subscribe({
       async next(user: UserRo) {
         if (user) {
-          this.selected = null;
-          this.managedUserData = null;
-          this.loadTableData(user.username);
-          this.alertService.success(await lastValueFrom(this.translateService.get("admin.user.success.create", {username: user.username})));
+          thatAdminUserComponent.selected = null;
+          thatAdminUserComponent.managedUserData = null;
+          thatAdminUserComponent.loadTableData(user.username);
+          thatAdminUserComponent.alertService.success(await lastValueFrom(thatAdminUserComponent.translateService.get("admin.user.success.create", {username: user.username})));
         }
       }, error(error) {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+        if (thatAdminUserComponent.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
           return;
         }
-        this.alertService.error(error.error?.errorDescription)
+        thatAdminUserComponent.alertService.error(error.error?.errorDescription)
       }
     });
   }
 
   async onDeleteSelectedUserClicked() {
-
+    // capture this to variable because of async call 'this' inside targets the wrong object
+    const thatAdminUserComponent = this;
     this.dialog.open(ConfirmationDialogComponent, {
       data: {
-        title: await lastValueFrom(this.translateService.get("admin.user.delete.confirmation.dialog.title", {username: this.managedUserData?.username})),
-        description: await lastValueFrom(this.translateService.get("admin.user.delete.confirmation.dialog.description"))
+        title: await lastValueFrom(thatAdminUserComponent.translateService.get("admin.user.delete.confirmation.dialog.title", {username: this.managedUserData?.username})),
+        description: await lastValueFrom(thatAdminUserComponent.translateService.get("admin.user.delete.confirmation.dialog.description"))
       }
     }).afterClosed().subscribe(result => {
       if (result) {
-        this.deleteUser(this.managedUserData);
+        this.deleteUser(thatAdminUserComponent.managedUserData);
       }
     });
   }
 
   deleteUser(user: UserRo) {
-
+    // capture this to variable because of async call 'this' inside targets the wrong object
+    const thatAdminUserComponent = this;
     // change only allowed data
     this.adminUserService.deleteManagedUser(user).subscribe({
       async next(user: UserRo) {
         if (user) {
-          this.selected = null;
-          this.managedUserData = null;
-          this.loadTableData();
-          this.alertService.success(await lastValueFrom(this.translateService.get("admin.user.success.delete", {username: user.username})));
+          thatAdminUserComponent.selected = null;
+          thatAdminUserComponent.managedUserData = null;
+          thatAdminUserComponent.loadTableData();
+          thatAdminUserComponent.alertService.success(await lastValueFrom(thatAdminUserComponent.translateService.get("admin.user.success.delete", {username: user.username})));
         }
       }, error(error) {
-        if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
+        if (thatAdminUserComponent.httpErrorHandlerService.logoutOnInvalidSessionError(error)) {
           return;
         }
-        this.alertService.error(error.error?.errorDescription)
+        thatAdminUserComponent.alertService.error(error.error?.errorDescription)
       }
     });
 
@@ -235,7 +242,7 @@ export class AdminUserComponent implements AfterViewInit, BeforeLeaveGuard {
       if (result) {
         this.selected = null;
         this.managedUserData = null;
-        this.loadTableData();
+        this.loadTableData(user.username);
         this.alertService.success(await lastValueFrom(this.translateService.get("admin.user.success.password.updated")));
       }
     });
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss
index e05994ebd40993c1d0ad1ab80963d366e047da20..28fabcf74d1072be6c1b1ea487ed583b4c350ae3 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss
+++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss
@@ -1,9 +1,7 @@
 @use '../../../../_smp-theme-helper' as smp;
 
 @mixin set-component-colors($theme) {
-  .access-token:hover {
-    background-color: smp.get-theme-color($theme, primary, 0.2);
-  }
+
 }
 
 
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html
index 74291e1d520577910a1e16dd5af2d0a96b40a8dc..65e3e708dbceac65c84fad0566c3dc0b2483cd71 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html
+++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html
@@ -1,35 +1,52 @@
 <mat-expansion-panel [expanded]="_expanded">
-  <mat-expansion-panel-header style="height: 72px">
-    <div style="display: flex; flex-direction: column;width: 100%; padding-right: 10px">
-      <smp-warning-panel *ngIf="!!_credential?.expired;" class="smp-certificate-warning-panel"
-                         [padding]="false"
-                         icon="error"
-                         label="{{ 'access.token.panel.label.token.expired' | translate }}">
-      </smp-warning-panel>
-      <div style="display: flex; flex-direction: row; justify-content: space-between; gap: 3px; padding-left: 5px;">
-        <input matInput style="flex-grow: 1; padding: 5px 0"
-               [value]="credential?.name"
-               [disabled]="!credential?.active"
-               maxlength="255" readonly>
-        <div style="display: inline">
+  <mat-expansion-panel-header style="height: 115px">
+    <div
+      style="flex-direction: column;width: 100%;margin-right: 10px;margin-top: 5px">
+      <div
+        style="display: flex; flex-direction: row; justify-content: space-between; gap: 3px; padding-left: 5px;">
+
+        <mat-form-field style="flex-grow: 1">
+          <mat-label>{{ "access.token.panel.label.name" | translate }}</mat-label>
+          <input matInput
+                 [value]="_credential.name"
+                 maxlength="255" disabled>
+          <mat-hint
+            style="display: flex; flex-direction: row; font-size: 0.8em;overflow: hidden">
+            <span
+              *ngIf="credentialForm.controls['activeFrom'].value;else elseNoDate">{{ credentialForm.controls["activeFrom"].value | date: dateFormat }}</span>
+            &nbsp;&nbsp;-&nbsp;&nbsp;
+            <span
+              *ngIf="credentialForm.controls['expireOn'].value;else elseNoDate">{{ credentialForm.controls["expireOn"].value | date: dateFormat }}</span>;
+            <span
+              style="overflow: hidden">{{ credentialForm.controls["description"].value }}</span>
+            <ng-template #elseNoDate><span>&nbsp;/&nbsp;</span></ng-template>
+          </mat-hint>
+        </mat-form-field>
+        <div class="access-token-control-panel">
           <button id="deleteButton" mat-raised-button
-                  (click)="onDeleteButtonClicked()"
-                  color="primary" >
+                  (click)="onDeleteButtonClicked($event)"
+                  color="primary">
             <mat-icon>delete</mat-icon>
             <span>{{ "access.token.panel.button.delete" | translate }}</span>
           </button>
           <button id="saveButton" mat-raised-button
-                  (click)="onSaveButtonClicked()"
+                  (click)="onSaveButtonClicked($event)"
                   color="primary"
-                  [disabled]="!submitButtonEnabled" >
+                  [disabled]="!submitButtonEnabled">
             <mat-icon>save</mat-icon>
             <span>{{ "access.token.panel.button.save" | translate }}</span>
           </button>
         </div>
       </div>
+      <smp-warning-panel *ngIf="!!_credential?.expired;"
+                         [padding]="false"
+                         style="padding-bottom: 5px"
+                         icon="error"
+                         label="{{ 'access.token.panel.label.token.expired' | translate }}">
+      </smp-warning-panel>
     </div>
   </mat-expansion-panel-header>
-  <div class="panel smp-data-panel"  [formGroup]="credentialForm" (ngSubmit)="onSaveButtonClicked()">
+  <div class="smp-data-panel" [formGroup]="credentialForm">
     <mat-form-field style="width: 100%">
       <mat-label>{{ "access.token.panel.label.description" | translate }}</mat-label>
       <input matInput
@@ -38,20 +55,30 @@
     </mat-form-field>
     <div style="display: flex;flex-flow: row wrap;">
 
-      <mat-checkbox formControlName="active" style="align-self: center; padding-bottom: 1em;padding-right: 2em">
+      <mat-checkbox formControlName="active"
+                    style="align-self: center; padding-bottom: 1em;padding-right: 2em">
         {{ "access.token.panel.label.active" | translate }}
       </mat-checkbox>
 
       <mat-form-field appearance="fill" style="flex-grow: 1">
         <mat-label>{{ "access.token.panel.label.validity.dates" | translate }}</mat-label>
-        <mat-date-range-input [rangePicker]="picker" [min]="minSelectableDate" >
-          <input matStartDate formControlName="activeFrom" placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}">
-          <input matEndDate formControlName="expireOn" placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}">
+        <mat-date-range-input [rangePicker]="picker" [min]="minSelectableDate">
+          <input matStartDate formControlName="activeFrom"
+                 placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}"
+                 required>
+          <input matEndDate formControlName="expireOn"
+                 placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}"
+                 required>
         </mat-date-range-input>
-        <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
+        <mat-datepicker-toggle matIconSuffix
+                               [for]="picker"></mat-datepicker-toggle>
         <mat-date-range-picker #picker></mat-date-range-picker>
-        <smp-field-error *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')">{{ "access.token.panel.error.invalid.start.date" | translate }}</smp-field-error >
-        <smp-field-error *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid')">{{ "access.token.panel.error.invalid.end.date" | translate }}</smp-field-error >
+        <smp-field-error
+          *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')  || credentialForm.controls.activeFrom.hasError('required')">{{ "access.token.panel.error.invalid.start.date" | translate }}
+        </smp-field-error>
+        <smp-field-error
+          *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid') || credentialForm.controls.expireOn.hasError('required')">{{ "access.token.panel.error.invalid.end.date" | translate }}
+        </smp-field-error>
       </mat-form-field>
     </div>
     <div style="display: flex;flex-flow: row;">
@@ -59,26 +86,33 @@
         <mat-label>{{ "access.token.panel.label.login.failed.attempts" | translate }}</mat-label>
         <input matInput
                [value]="sequentialLoginFailureCount"
-               id="sequentialTokenLoginFailureCount_id" maxlength="255" disabled readonly>
+               id="sequentialTokenLoginFailureCount_id" maxlength="255" disabled
+               readonly>
       </mat-form-field>
-      <mat-form-field style="flex-grow:2 "  floatLabel="always">
+      <mat-form-field style="flex-grow:2 " floatLabel="always">
         <mat-label>{{ "access.token.panel.label.login.last.failed.attempt" | translate }}</mat-label>
-        <input id="LastFailedAttempt_id" matInput [ngxMatDatetimePicker]="LastFailedAttemptPicker"
+        <input id="LastFailedAttempt_id" matInput
+               [ngxMatDatetimePicker]="LastFailedAttemptPicker"
                [value]="lastFailedLoginAttempt"
                placeholder="---"
                readonly>
-        <mat-datepicker-toggle matSuffix [for]="LastFailedAttemptPicker" style="visibility: hidden"></mat-datepicker-toggle>
-        <ngx-mat-datetime-picker #LastFailedAttemptPicker [showSpinners]="true" [showSeconds]="false"
+        <mat-datepicker-toggle matSuffix [for]="LastFailedAttemptPicker"
+                               style="visibility: hidden"></mat-datepicker-toggle>
+        <ngx-mat-datetime-picker #LastFailedAttemptPicker [showSpinners]="true"
+                                 [showSeconds]="false"
                                  [hideTime]="false"></ngx-mat-datetime-picker>
       </mat-form-field>
-      <mat-form-field style="flex-grow: 2"  floatLabel="always">
+      <mat-form-field style="flex-grow: 2" floatLabel="always">
         <mat-label>{{ "access.token.panel.label.suspended.until" | translate }}</mat-label>
-        <input id="SuspendedUtil_id" matInput [ngxMatDatetimePicker]="suspendedUtilPicker"
+        <input id="SuspendedUtil_id" matInput
+               [ngxMatDatetimePicker]="suspendedUtilPicker"
                [value]="suspendedUtil"
                placeholder="---"
                readonly>
-        <mat-datepicker-toggle matSuffix [for]="suspendedUtilPicker" style="visibility: hidden"></mat-datepicker-toggle>
-        <ngx-mat-datetime-picker #suspendedUtilPicker [showSpinners]="true" [showSeconds]="false"
+        <mat-datepicker-toggle matSuffix [for]="suspendedUtilPicker"
+                               style="visibility: hidden"></mat-datepicker-toggle>
+        <ngx-mat-datetime-picker #suspendedUtilPicker [showSpinners]="true"
+                                 [showSeconds]="false"
                                  [hideTime]="false"></ngx-mat-datetime-picker>
 
       </mat-form-field>
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..babb6cf50300f108c23582446630a294690f8281 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss
+++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss
@@ -0,0 +1,9 @@
+.access-token-panel {
+  border-bottom: 1px solid #e0e0e0;
+}
+
+.access-token-control-panel {
+  display: flex;
+  flex-direction: column;
+  gap: 3px
+}
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts
index 9a6e22e34398d8872ad065e4f673ce9c63687648..285eb0024c1649fd2a03a697165bceda2795a7e9 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts
+++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts
@@ -1,7 +1,41 @@
 import {Component, EventEmitter, Input, Output} from '@angular/core';
-import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
+import {
+  AbstractControl,
+  FormBuilder,
+  FormControl,
+  FormGroup, ValidatorFn
+} from "@angular/forms";
 import {CredentialRo} from "../../../security/credential.model";
 import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard";
+import {GlobalLookups} from "../../../common/global-lookups";
+
+
+export function notAfterCurrentDateValidator(): ValidatorFn {
+  return (control: AbstractControl): { [key: string]: any } | null => {
+    let date = control.value;
+    if (date) {
+      // make date mutable and the modification
+      date = new Date(date);
+      date.setHours(0, 0, 0, 0);
+    }
+    const forbidden = date && date > Date.now();
+
+    return forbidden ? { 'matStartDateInvalid': { value: control.value } } : null;
+  };
+}
+
+export function notBeforeCurrentDateValidator(): ValidatorFn {
+  return (control: AbstractControl): { [key: string]: any } | null => {
+    let date = control.value;
+    if (date) {
+      // make date mutable and the modification
+      date = new Date(date);
+      date.setHours(23, 59, 59, 999);
+    }
+    const forbidden = date && date < Date.now();
+    return forbidden ? { 'matEndDateInvalid': { value: control.value } } : null;
+  };
+}
 
 
 @Component({
@@ -11,24 +45,27 @@ import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guar
 })
 export class AccessTokenPanelComponent implements BeforeLeaveGuard {
 
-  @Output() minSelectableDate: Date = new Date();
+  @Output() minSelectableDate: Date = null;
   @Output() onDeleteEvent: EventEmitter<CredentialRo> = new EventEmitter();
   @Output() onSaveEvent: EventEmitter<CredentialRo> = new EventEmitter();
 
-  dateFormat: string = 'yyyy-MM-dd'
-
   _credential: CredentialRo;
   credentialForm: FormGroup;
   _expanded: boolean = false;
 
-  constructor(private formBuilder: FormBuilder) {
+
+
+  constructor(private formBuilder: FormBuilder,
+              private globalLookups: GlobalLookups) {
     this.credentialForm = formBuilder.group({
       // common values
+      'name': new FormControl({value: '', disabled: true}),
       'active': new FormControl({value: '', disabled: false}),
       'description': new FormControl({value: '', disabled: false}),
-      'activeFrom': new FormControl({value: '', disabled: false}),
-      'expireOn': new FormControl({value: '', disabled: false})
+      'activeFrom': new FormControl({value: '', disabled: false}, [notAfterCurrentDateValidator()]),
+      'expireOn': new FormControl({value: '', disabled: false}, [notBeforeCurrentDateValidator()])
     });
+
   }
 
   get credential(): CredentialRo {
@@ -38,11 +75,13 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard {
   @Input() set credential(value: CredentialRo) {
     this._credential = value;
     if (this._credential) {
+      this.credentialForm.controls['name'].setValue(this._credential.name);
       this.credentialForm.controls['active'].setValue(this._credential.active);
       this.credentialForm.controls['description'].setValue(this._credential.description);
       this.credentialForm.controls['activeFrom'].setValue(this._credential.activeFrom);
       this.credentialForm.controls['expireOn'].setValue(this._credential.expireOn);
     } else {
+      this.credentialForm.controls['name'].setValue(null);
       this.credentialForm.controls['active'].setValue(null);
       this.credentialForm.controls['description'].setValue(null);
       this.credentialForm.controls['activeFrom'].setValue(null);
@@ -53,16 +92,30 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard {
     this.credentialForm.markAsPristine();
   }
 
-  onDeleteButtonClicked() {
+  onDeleteButtonClicked(event: MouseEvent) {
     this.onDeleteEvent.emit(this.credential);
+    event?.stopPropagation();
   }
 
-  onSaveButtonClicked() {
+  onSaveButtonClicked(event: MouseEvent) {
     this._credential.active = this.credentialForm.controls['active'].value
     this._credential.description = this.credentialForm.controls['description'].value
-    this._credential.activeFrom = this.credentialForm.controls['activeFrom'].value
-    this._credential.expireOn = this.credentialForm.controls['expireOn'].value
+    let dateFrom = this.credentialForm.controls['activeFrom'].value;
+    if (dateFrom) {
+      // make date mutable and the modification
+      dateFrom = new Date(dateFrom);
+      dateFrom.setHours(0, 0, 0, 0);
+    }
+    this._credential.activeFrom = dateFrom
+    let dateTo = this.credentialForm.controls['expireOn'].value;
+    if (dateTo) {
+      // make date mutable and the modification
+      dateTo = new Date(dateTo);
+      dateTo.setHours(23, 59, 59, 999);
+    }
+    this._credential.expireOn = dateTo
 
+    event?.stopPropagation();
     this.onSaveEvent.emit(this._credential);
   }
 
@@ -71,7 +124,7 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard {
   }
 
   get sequentialLoginFailureCount(): string {
-    return this._credential && this._credential.sequentialLoginFailureCount ?
+    return this._credential?.sequentialLoginFailureCount ?
       this._credential.sequentialLoginFailureCount + "" : "0";
   }
 
@@ -87,4 +140,7 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard {
     return this.credentialForm.dirty;
   }
 
+  get dateFormat(): string {
+    return this.globalLookups.getDateFormat();
+  }
 }
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html
index a6b7f96f9d5f2741d51bd71405a87e1c6038d297..535aa91f957ca84fb7d52df7937a5e488ccf18c5 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html
+++ b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html
@@ -3,33 +3,43 @@
               text="{{ 'user.access.tokens.text' | translate }}"
               [labelColumnContent]="commonToolbar">
 
-    <table mat-table id="user-access-token-table" [dataSource]="dataSource" class="panel smp-data-panel" >
+    <table mat-table id="user-access-token-table" [dataSource]="dataSource"
+           class="panel smp-data-panel">
       <ng-container matColumnDef="accessTokens">
-        <th mat-header-cell *matHeaderCellDef>{{ "user.access.tokens.label.access.tokens" | translate }}</th>
+        <th mat-header-cell
+            *matHeaderCellDef>{{ "user.access.tokens.label.access.tokens" | translate }}
+        </th>
         <td mat-cell *matCellDef="let token"
             [ngClass]="{'datatable-row-error': token.invalid}"
-            [matTooltip]="token.name">
-          <access-token-panel (onDeleteEvent)="onDeleteItemClicked(token)"
+            [matTooltip]="token.name"
+        class="access-token-panel">
+          <access-token-panel class="access-token-panel"
+                              (onDeleteEvent)="onDeleteItemClicked(token)"
                               (onSaveEvent)="onSaveItemClicked(token)"
                               [credential]="token"></access-token-panel>
 
         </td>
-        <tr mat-header-row class="user-access-token-table-header" *matHeaderRowDef="displayedColumns"></tr>
-        <tr mat-row class="user-access-token-table-data" *matRowDef="let myRowData; columns: displayedColumns"></tr>
+        <tr mat-header-row class="user-access-token-table-header"
+            *matHeaderRowDef="displayedColumns"></tr>
+        <tr mat-row class="user-access-token-table-data"
+            *matRowDef="let myRowData; columns: displayedColumns"></tr>
       </ng-container>
     </table>
 
     <mat-paginator class="mat-elevation-z2" id="tokens-paginator"
                    [hidePageSize]="true"
-                   [pageSize]="5" attr.aria-label="{{ 'user.access.tokens.label.select.page' | translate }}"></mat-paginator>
+                   [pageSize]="5"
+                   attr.aria-label="{{ 'user.access.tokens.label.select.page' | translate }}"></mat-paginator>
   </data-panel>
 
 </div>
 
 <ng-template #commonToolbar>
 
-  <button id="createAccessTokenButton" mat-raised-button color="primary" matTooltip="{{ 'user.access.tokens.tooltip.create' | translate }}" style="margin: 2em "
-  (click)="createNewAccessToken()">
+  <button id="createAccessTokenButton" mat-raised-button color="primary"
+          matTooltip="{{ 'user.access.tokens.tooltip.create' | translate }}"
+          style="margin: 2em "
+          (click)="createNewAccessToken()">
     <mat-icon>key</mat-icon>
     <span>{{ "user.access.tokens.button.create" | translate }}</span>
   </button>
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss
index bde62fecdac7bff9df60de91601e44f25d8564b3..1766781f6f50b737e002940eddf6ce12e69cc3d3 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss
+++ b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss
@@ -17,6 +17,7 @@
 #user-access-token-table {
   padding: 0;
   border: none;
+  background-color: transparent !important;
 }
 
 .user-access-token-table-header {
@@ -25,4 +26,5 @@
 
 .user-access-token-table-data td {
   padding: 0;
+  background-color: transparent !important;
 }
diff --git a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts
index 1c1416474551825a2ef6e16ac17479ae2dd27e3d..2be5a50b57e59d1ca2e2fae44879f3a73460955a 100644
--- a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts
+++ b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts
@@ -68,9 +68,12 @@ export class UserAccessTokensComponent implements AfterViewInit, BeforeLeaveGuar
         userAccessToken];
     }
 
+    // show current page after update if possible or previous page
+    let pageIndex = Math.min(this.paginator.pageIndex,
+      Math.floor(this.accessTokens.length / this.paginator.pageSize));
+    // set the data source
     this.dataSource.data = this.accessTokens;
-    // show the last page
-    this.paginator.lastPage();
+    this.paginator.pageIndex = pageIndex;
   }
 
   public trackListItem(index: number, credential: CredentialRo) {
diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html
index 3a97f9e57814c31ed6fbbe50eaa50d704d38c8b3..3d218ac523f05b76dfd56faeeacf9a95b1113956 100644
--- a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html
+++ b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html
@@ -1,28 +1,36 @@
-<mat-expansion-panel [expanded]="_expanded" [formGroup]="credentialForm" (ngSubmit)="onSaveButtonClicked()">
-  <mat-expansion-panel-header style="height: 72px">
-    <div style="display: flex; flex-direction: column;width: 100%; padding-right: 10px">
-      <smp-warning-panel *ngIf="_credential.certificate?.invalid;" class="smp-certificate-warning-panel"
-                         [padding]="false"
-                         icon="error"
-                         label="{{ 'user.certificate.panel.label.invalid.certificate' | translate: { reason: _credential.certificate.invalidReason} }}">
-      </smp-warning-panel>
-      <div style="display: flex;flex-flow: row; align-items: center; width: 100%">
+<mat-expansion-panel [expanded]="_expanded" [formGroup]="credentialForm">
+  <mat-expansion-panel-header style="height: 105px">
+    <div
+      style="display: flex; flex-direction: column;width: 100%; padding-right: 10px;margin-top: 5px">
 
-        <input matInput style="flex-grow: 1; padding: 5px 0" [matTooltip]="credential?.name"
-               [value]="credential?.name"
-               [disabled]="!credential?.active"
-               maxlength="255" readonly>
+      <div
+        style="display: flex;flex-flow: row; align-items: center; width: 100%">
+
+        <mat-form-field style="flex-grow: 1">
+          <mat-label>{{ "user.certificate.panel.label.certificate.id" | translate }}</mat-label>
+          <input matInput
+                 [value]="_credential.name"
+                 maxlength="255" disabled>
+          <mat-hint
+            style="display: flex; flex-direction: row; font-size: 0.8em;overflow: hidden">
+            <span *ngIf="credentialForm.controls['activeFrom'].value;else elseNoDate ">{{ credentialForm.controls["activeFrom"].value | date: dateFormat }}</span>
+            &nbsp;&nbsp;-&nbsp;&nbsp;
+            <span *ngIf="credentialForm.controls['expireOn'].value;else elseNoDate">{{ credentialForm.controls["expireOn"].value | date: dateFormat }}</span>;
+            <span style="overflow: hidden">{{ credentialForm.controls["description"].value }}</span>
+          </mat-hint>
+          <ng-template #elseNoDate><span>&nbsp;/&nbsp;</span></ng-template>
+        </mat-form-field>
 
         <div
-          style="display: flex; flex-direction: row; justify-content: space-between; gap: 3px; padding-left: 5px;">
+          class="user-certificate-control-panel">
           <button id="deleteButton" mat-raised-button
-                  (click)="onDeleteButtonClicked()"
+                  (click)="onDeleteButtonClicked($event)"
                   color="primary">
             <mat-icon>delete</mat-icon>
             <span>{{ "user.certificate.panel.button.delete" | translate }}</span>
           </button>
           <button id="saveButton" mat-raised-button
-                  (click)="onSaveButtonClicked()"
+                  (click)="onSaveButtonClicked($event)"
                   color="primary"
                   [disabled]="!submitButtonEnabled">
             <mat-icon>save</mat-icon>
@@ -30,6 +38,12 @@
           </button>
         </div>
       </div>
+      <smp-warning-panel *ngIf="_credential.certificate?.invalid;"
+                         class="smp-certificate-warning-panel"
+                         [padding]="false"
+                         icon="error"
+                         label="{{ 'user.certificate.panel.label.invalid.certificate' | translate: { reason: _credential.certificate.invalidReason} }}">
+      </smp-warning-panel>
     </div>
   </mat-expansion-panel-header>
   <div class="panel smp-data-panel">
@@ -63,13 +77,17 @@
       <mat-form-field appearance="fill" style="flex-grow: 1">
         <mat-label>{{ "user.certificate.panel.label.validity.dates" | translate }}</mat-label>
         <mat-date-range-input>
-          <input matStartDate formControlName="activeFrom" placeholder="{{ 'user.certificate.panel.placeholder.start.date' | translate }}">
-          <input matEndDate formControlName="expireOn" placeholder="{{ 'user.certificate.panel.placeholder.end.date' | translate }}">
+          <input matStartDate formControlName="activeFrom"
+                 placeholder="{{ 'user.certificate.panel.placeholder.start.date' | translate }}">
+          <input matEndDate formControlName="expireOn"
+                 placeholder="{{ 'user.certificate.panel.placeholder.end.date' | translate }}">
         </mat-date-range-input>
-        <smp-field-error *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')">
+        <smp-field-error
+          *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')">
           {{ "user.certificate.panel.label.invalid.start.date" | translate }}
         </smp-field-error>
-        <smp-field-error *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid')">
+        <smp-field-error
+          *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid')">
           {{ "user.certificate.panel.label.invalid.end.date" | translate }}
         </smp-field-error>
       </mat-form-field>
diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.scss b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.scss
index 588a7d255e8db0eb482aa3fc25b87044a7cfcd24..729c4a8e2cdfc6df447bc43bbe9be881c47f2e59 100644
--- a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.scss
+++ b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.scss
@@ -1,4 +1,11 @@
 .smp-certificate-warning-panel   {
   font-size: 0.8em;
+  padding-bottom: 5px;
+}
+
+.user-certificate-control-panel {
+  display: flex;
+  flex-direction: column;
+  gap: 3px;
 }
 
diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts
index 232de7158629e9b9cd2bfb398168c62d4581b229..3a772a9a4f3241f23c44292f370a90344510b2bd 100644
--- a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts
+++ b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts
@@ -2,6 +2,7 @@ import {Component, EventEmitter, Input, Output} from '@angular/core';
 import {FormBuilder, FormControl, FormGroup} from "@angular/forms";
 import {CredentialRo} from "../../../security/credential.model";
 import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard";
+import {GlobalLookups} from "../../../common/global-lookups";
 
 
 @Component({
@@ -15,13 +16,12 @@ export class UserCertificatePanelComponent  implements  BeforeLeaveGuard {
 
   @Output() onShowCertificate: EventEmitter<CredentialRo> = new EventEmitter();
 
-  dateFormat: string = 'yyyy-MM-dd'
-
   _credential: CredentialRo;
   _expanded: boolean = false;
   credentialForm: FormGroup;
 
-  constructor(private formBuilder: FormBuilder) {
+  constructor(private formBuilder: FormBuilder,
+              private globalLookups: GlobalLookups) {
     this.credentialForm = formBuilder.group({
       // common values
       'active': new FormControl({value: '', disabled: false}),
@@ -59,13 +59,14 @@ export class UserCertificatePanelComponent  implements  BeforeLeaveGuard {
     this.credentialForm.markAsPristine();
   }
 
-  onDeleteButtonClicked() {
-
+  onDeleteButtonClicked(event: MouseEvent) {
     this.onDeleteEvent.emit(this.credential);
+    event?.stopPropagation();
   }
 
-  onSaveButtonClicked() {
+  onSaveButtonClicked(event: MouseEvent) {
     this.onSaveEvent.emit(this.credential);
+    event?.stopPropagation();
   }
 
   onShowCertificateButtonClicked(){
@@ -95,4 +96,8 @@ export class UserCertificatePanelComponent  implements  BeforeLeaveGuard {
     return this.credentialForm.dirty;
   }
 
+  get dateFormat(): string {
+    return this.globalLookups.getDateFormat();
+  }
+
 }
diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts b/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts
index 694b7c37004193bf51430878e777a3e6aa1dbd6d..c375ab987e23268259a5374f34e7da77c38191fa 100644
--- a/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts
+++ b/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts
@@ -73,8 +73,13 @@ export class UserCertificatesComponent implements AfterViewInit, BeforeLeaveGuar
         certificate];
     }
 
+    // show current page after update if possible or previous page
+    let pageIndex = Math.min(this.paginator.pageIndex,
+      Math.floor(this.certificates.length / this.paginator.pageSize));
+    // set data
     this.dataSource.data = this.certificates;
-    // show the last page
+    // set page
+    this.paginator.pageIndex = pageIndex;
     this.paginator.lastPage();
   }
 
diff --git a/smp-angular/src/app/window/sidenav/navigation-model.service.ts b/smp-angular/src/app/window/sidenav/navigation-model.service.ts
index 12738b08cdd807aa497db15d0a5b7366f8662a78..12c2b2822b21c74834e8209e95cb4f606f3e3cee 100644
--- a/smp-angular/src/app/window/sidenav/navigation-model.service.ts
+++ b/smp-angular/src/app/window/sidenav/navigation-model.service.ts
@@ -92,11 +92,11 @@ export class NavigationService extends MatTreeNestedDataSource<NavigationNode> {
       }
     );
     securityEventService.onLogoutSuccessEvent().subscribe(value => {
-        this.refreshNavigationTree();
+        this.reset();
       }
     );
     securityEventService.onLogoutErrorEvent().subscribe(value => {
-        this.refreshNavigationTree();
+        this.reset();
       }
     );
   }
diff --git a/smp-angular/src/assets/i18n/en.json b/smp-angular/src/assets/i18n/en.json
index 7c1b5c714030072bb8dc22281148b8363d2715c0..5ff9a793928f89c7ee66bb93d79e2ebf66516acb 100644
--- a/smp-angular/src/assets/i18n/en.json
+++ b/smp-angular/src/assets/i18n/en.json
@@ -1,19 +1,14 @@
 {
-
   "column.selection.link.all": "All",
   "column.selection.link.none": "None",
   "column.selection.link.show": "Show columns",
   "column.selection.link.hide": "Hide columns",
-
   "cancel.dialog.text": "Do you want to cancel all unsaved operations?",
   "cancel.dialog.title": "Unsaved data",
-
   "certificate.dialog.button.close": "Close",
   "certificate.dialog.title": "Certificate details",
-
   "confirmation.dialog.button.no": "No",
   "confirmation.dialog.button.yes": "Yes",
-
   "credentials.dialog.button.close": "Close",
   "credentials.dialog.button.copy.access.token": "Copy Access token value",
   "credentials.dialog.button.import": "Import",
@@ -36,12 +31,10 @@
   "credentials.dialog.placeholder.expire.on": "Expire On",
   "credentials.dialog.placeholder.start.date": "Start date",
   "credentials.dialog.placeholder.valid.from": "Valid from",
-
   "dialog.button.close": "Close",
   "dialog.button.no": "No",
   "dialog.button.ok": "OK",
   "dialog.button.yes": "Yes",
-
   "document.property.dialog.button.ok": "OK",
   "document.property.dialog.button.cancel": "Cancel",
   "document.property.dialog.error.property.already.exists": "The property name already exists!",
@@ -52,14 +45,11 @@
   "document.property.dialog.label.property.value": "Property value:",
   "document.property.dialog.title.new.mode": "Create Document Property",
   "document.property.dialog.title.edit.mode": "Edit Document Property",
-
   "expired.password.dialog.text": "Your password is more than three months old. Please change it as soon as possible!",
   "expired.password.dialog.title": "Password about to expire",
-
   "manage.members.dialog.button.close": "Close",
   "manage.members.dialog.title.invite.mode": "Invite {{membershipType}} member",
   "manage.members.dialog.title.edit.mode": "Edit {{membershipType}} member",
-
   "member.dialog.button.close": "Close",
   "member.dialog.button.save": "Save",
   "member.dialog.hint.choose.role": "Choose member role",
@@ -74,11 +64,9 @@
   "manage.dialog.title.edit.mode": "Edit {{membershipType}} member",
   "member.dialog.tooltip.role.type": "Role type for the member.",
   "member.dialog.tooltip.permission.review": "Can review document.",
-
   "object.properties.dialog.button.close": "Close",
   "object.properties.dialog.header.key": "Key",
   "object.properties.dialog.header.value": "Value",
-
   "password.change.dialog.button.confirm": "Set/change password",
   "password.change.dialog.button.close": "Close",
   "password.change.dialog.error.old.password.reused": "New password must not be equal than old current password!",
@@ -92,7 +80,6 @@
   "password.change.dialog.title": "Set/Change password dialog",
   "password.change.dialog.success.password.change.admin": "Password has been successfully set/changed.",
   "password.change.dialog.success.password.change.user": "Password has been successfully set/changed. Login again to the application with the new password!",
-
   "property.details.dialog.button.ok": "OK",
   "property.details.dialog.button.cancel": "Cancel",
   "property.details.dialog.error.invalid.property": "Invalid property",
@@ -102,12 +89,11 @@
   "property.details.dialog.legend.description": "Description:",
   "property.details.dialog.title.edit.mode": "{{type}} Property Edit",
   "property.details.dialog.title.new.mode": "New {{type}} Property",
-
   "session.expiration.dialog.button.expire": "Extend",
   "session.expiration.dialog.button.logout": "Logout",
   "session.expiration.dialog.title": "Extend session",
-  "session.expiration.dialog.label.session.about.to.expire": "Your session is about to expire in <b>{{timeLeft}}</b> seconds!<br />Would you like to logout now or extend it for another <b>{{timeout}}</b> seconds?",
-
+  "session.expiration.dialog.label.session.about.to.expire": "Your session is about to expire in <b>{{timeLeft}}</b> seconds!<br />Would you like to logout now or extend it<br /> for another <b>{{timeoutMinutes}}</b> minute(s) and <b>{{timeoutSeconds}}</b> second(s)?",
+  "session.alert.message.logout.expired": "Your session has expired, and you have been logged out.",
   "alert.panel.dialog.title.alert.details": "Alert details",
   "alert.panel.label.column.alert.date": "Alert date",
   "alert.panel.label.column.alert.level": "Alert level",
@@ -145,7 +131,6 @@
   "certificate.panel.placeholder.subject.name": "Subject Name",
   "certificate.panel.placeholder.valid.from": "Valid from date",
   "certificate.panel.placeholder.valid.to": "Valid to date",
-
   "document.properties.panel.label.filter": "Filter",
   "document.properties.panel.label.property": "Property",
   "document.properties.panel.label.value": "Value",
@@ -161,17 +146,16 @@
   "document.properties.panel.tooltip.reset": "Reset changes",
   "document.properties.panel.tab.title": "Document properties",
   "document.properties.panel.tab.button.properties": "Properties",
-
   "document.events.panel.tab.title": "Current Document version events",
   "document.events.panel.tab.button.events": "Events",
   "document.events.panel.label.filter": "Filter",
   "document.events.panel.label.date": "Date",
   "document.events.panel.label.type": "Event type",
+  "document.events.panel.label.status": "Status",
   "document.events.panel.label.username": "Username",
   "document.events.panel.label.source": "Event Source",
   "document.events.panel.label.no.properties.found": "No DocumentVersion events found",
   "document.events.panel.label.select.page": "Select page of events",
-
   "document.versions.panel.tab.title": "All Document Versions",
   "document.versions.panel.tab.button.versions": "Versions",
   "document.versions.panel.label.filter": "Filter",
@@ -181,7 +165,6 @@
   "document.versions.panel.label.created": "Created",
   "document.versions.panel.label.updated": "Last updated",
   "document.versions.panel.label.status": "status",
-
   "membership.panel.button.invite.member": "Invite member",
   "membership.panel.button.edit.membership": "Edit",
   "membership.panel.button.delete.membership": "Remove",
@@ -196,14 +179,12 @@
   "membership.panel.label.username": "Username",
   "membership.panel.label.permission.review": "Can review",
   "membership.panel.placeholder.filter": "Member filter",
-
   "membership.panel.title.domain": "Direct Domain members {{value}}",
   "membership.panel.title.group": "Direct Group members {{value}}",
   "membership.panel.title.resource": "Resource direct members",
   "membership.panel.tooltip.invite.member": "Invite new member",
   "membership.panel.tooltip.edit.membership": "Edit membership of selected user",
   "membership.panel.tooltip.delete.membership": "Delete selected membership",
-
   "user.profile.panel.button.reset": "Reset",
   "user.profile.panel.button.save": "Save",
   "user.profile.panel.button.update.password": "Set/change password",
@@ -258,9 +239,7 @@
   "user.profile.panel.tooltip.application.role": "application role for the user.",
   "user.profile.panel.tooltip.password.expiration.date": "Default password set by system admin! User must change password immediately!",
   "user.profile.panel.value.password.expiration.date": "Default or null password",
-
   "row.limiter.placeholder": "Rows",
-
   "search.table.button.cancel": "Cancel",
   "search.table.button.delete": "Delete",
   "search.table.button.edit": "Edit",
@@ -274,7 +253,6 @@
   "search.table.tooltip.edit": "Edit",
   "search.table.tooltip.delete": "Delete",
   "search.table.success.update": "The operation 'update' completed successfully",
-
   "group.dialog.button.close": "Close",
   "group.dialog.button.save": "Save",
   "group.dialog.description": "To create a new group enter unique group name for the domain and click save.",
@@ -285,7 +263,8 @@
   "group.dialog.label.group.visibility": "Group visibility",
   "group.dialog.placeholder.group.visibility": "Group visibility",
   "group.dialog.tooltip.group.visibility": "Group visibility.",
-
+  "group.dialog.error.group.name.length": "Group name must not be empty and shorter than 512 characters.",
+  "group.dialog.error.group.description.length": "Group description must be shorter than 1024 characters.",
   "domain.group.button.create": "Create",
   "domain.group.button.delete": "Delete",
   "domain.group.button.edit": "Edit data",
@@ -310,7 +289,6 @@
   "domain.group.tooltip.edit": "Edit selected group",
   "domain.group.tooltip.filter": "Member filter",
   "domain.group.tooltip.group.members": "Group members",
-
   "edit.domain.label.configuration": "Configuration",
   "edit.domain.label.domain.code": "Domain code",
   "edit.domain.label.domain.members": "Domain Members",
@@ -321,7 +299,6 @@
   "edit.domain.placeholder.domain.code": "Domain code",
   "edit.domain.text": "Edit Domains administration panel is a tool for domain administrators to manage domain members and domain groups",
   "edit.domain.title": "Edit Domains",
-
   "resource.dialog.button.close": "Close",
   "resource.dialog.button.save": "Save",
   "resource.dialog.description": "To create a new resource enter unique identifier and scheme and click save.",
@@ -337,13 +314,12 @@
   "resource.dialog.tooltip.resource.type": "Select type for the resource.",
   "resource.dialog.tooltip.resource.visibility": "Resource visibility.",
   "resource.dialog.tooltip.resource.review.enabled": "Review process enabled",
-
   "group.resource.panel.button.create": "Create",
   "group.resource.panel.button.delete": "Delete",
   "group.resource.panel.button.edit": "Edit",
   "group.resource.panel.button.members": "Resource members",
   "group.resource.panel.delete.confirmation.dialog.title": "Delete Resource with scheme from DomiSMP",
-  "group.resource.panel.delete.confirmation.dialog.description": "Action will permanently delete resource  [{{identifierScheme}}] and identifier: [{{identifierValue}}]!<br/><br/>Do you wish to continue?",
+  "group.resource.panel.delete.confirmation.dialog.description": "Action will permanently delete resource with scheme [{{identifierScheme}}] and identifier: [{{identifierValue}}]!<br/><br/>Do you wish to continue?",
   "group.resource.panel.label.filter": "Resource filter",
   "group.resource.panel.label.identifier.scheme": "Scheme",
   "group.resource.panel.label.identifier.value": "Identifier",
@@ -361,7 +337,6 @@
   "group.resource.panel.tooltip.delete": "Delete selected resource",
   "group.resource.panel.tooltip.edit": "Edit data",
   "group.resource.panel.tooltip.members": "Group members",
-
   "edit.group.label.resources": "Resources",
   "edit.group.label.members": "Members",
   "edit.group.label.user.not.administrator": "User is not administrator of any of the groups",
@@ -373,11 +348,9 @@
   "edit.group.title": "Edit Group",
   "edit.group.tooltip.select.domain": "Selected domain.",
   "edit.group.tooltip.select.group": "Select group.",
-
   "document.wizard.dialog.button.cancel": "Cancel",
   "document.wizard.dialog.button.ok": "OK",
   "document.wizard.dialog.title": "Resource Extension Wizard",
-
   "resource.details.panel.alert.resource.saved": "Resource data are persisted.",
   "resource.details.panel.label.resource.id": "Resource identifier",
   "resource.details.panel.label.resource.name": "Edit resource document",
@@ -398,6 +371,8 @@
   "resource.details.panel.title": "Resources",
   "resource.details.panel.button.reset": "Reset",
   "resource.details.panel.button.save": "Save",
+  "resource.details.panel.review.disabled.confirmation.dialog.title": "Review disabled?",
+  "resource.details.panel.review.disabled.confirmation.dialog.description": "All document versions with review statuses (UNDER_REVIEW, APPROVED, REJECTED) will be set to DRAFT\nDo you want to continue?",
 
   "document.edit.panel.button.back": "Back",
   "document.edit.panel.button.cancel": "Cancel",
@@ -406,9 +381,9 @@
   "document.edit.panel.button.validate": "Validate",
   "document.edit.panel.button.version.new": "New version",
   "document.edit.panel.button.version.publish": "Publish",
-  "document.edit.panel.button.version.review": "Review",
-  "document.edit.panel.button.version.approve": "Approve",
-  "document.edit.panel.button.version.reject": "Reject",
+  "document.edit.panel.button.version.review.request": "Request review",
+  "document.edit.panel.button.version.review.approve": "Approve",
+  "document.edit.panel.button.version.review.reject": "Reject",
   "document.edit.panel.button.save": "Save",
   "document.edit.panel.cancel.confirmation.dialog.description": "Do you want to cancel all changes on the document?",
   "document.edit.panel.cancel.confirmation.dialog.title": "Cancel changes",
@@ -416,10 +391,14 @@
   "document.edit.panel.label.selected.created.on": "Created on:",
   "document.edit.panel.label.selected.version": "Selected version:",
   "document.edit.panel.label.selected.status": "Status:",
+  "document.edit.panel.label.reference.name": "Reference document name",
   "document.edit.panel.placeholder.version": "All document version",
   "document.edit.panel.success.save": "Document is saved with current version [{{currentResourceVersion}}].",
   "document.edit.panel.success.generate": "Document is generated.",
   "document.edit.panel.success.valid": "Document is Valid.",
+  "document.edit.panel.select.item.reference": "Reference document",
+  "document.edit.panel.select.item.current": "Current document",
+  "document.edit.panel.label.show.document.type": "View document",
   "document.edit.panel.error.document.null": "Can not show document because it is not selected.",
   "document.edit.panel.title": "Resources",
   "document.edit.panel.tooltip.document.wizard": "Show document wizard dialog",
@@ -428,20 +407,54 @@
   "document.edit.panel.tooltip.validate": "Validate resource",
   "document.edit.panel.tooltip.version": "Select version to display.",
   "document.edit.panel.tooltip.version.new": "Create new document version for the resource",
-  "document.edit.panel.tooltip.version.publish": "Publish selected document version for the resource",
-  "document.edit.panel.tooltip.version.review": "Submit selected document version for the review",
-  "document.edit.panel.tooltip.version.approve": "Submit selected document version for the review",
-  "document.edit.panel.tooltip.version.reject": "Submit selected document version for the review",
-  "document.edit.panel.note.editable": "Note: Only documents in following status can be edited: [{{editableDocStatusList}}]",
-
-  "document.metadata.panel.tab.title": "Document metadata",
-  "document.metadata.panel.tab.button.metadata": "Metadata",
-
-  "document.metadata.panel.label.name": "Name",
-  "document.metadata.panel.label.mimetype": "Mimetype",
-  "document.metadata.panel.label.published.version": "Published version",
-  "document.metadata.panel.label.sharing.enabled": "Document sharing enabled",
-  "document.metadata.panel.label.reference.document": "Referenced document",
+  "document.edit.panel.tooltip.version.publish": "Publish selected document version",
+  "document.edit.panel.tooltip.version.request.review": "Submit selected document version for the review",
+  "document.edit.panel.tooltip.version.review.approve.description": "Approve  document version",
+  "document.edit.panel.tooltip.version.review.reject.description": "Reject document version",
+  "document.edit.panel.note.editable": "Note: Only document payloads in following status can be edited: [{{editableDocStatusList}}]",
+  "document.edit.panel.dialog.confirmation.publish.title": "Document publish action confirmation",
+  "document.edit.panel.dialog.confirmation.publish.description": "Do you want to publish the document version?",
+
+  "document.edit.panel.review.dialog.confirmation.title": "Review action confirmation",
+  "document.edit.panel.review.dialog.confirmation.approve.description": "Do you want to <b>approve</b> the document version?",
+  "document.edit.panel.review.dialog.confirmation.reject.description": "Do you want to <b>reject</b> the document version?",
+
+  "document.configuration.panel.tab.title": "Document configuration",
+  "document.configuration.panel.tab.button.metadata": "Metadata",
+  "document.configuration.panel.label.name": "Name",
+  "document.configuration.panel.label.mimetype": "Mimetype",
+  "document.configuration.panel.label.published.version": "Published version",
+  "document.configuration.panel.label.sharing.enabled": "Document payload sharing enabled",
+  "document.configuration.panel.label.reference.document": "Referenced document",
+  "document.configuration.panel.label.reference.document.name": "Document name",
+  "document.configuration.panel.label.reference.document.open.url": "Open URL",
+  "document.configuration.panel.label.reference.resource.scheme": "Resource scheme",
+  "document.configuration.panel.label.reference.resource.value": "Resource value",
+  "document.configuration.panel.label.reference.subresource.scheme": "Subresource. scheme",
+  "document.configuration.panel.label.reference.subresource.value": "Subresource. value",
+  "document.configuration.panel.label.reference.document.not.selected": "No reference document",
+  "document.configuration.panel.button.reference.select": "Select reference",
+  "document.configuration.panel.button.reference.clear": "Clear reference",
+  "document.configuration.panel.tooltip.sharing.enabled": "When selected, others can use the published document payload as template.",
+
+  "reference.document.dialog.title": "Select reference document",
+  "reference.document.dialog.label.resource.value": "Resource value",
+  "reference.document.dialog.label.resource.scheme": "Resource scheme",
+  "reference.document.dialog.label.subresource.value": "Subresource value",
+  "reference.document.dialog.label.subresource.scheme": "Subresource scheme",
+  "reference.document.dialog.label.domain": "Domain",
+  "reference.document.dialog.tooltip.domain": "Select domain",
+  "reference.document.dialog.button.search": "Search",
+  "reference.document.dialog.column.resource.value": "Res. value",
+  "reference.document.dialog.column.resource.scheme": "Res. scheme",
+  "reference.document.dialog.column.subresource.value": "Subr. value",
+  "reference.document.dialog.column.subresource.scheme": "Subr. scheme",
+  "reference.document.dialog.column.open.url": "Open URL",
+  "reference.document.dialog.button.close": "Close",
+  "reference.document.dialog.button.save": "Save",
+  "reference.document.dialog.button.select": "Set selected document as reference",
+  "reference.document.dialog.label.select.page": "Page",
+  "reference.document.dialog.button.reset": "Reset",
 
   "review.edit.dialog.title": "Review tasks details",
   "review.edit.panel.label.review": "Review",
@@ -494,7 +507,7 @@
   "subresource.panel.button.edit": "Edit",
   "subresource.panel.error.delete.resource.data": "Can not delete subresource because of invalid resource data. Is resource selected?",
   "subresource.panel.error.delete.subresource.data": "Can not delete subresource because of invalid subresource data. Is subresource selected?",
-  "subresource.panel.delete.confirmation.dialog.description": "Action will permanently delete subresource [{{identifierScheme}}] and identifier: [{{identifierValue}}]!<br/><br/>Do you wish to continue?",
+  "subresource.panel.delete.confirmation.dialog.description": "Action will permanently delete subresource with scheme: [{{identifierScheme}}] and identifier: [{{identifierValue}}]!<br/><br/>Do you wish to continue?",
   "subresource.panel.delete.confirmation.dialog.title": "Delete Resource with scheme from DomiSMP",
   "subresource.panel.label.filter": "Resource filter",
   "subresource.panel.label.identifier.scheme": "Scheme",
@@ -505,7 +518,7 @@
   "subresource.panel.label.select.pages": "Select pages",
   "subresource.panel.subresource.dialog.title": "Create Subresource Dialog",
   "subresource.panel.placeholder.filter": "Resource filter",
-  "subresource.panel.success.delete": "Subresource [{{identifierScheme}}] and identifier: [{{identifierValue}}] deleted.",
+  "subresource.panel.success.delete": "Subresource with scheme [{{identifierScheme}}] and identifier: [{{identifierValue}}] deleted.",
   "subresource.panel.title": "Subresources",
   "subresource.panel.tooltip.create": "Create",
   "subresource.panel.tooltip.delete": "Delete selected resource",
@@ -591,7 +604,7 @@
 
   "domain.panel.button.reset": "Reset",
   "domain.panel.button.save": "Save",
-  "domain.panel.label.domain": "Domain Code [{{value}}]",
+  "domain.panel.label.domain": "Domain Code",
   "domain.panel.label.domain.already.exists": "The Domain code already exists!",
   "domain.panel.label.domain.default.resource.type": "Default resource type for the domain",
   "domain.panel.label.domain.mandatory": "Domain code must contain only chars and numbers and must be less than 63 chars long.",
@@ -826,6 +839,7 @@
   "access.token.panel.button.save": "Save",
   "access.token.panel.error.invalid.end.date": "Invalid expire on date",
   "access.token.panel.error.invalid.start.date": "Invalid active from date",
+  "access.token.panel.label.name": "Name",
   "access.token.panel.label.active": "Active",
   "access.token.panel.label.description": "Description",
   "access.token.panel.label.login.failed.attempts": "Seq. failed attempts",
@@ -847,6 +861,9 @@
   "user.access.tokens.update.confirmation.dialog.description": "Action will update access token: \"{{credentialName}}\"!<br /><br />Do you wish to continue?",
   "user.access.tokens.update.confirmation.dialog.title": "Update Access token",
   "user.access.tokens.tooltip.create": "Create new Access token",
+  "user.access.tokens.success.deleted": "Access token \"{{credentialName}}\" has been deleted!",
+  "user.access.tokens.success.updated": "Access token \"{{credentialName}}\" has been updated!",
+
 
   "user.certificate.panel.button.delete": "Delete",
   "user.certificate.panel.button.show.details": "Show Details",
@@ -860,6 +877,9 @@
   "user.certificate.panel.label.validity.dates": "Validity period of the certificate",
   "user.certificate.panel.placeholder.end.date": "End date",
   "user.certificate.panel.placeholder.start.date": "Start date",
+  "user.certificate.success.deleted": "Certificate \"{{credentialName}}\" has been deleted!",
+  "user.certificate.success.updated": "Certificate \"{{credentialName}}\" has been updated!",
+  "user.certificate.success.uploaded": "Certificate \"{{credentialName}}\" has been uploaded!",
 
   "user.certificates.button.import": "Import new certificate",
   "user.certificates.label.user.certificate": "User Certificates",
diff --git a/smp-angular/src/styles.css b/smp-angular/src/styles.css
index 48c456a492e3046dd930df20fb72baaef94a63ba..c7991851c85fbfcc5398060e1d22ddbc25010b09 100644
--- a/smp-angular/src/styles.css
+++ b/smp-angular/src/styles.css
@@ -15,6 +15,10 @@ td , th {
   max-width: 200px;
 }
 
+.form-field-full-width {
+  width: 100%;
+}
+
 .smp-data-panel-field {
   width: 100% !important;
 }
diff --git a/smp-resource-extensions/oasis-cppa3-spi/src/main/java/eu/europa/ec/smp/spi/handler/AbstractHandler.java b/smp-resource-extensions/oasis-cppa3-spi/src/main/java/eu/europa/ec/smp/spi/handler/AbstractHandler.java
index 9a3fd51cac2f07a0430578a85b40188b250fb8e2..023a1effab84162789500690a3bd9c0274f31c84 100644
--- a/smp-resource-extensions/oasis-cppa3-spi/src/main/java/eu/europa/ec/smp/spi/handler/AbstractHandler.java
+++ b/smp-resource-extensions/oasis-cppa3-spi/src/main/java/eu/europa/ec/smp/spi/handler/AbstractHandler.java
@@ -67,11 +67,8 @@ public abstract class AbstractHandler implements ResourceHandlerSpi {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
         factory.setNamespaceAware(true);
         factory.setValidating(true);
-        try {
-            factory.setFeature(DISALLOW_DOCTYPE_FEATURE, true);
-        } catch (ParserConfigurationException e) {
-            LOG.warn("DocumentBuilderFactory initialization error. The feature [{}] is not supported by current factory. The feature is ignored.", DISALLOW_DOCTYPE_FEATURE);
-        }
+        enableFeature(factory, DISALLOW_DOCTYPE_FEATURE);
+        enableFeature(factory, XMLConstants.FEATURE_SECURE_PROCESSING);
 
         try {
             return factory.newDocumentBuilder();
@@ -80,6 +77,16 @@ public abstract class AbstractHandler implements ResourceHandlerSpi {
         }
     }
 
+    private static boolean enableFeature(DocumentBuilderFactory factory, String feature) {
+        try {
+            factory.setFeature(feature, true);
+            return true;
+        } catch (ParserConfigurationException e) {
+            LOG.warn("DocumentBuilderFactory initialization error. The feature [{}] is not supported by current factory. The feature is ignored.", feature);
+            return false;
+        }
+    }
+
     private static final ThreadLocal<Unmarshaller> jaxbUnmarshaller = ThreadLocal.withInitial(() -> {
         try {
             JAXBContext jaxbContext = JAXBContext.newInstance(CPP.class);
diff --git a/smp-server-library/pom.xml b/smp-server-library/pom.xml
index ddfe59831ed3a14358db0f71dfd45f2c4e833c65..292bff3360bdd9d6e38819e2470955c4bef3c887 100644
--- a/smp-server-library/pom.xml
+++ b/smp-server-library/pom.xml
@@ -80,6 +80,11 @@
             <groupId>org.springframework</groupId>
             <artifactId>spring-context-support</artifactId>
         </dependency>
+        <dependency>
+            <!-- added only for tool: org.springframework.web.servlet.support.ServletUriComponentsBuilder -->
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.sun.mail</groupId>
             <artifactId>javax.mail</artifactId>
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java
index 04787384baa36c4d5e7d775db41ade0bf62d6e47..999c8349be552e15360be45f02736f988d2ccc1e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java
@@ -22,6 +22,7 @@ import eu.europa.ec.edelivery.smp.data.model.DBConfiguration;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.utils.PropertyUtils;
+import org.slf4j.event.Level;
 
 import javax.persistence.EntityManager;
 import javax.persistence.Transient;
@@ -40,8 +41,6 @@ import static org.apache.commons.lang3.StringUtils.trim;
  * @since 4.2
  */
 public class DatabaseProperties extends Properties {
-    @Transient
-    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DatabaseProperties.class);
 
     private OffsetDateTime lastUpdate;
 
@@ -54,7 +53,7 @@ public class DatabaseProperties extends Properties {
                 String prop =trim(dc.getProperty());
                 String value =trim(dc.getValue());
                 setProperty(prop, value);
-                LOG.info("Database property: [{}] value: [{}]", prop,PropertyUtils.getMaskedData(prop, value) );
+                PropertyUtils.printProperty(prop, value, Level.INFO);
             }
             lastUpdate = (lastUpdate == null || lastUpdate.isBefore(dc.getLastUpdatedOn())) ? dc.getLastUpdatedOn() : lastUpdate;
         }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java
index 68e41fb0a1dc7245a6ef990df2a6408d1f3b9171..f2196507272c65ada79915198bfd368271f83da6 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java
@@ -55,7 +55,7 @@ public class SMPDatabaseConfig {
     @Bean(name = "smpDataSource")
     @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
     public DataSource getDataSource() {
-        LOG.info("Create DomiSMP datasource");
+        LOG.trace("Create DomiSMP datasource");
         return databaseConnectionBeanCreator.getDataSource();
     }
 
@@ -63,7 +63,7 @@ public class SMPDatabaseConfig {
     @Bean(name = "smpEntityManagerFactory")
     @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
     public LocalContainerEntityManagerFactoryBean smpEntityManagerFactory(@Qualifier("smpDataSource") DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) {
-        LOG.info("Create DomiSMP EntityManagerFactory");
+        LOG.trace("Create DomiSMP EntityManagerFactory");
         return databaseConnectionBeanCreator.smpEntityManagerFactory(dataSource, jpaVendorAdapter);
     }
 
@@ -71,7 +71,7 @@ public class SMPDatabaseConfig {
     @Bean(name = "transactionManager")
     @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
     public PlatformTransactionManager smpTransactionManager(@Qualifier("smpEntityManagerFactory") EntityManagerFactory emf) {
-        LOG.info("Create DomiSMP TransactionManager");
+        LOG.trace("Create DomiSMP TransactionManager");
         return databaseConnectionBeanCreator.getSmpTransactionManager(emf);
     }
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java
index b3b1de294aa85483e28955ad4ed9ca6f2d8d5ff3..a37161aafcd2cfc07bd77bbb0a2dd2ec6b18ac6a 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -28,6 +28,7 @@ import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -42,6 +43,7 @@ import java.util.Properties;
 import static eu.europa.ec.edelivery.smp.config.enums.SMPEnvPropertyEnum.*;
 import static eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum.CLIENT_CERT_HEADER_ENABLED_DEPRECATED;
 import static eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum.EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED;
+import static eu.europa.ec.edelivery.smp.utils.PropertyUtils.printProperties;
 
 /**
  * DomiSMP environment property initialization.
@@ -101,11 +103,11 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties {
      * Initialize the default properties in to the cache for faster lookup of the default values
      */
     private void init() {
-        LOG.debug("Initialize DomiSMP environment properties");
+        LOG.info("Initialize DomiSMP environment properties");
         classPathEnvFileProperties = readProperties(CLASSPATH_PROPERTIES, true);
         if (classPathEnvFileProperties != null) {
             LOG.debug("------ Print classPathEnvFileProperties ------");
-            classPathEnvFileProperties.entrySet().stream().forEach(e -> LOG.info(e.getKey() + ":" + e.getValue()));
+            printProperties(extInitFileProperties, Level.DEBUG);
         }
 
         // get init file property
@@ -113,29 +115,34 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties {
         extInitFileProperties = readProperties(extInitPropFilePath, false);
         if (extInitFileProperties != null) {
             LOG.debug("------ Print classPathEnvFileProperties ------");
-            extInitFileProperties.entrySet().stream().forEach(e -> LOG.info(e.getKey() + ":" + e.getValue()));
+            printProperties(extInitFileProperties, Level.DEBUG);
         }
 
         // get init file property
         extSpringBootFileProperties = readProperties(INIT_SPRINGBOOT_PROPERTIES, false);
         if (extSpringBootFileProperties != null) {
             LOG.debug("------ Print extSpringBootFileProperties ------");
-            extSpringBootFileProperties.entrySet().stream().forEach(e -> LOG.info(e.getKey() + ":" + e.getValue()));
+            printProperties(extInitFileProperties, Level.DEBUG);
         }
 
         String extAppFilePath = getEnvPropertyValue(CONFIGURATION_FILE);
         extEnvFileProperties = readProperties(extAppFilePath, false);
         if (extInitFileProperties != null) {
             LOG.debug("------ Print extInitFileProperties ------");
-            extEnvFileProperties.entrySet().stream().forEach(e -> LOG.info(e.getKey() + ":" + e.getValue()));
+            printProperties(extInitFileProperties, Level.DEBUG);
         }
 
 
         // update log configuration
         updateLogConfiguration(getEnvPropertyValue(LOG_FOLDER),
                 getEnvPropertyValue(LOG_CONFIGURATION_FILE));
+
+        LOG.info("DomiSMP environment properties initialized!");
+        Properties properties = getEnvProperties();
+        printProperties(properties, Level.INFO);
     }
 
+
     protected Properties readProperties(String path, boolean inClasspath) {
 
         if (inClasspath) {
@@ -336,6 +343,7 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties {
 
     /**
      * For the precaution the mode must be in development mode to enable  create ddl!
+     *
      * @return
      */
     @Override
@@ -351,9 +359,7 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties {
     }
 
 
-
-
-    public boolean isSMPStartupInDevMode(){
+    public boolean isSMPStartupInDevMode() {
         return Boolean.parseBoolean(getEnvPropertyValue(SMP_MODE_DEVELOPMENT));
     }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/enums/SMPPropertyTypeEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/enums/SMPPropertyTypeEnum.java
index 714a7bf8b71e043778c8e8db630480237c91a726..2acbeb11ffad546e504368e3aa45e71584cee6d8 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/enums/SMPPropertyTypeEnum.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/enums/SMPPropertyTypeEnum.java
@@ -25,6 +25,7 @@ package eu.europa.ec.edelivery.smp.config.enums;
  */
 public enum SMPPropertyTypeEnum {
     STRING (".{0,2000}","Property value [%s] must be less than 2000 characters!"),
+    DATETIME (".{0,2000}","Property value [%s] must be less than 2000 characters!"),
     LIST_STRING(".{0,2000}","Property [%s] is not valid LIST_STRING type!"),
     MAP_STRING(".{0,2000}","Property [%s] is not valid MAP_STRING type!"),
     INTEGER("\\d{0,12}","Property [%s] is not valid Integer!"),
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDocumentVersionEventToDocumentVersionEventROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDocumentVersionEventToDocumentVersionEventROConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e2bf586f84d4fc7722068137535e542d11b112a
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDocumentVersionEventToDocumentVersionEventROConverter.java
@@ -0,0 +1,44 @@
+package eu.europa.ec.edelivery.smp.conversion;
+
+
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.doc.DBDocumentVersionEvent;
+import eu.europa.ec.edelivery.smp.data.ui.DocumentVersionEventRO;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import org.apache.commons.beanutils.BeanUtils;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Converter for domain DAO entity {@link DBDomain} to
+ * enriched webservice object {@link eu.europa.ec.edelivery.smp.data.ui.DomainPublicRO}.
+ *
+ * @author Joze Rihtarsic
+ * @since 5.1
+ */
+@Component
+public class DBDocumentVersionEventToDocumentVersionEventROConverter
+        implements Converter<DBDocumentVersionEvent, DocumentVersionEventRO> {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBDocumentVersionEventToDocumentVersionEventROConverter.class);
+
+    @Override
+    public DocumentVersionEventRO convert(DBDocumentVersionEvent source) {
+
+        if (source == null) {
+            return null;
+        }
+        DocumentVersionEventRO target = new DocumentVersionEventRO();
+        try {
+            BeanUtils.copyProperties(target, source);
+            target.setDocumentVersionStatus(source.getStatus());
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            LOG.error("Error occurred while converting DBDomain", e);
+            return null;
+        }
+        return target;
+    }
+
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainConfToDomainPropROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainConfToDomainPropROConverter.java
index 8a7ea6735afc0965a218da54d1e8ee2e64103537..63c2d9b852d7b045595d4f53f2c1d7cada9034ef 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainConfToDomainPropROConverter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainConfToDomainPropROConverter.java
@@ -41,6 +41,7 @@ public class DBDomainConfToDomainPropROConverter implements Converter<DBDomainCo
         target.setProperty(source.getProperty());
         target.setSystemDefault(source.isUseSystemDefault());
         target.setValue(source.getValue());
+        target.setDesc(source.getDescription());
         target.setValuePattern(enumType.getValuePattern().pattern());
         target.setType(enumType.getPropertyType().name());
         target.setSystemDefaultValue(configurationService.getDefaultDomainConfiguration(enumType));
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainPublicROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainPublicROConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..39300e6667903614f39ace2f5a99972fab9f1710
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBDomainToDomainPublicROConverter.java
@@ -0,0 +1,57 @@
+/*-
+ * #START_LICENSE#
+ * smp-server-library
+ * %%
+ * Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
+ * %%
+ * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
+ * versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ *
+ * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
+ * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ * #END_LICENSE#
+ */
+package eu.europa.ec.edelivery.smp.conversion;
+
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.ui.DomainPublicRO;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import org.apache.commons.beanutils.BeanUtils;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * Converter for domain DAO entity {@link DBDomain} to enriched webservice object {@link eu.europa.ec.edelivery.smp.data.ui.DomainPublicRO}.
+ *
+ * @author Joze Rihtarsic
+ * @since 5.1
+ */
+@Component
+public class DBDomainToDomainPublicROConverter implements Converter<DBDomain, DomainPublicRO> {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBDomainToDomainPublicROConverter.class);
+
+    @Override
+    public DomainPublicRO convert(DBDomain source) {
+
+        if (source == null) {
+            return null;
+        }
+        DomainPublicRO target = new DomainPublicRO();
+        try {
+            BeanUtils.copyProperties(target, source);
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            LOG.error("Error occurred while converting DBDomain", e);
+            return null;
+        }
+        return target;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceToResourceROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceToResourceROConverter.java
index 637dca1fd6469b3ad6a5ccb18194139361fdfbdc..89fcbe88b3659a74f7fa60ca4c7e20cee846cc5c 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceToResourceROConverter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceToResourceROConverter.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -18,6 +18,7 @@
  */
 package eu.europa.ec.edelivery.smp.conversion;
 
+import eu.europa.ec.edelivery.smp.data.dao.ResourceMemberDao;
 import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
 import eu.europa.ec.edelivery.smp.data.ui.ResourceRO;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
@@ -37,6 +38,12 @@ import java.lang.reflect.InvocationTargetException;
 public class DBResourceToResourceROConverter implements Converter<DBResource, ResourceRO> {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBResourceToResourceROConverter.class);
 
+    private final ResourceMemberDao resourceMemberDao;
+
+    public DBResourceToResourceROConverter(ResourceMemberDao resourceMemberDao) {
+        this.resourceMemberDao = resourceMemberDao;
+    }
+
     @Override
     public ResourceRO convert(DBResource source) {
 
@@ -46,6 +53,12 @@ public class DBResourceToResourceROConverter implements Converter<DBResource, Re
             target.setResourceTypeIdentifier(source.getDomainResourceDef().getResourceDef().getIdentifier());
             target.setResourceId(SessionSecurityUtils.encryptedEntityId(source.getId()));
             target.setReviewEnabled(source.isReviewEnabled());
+            Long userId = SessionSecurityUtils.getSessionUserId();
+            if (userId != null && source.getId() != null) {
+                target.setHasCurrentUserReviewPermission(
+                        resourceMemberDao.isUserResourceMemberWithReviewPermission(userId, source.getId()));
+            }
+
         } catch (IllegalAccessException | InvocationTargetException e) {
             LOG.error("Error occurred while converting DBResource", e);
             return null;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBReviewDocumentVersionToReviewDocumentVersionROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBReviewDocumentVersionToReviewDocumentVersionROConverter.java
index 2698e529d5bb26e92fe82d89ffc0fc737062b33f..b648018219c88f85fa58a8a8ec888c24c25c088d 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBReviewDocumentVersionToReviewDocumentVersionROConverter.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBReviewDocumentVersionToReviewDocumentVersionROConverter.java
@@ -18,7 +18,7 @@
  */
 package eu.europa.ec.edelivery.smp.conversion;
 
-import eu.europa.ec.edelivery.smp.data.model.doc.DBReviewDocumentVersion;
+import eu.europa.ec.edelivery.smp.data.model.doc.DBReviewDocumentVersionMapping;
 import eu.europa.ec.edelivery.smp.data.ui.ReviewDocumentVersionRO;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
@@ -37,11 +37,11 @@ import java.lang.reflect.InvocationTargetException;
  * @since 5.1
  */
 @Component
-public class DBReviewDocumentVersionToReviewDocumentVersionROConverter implements Converter<DBReviewDocumentVersion, ReviewDocumentVersionRO> {
+public class DBReviewDocumentVersionToReviewDocumentVersionROConverter implements Converter<DBReviewDocumentVersionMapping, ReviewDocumentVersionRO> {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBReviewDocumentVersionToReviewDocumentVersionROConverter.class);
 
     @Override
-    public ReviewDocumentVersionRO convert(DBReviewDocumentVersion source) {
+    public ReviewDocumentVersionRO convert(DBReviewDocumentVersionMapping source) {
 
         ReviewDocumentVersionRO target = new ReviewDocumentVersionRO();
         try {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBSearchReferenceDocumentVersionToSearchReferenceDocumentROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBSearchReferenceDocumentVersionToSearchReferenceDocumentROConverter.java
new file mode 100644
index 0000000000000000000000000000000000000000..e221c37a29ea6337b415b6cbff6b6ebb71e3c7a7
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBSearchReferenceDocumentVersionToSearchReferenceDocumentROConverter.java
@@ -0,0 +1,98 @@
+/*-
+ * #START_LICENSE#
+ * smp-server-library
+ * %%
+ * Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
+ * %%
+ * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
+ * versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ *
+ * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
+ * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ * #END_LICENSE#
+ */
+package eu.europa.ec.edelivery.smp.conversion;
+
+import eu.europa.ec.edelivery.smp.data.enums.DocumentReferenceType;
+import eu.europa.ec.edelivery.smp.data.model.doc.DBSearchReferenceDocumentMapping;
+import eu.europa.ec.edelivery.smp.data.ui.SearchReferenceDocumentRO;
+import eu.europa.ec.edelivery.smp.identifiers.Identifier;
+import eu.europa.ec.edelivery.smp.logging.SMPLogger;
+import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.services.IdentifierService;
+import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.InvocationTargetException;
+
+
+/**
+ * Converter for DBReviewDocumentVersion to ReviewDocumentVersionRO
+ *
+ * @author Joze RIHTARSIC
+ * @since 5.1
+ */
+@Component
+public class DBSearchReferenceDocumentVersionToSearchReferenceDocumentROConverter implements Converter<DBSearchReferenceDocumentMapping, SearchReferenceDocumentRO> {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBSearchReferenceDocumentVersionToSearchReferenceDocumentROConverter.class);
+
+    IdentifierService identifierService;
+    private static final String URL_SEPARATOR = "/";
+
+    public DBSearchReferenceDocumentVersionToSearchReferenceDocumentROConverter(IdentifierService identifierService) {
+        this.identifierService = identifierService;
+    }
+
+    @Override
+    public SearchReferenceDocumentRO convert(DBSearchReferenceDocumentMapping source) {
+
+        SearchReferenceDocumentRO target = new SearchReferenceDocumentRO();
+        try {
+            BeanUtils.copyProperties(target, source);
+            target.setDocumentId(SessionSecurityUtils.encryptedEntityId(source.getDocumentId()));
+            target.setResourceId(SessionSecurityUtils.encryptedEntityId(source.getResourceId()));
+            target.setSubresourceId(SessionSecurityUtils.encryptedEntityId(source.getSubresourceId()));
+            target.setReferenceUrl(getReferenceUrl(source));
+
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            LOG.error("Error occurred while converting DBResource", e);
+            return null;
+        }
+        return target;
+    }
+
+
+    /**
+     * Method returns  partial reference URL for given reference document
+     * @param source reference document
+     * @return partial reference URL
+     */
+    private String getReferenceUrl(DBSearchReferenceDocumentMapping source) {
+
+        String ctx = URL_SEPARATOR + getUrlPart(source.getDomainCode()) + getUrlPart(source.getResourceDefUrlSegment());
+        ctx += identifierService.urlEncodedFormatParticipant(source.getDomainCode(), new Identifier(source.getResourceValue(), source.getResourceScheme()));
+
+        if (source.getReferenceType() == DocumentReferenceType.SUBRESOURCE) {
+            ctx += URL_SEPARATOR + getUrlPart(source.getSubresourceDefUrlSegment())
+                    + identifierService.urlEncodedFormatDocument(source.getDomainCode(), new Identifier(source.getSubresourceValue(), source.getSubresourceScheme()));
+        }
+        return ctx;
+    }
+
+    /**
+     * Method returns URL part for given value
+     * @param value the part of URL
+     * @return trimmed value which ends with URL_SEPARATOR or empty string
+     */
+    private String getUrlPart(String value) {
+        return StringUtils.isBlank(value) ? "" : value + URL_SEPARATOR;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java
index e2c723a32cd900ff42bd61d4b40e87a0bc38e6fd..a053da1be4f7108b9b5be713e52ac2c77462cf81 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/BaseDao.java
@@ -40,6 +40,9 @@ import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
 
+import static org.apache.commons.lang3.StringUtils.lowerCase;
+import static org.apache.commons.lang3.StringUtils.trimToNull;
+
 /**
  * Database abstract resource file. Class implements all common methods for all resources.
  *
@@ -379,5 +382,30 @@ public abstract class BaseDao<E extends BaseEntity> {
         return memEManager.createQuery(cqCount).getSingleResult();
     }
 
+    /**
+     * Method sets pagination to the query
+     * @param query query to set pagination
+     * @param iPage page number
+     * @param iPageSize page size
+     */
+    protected void setPaginationParametersToQuery(TypedQuery<?> query, int iPage, int iPageSize) {
+        if (iPageSize > -1 && iPage > -1) {
+            query.setFirstResult(iPage * iPageSize);
+        }
+        if (iPageSize > 0) {
+            query.setMaxResults(iPageSize);
+        }
+    }
+
+    /**
+     * Method prepare like parameter for query. If parameter is blank, than null is returned, otherwise
+     * parameter is converted to lower case and % is added to the beginning and end of the parameter.
+     * @param param parameter to prepare
+     * @return prepared parameter
+     */
+    protected String likeParam(String param) {
+        return trimToNull(param) == null? null: "%" + lowerCase(param) + "%";
+    }
+
 
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/CredentialDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/CredentialDao.java
index befbf646294f12b4279584a046543eea687bfca7..5be507b2cbf82497fae40bc7682a8156c856ec05 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/CredentialDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/CredentialDao.java
@@ -21,7 +21,7 @@ package eu.europa.ec.edelivery.smp.data.dao;
 
 import eu.europa.ec.edelivery.smp.data.enums.CredentialTargetType;
 import eu.europa.ec.edelivery.smp.data.enums.CredentialType;
-import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidation;
+import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidationMapping;
 import eu.europa.ec.edelivery.smp.data.model.user.DBCredential;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
@@ -313,9 +313,9 @@ public class CredentialDao extends BaseDao<DBCredential> {
      * @param userIds
      * @return
      */
-    public List<DBUserDeleteValidation> validateUsersForDelete(List<Long> userIds) {
-        TypedQuery<DBUserDeleteValidation> query = memEManager.createNamedQuery("DBUserDeleteValidation.validateUsersForOwnership",
-                DBUserDeleteValidation.class);
+    public List<DBUserDeleteValidationMapping> validateUsersForDelete(List<Long> userIds) {
+        TypedQuery<DBUserDeleteValidationMapping> query = memEManager.createNamedQuery("DBUserDeleteValidation.validateUsersForOwnership",
+                DBUserDeleteValidationMapping.class);
         query.setParameter("idList", userIds);
         return query.getResultList();
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java
index 41367b1bd43adb803e6f980ad390ff4be390acbf..10606a7ded34b0c8c0de8b4548aceed4d67503bd 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDao.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -20,9 +20,13 @@ package eu.europa.ec.edelivery.smp.data.dao;
 
 
 import eu.europa.ec.edelivery.smp.data.enums.DocumentVersionStatusType;
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
+import eu.europa.ec.edelivery.smp.data.model.DBDomainResourceDef;
 import eu.europa.ec.edelivery.smp.data.model.doc.*;
 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.springframework.stereotype.Repository;
 
 import javax.persistence.NoResultException;
@@ -42,6 +46,8 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @Repository
 public class DocumentDao extends BaseDao<DBDocument> {
 
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DocumentDao.class);
+
     /**
      * Method returns the document for the resource
      *
@@ -94,6 +100,19 @@ public class DocumentDao extends BaseDao<DBDocument> {
         }
     }
 
+    public Optional<DBDocumentVersion> getCurrentDocumentVersionForDocument(DBDocument document) {
+
+        try {
+            // expected is only one domain,
+            TypedQuery<DBDocumentVersion> query = memEManager.createNamedQuery(QUERY_DOCUMENT_VERSION_CURRENT_FOR_DOCUMENT, DBDocumentVersion.class);
+            query.setParameter(PARAM_DOCUMENT_ID, document.getId());
+            return Optional.of(query.getSingleResult());
+        } catch (NoResultException e) {
+            return Optional.empty();
+        }
+    }
+
+
     public Optional<DBDocumentVersion> getCurrentDocumentVersionForSubresource(DBSubresource subresource) {
 
         try {
@@ -137,14 +156,170 @@ public class DocumentDao extends BaseDao<DBDocument> {
         return query.getResultList();
     }
 
-    public List<DBReviewDocumentVersion> getDocumentReviewListForUser(Long dbUserId) {
-        TypedQuery<DBReviewDocumentVersion> query = memEManager.createNamedQuery(
-                QUERY_DOCUMENT_VERSION_UNDER_REVIEW_FOR_USER, DBReviewDocumentVersion.class);
+    /**
+     * Method creates query for searching users review tasks
+     *
+     * @param resultClass class of the result, can be DBResource or Long
+     * @param dbUserId    target user id
+     * @param <T>         type of the result
+     * @return the typed query
+     */
+    private <T> TypedQuery<T> createDocumentReviewListForUserQuery(Class<T> resultClass, Long dbUserId) {
+
+        String queryName = resultClass == Long.class ? QUERY_DOCUMENT_VERSION_UNDER_REVIEW_FOR_USER_COUNT : QUERY_DOCUMENT_VERSION_UNDER_REVIEW_FOR_USER;
+        LOG.debug("Creating query [{}] for class [{}] and user id [{}]", queryName, resultClass, dbUserId);
+        TypedQuery<T> query = memEManager.createNamedQuery(queryName, resultClass);
         query.setParameter(PARAM_USER_ID, dbUserId);
         query.setParameter(PARAM_PERMISSION_CAN_REVIEW, true);
         query.setParameter(PARAM_REVIEW_ENABLED, true);
         query.setParameter(PARAM_STATUS, DocumentVersionStatusType.UNDER_REVIEW.name());
+        return query;
+    }
+
+    public List<DBReviewDocumentVersionMapping> getDocumentReviewListForUser(Long dbUserId, int iPage, int iPageSize) {
+        TypedQuery<DBReviewDocumentVersionMapping> query = createDocumentReviewListForUserQuery(DBReviewDocumentVersionMapping.class, dbUserId);
+        setPaginationParametersToQuery(query, iPage, iPageSize);
         return query.getResultList();
 
     }
+
+    /**
+     * Method returns count of document versions under review for the user
+     *
+     * @param dbUserId
+     * @return
+     */
+    public long getDocumentReviewListForUserCount(Long dbUserId) {
+        TypedQuery<Long> query = createDocumentReviewListForUserQuery(Long.class, dbUserId);
+
+        return query.getSingleResult().longValue();
+    }
+
+    /**
+     * Method creates query for searching reference document resources
+     *
+     * @param resultClass              class of the result, can be DBResource or Long
+     * @param dbTargetResource         target resource
+     * @param searchResourceIdentifier if of the search resource
+     * @param searchResourceScheme     scheme of the search resource
+     * @param <T>                      type of the result
+     * @return the typed query
+     */
+    private <T> TypedQuery<T> createSearchReferenceDocumentResourcesQuery(Class<T> resultClass, DBResource dbTargetResource, String searchResourceIdentifier, String searchResourceScheme) {
+
+        String queryName = resultClass == Long.class ? QUERY_SEARCH_DOCUMENT_REFERENCES_COUNT : QUERY_SEARCH_DOCUMENT_REFERENCES;
+        LOG.debug("Create search query [{}] for resource references class [{}] with resource [{}] - [{}]", queryName, resultClass,
+                searchResourceIdentifier, searchResourceScheme);
+
+        DBDomainResourceDef dbDomainResourceDef = dbTargetResource.getDomainResourceDef();
+        TypedQuery<T> query = memEManager.createNamedQuery(queryName, resultClass);
+        query.setParameter(PARAM_RESOURCE_DEF_ID, dbDomainResourceDef.getResourceDef().getId());
+        query.setParameter(PARAM_RESOURCE_ID, dbTargetResource.getId());
+        query.setParameter(PARAM_SHARING_ENABLED, true);
+        query.setParameter(PARAM_RESOURCE_VISIBILITY, VisibilityType.PUBLIC);
+        query.setParameter(PARAM_RESOURCE_SCHEME, likeParam(searchResourceScheme));
+        query.setParameter(PARAM_RESOURCE_IDENTIFIER, likeParam(searchResourceIdentifier));
+        query.setParameter(PARAM_GROUP_ID, dbTargetResource.getGroup().getId());
+        query.setParameter(PARAM_GROUP_VISIBILITY, VisibilityType.PUBLIC);
+        query.setParameter(PARAM_DOMAIN_ID, dbDomainResourceDef.getDomain().getId());
+        query.setParameter(PARAM_DOMAIN_VISIBILITY, VisibilityType.PUBLIC);
+
+        return query;
+    }
+
+
+    private <T> TypedQuery<T> createSearchReferenceDocumentSubResourcesQuery(Class<T> resultClass,
+                                                                             DBSubresource dbTargetSubresource,
+                                                                             String searchResourceIdentifier,
+                                                                             String searchResourceScheme,
+                                                                             String searchSubresourceIdentifier,
+                                                                             String searchSubresourceScheme) {
+
+        String queryName = resultClass == Long.class ? QUERY_SEARCH_DOCUMENT_REFERENCES_FOR_SUBRESOURCES_COUNT :
+                QUERY_SEARCH_DOCUMENT_REFERENCES_FOR_SUBRESOURCES;
+        LOG.debug("Create search query [{}] for subresource references with class [{}] with resource [{}] - [{}], subresource [{}] - [{}]",
+                queryName, resultClass,
+                searchResourceIdentifier,
+                searchResourceScheme,
+                searchResourceIdentifier,
+                searchResourceScheme);
+
+        DBResource dbTargetResource = dbTargetSubresource.getResource();
+        DBDomainResourceDef dbDomainResourceDef = dbTargetResource.getDomainResourceDef();
+
+        TypedQuery<T> query = memEManager.createNamedQuery(queryName, resultClass);
+        query.setParameter(PARAM_SUBRESOURCE_DEF_ID, dbTargetSubresource.getSubresourceDef().getId());
+        query.setParameter(PARAM_SUBRESOURCE_ID, dbTargetSubresource.getId());
+        query.setParameter(PARAM_SHARING_ENABLED, true);
+        query.setParameter(PARAM_RESOURCE_VISIBILITY, VisibilityType.PUBLIC);
+        query.setParameter(PARAM_GROUP_VISIBILITY, VisibilityType.PUBLIC);
+        query.setParameter(PARAM_GROUP_ID, dbTargetResource.getGroup().getId());
+        query.setParameter(PARAM_DOMAIN_VISIBILITY, VisibilityType.PUBLIC);
+        query.setParameter(PARAM_DOMAIN_ID, dbDomainResourceDef.getDomain().getId());
+        query.setParameter(PARAM_RESOURCE_SCHEME, likeParam(searchResourceScheme));
+        query.setParameter(PARAM_RESOURCE_IDENTIFIER, likeParam(searchResourceIdentifier));
+        query.setParameter(PARAM_SUBRESOURCE_SCHEME, likeParam(searchSubresourceScheme));
+        query.setParameter(PARAM_SUBRESOURCE_IDENTIFIER, likeParam(searchSubresourceIdentifier));
+
+        return query;
+    }
+
+
+    /**
+     * Method returns list of all possible reference document resources for the target resource with pagination.
+     * The target resource defines the domain and the resource definition type of the reference document.
+     *
+     * @param dbTargetResource         target resource
+     * @param searchResourceIdentifier identifier of the search resource
+     * @param searchResourceScheme     scheme of the search resource
+     * @param iPage                    page number
+     * @param iPageSize                page size
+     * @return list of reference document resources
+     */
+    public List<DBSearchReferenceDocumentMapping> getSearchReferenceDocumentResources(DBResource dbTargetResource,
+                                                                                      String searchResourceIdentifier,
+                                                                                      String searchResourceScheme, int iPage, int iPageSize) {
+        TypedQuery<DBSearchReferenceDocumentMapping> query = createSearchReferenceDocumentResourcesQuery(DBSearchReferenceDocumentMapping.class,
+                dbTargetResource,
+                searchResourceIdentifier,
+                searchResourceScheme);
+        setPaginationParametersToQuery(query, iPage, iPageSize);
+        return query.getResultList();
+    }
+
+    public long getSearchReferenceDocumentResourcesCount(DBResource dbTargetResource, String searchResourceIdentifier, String searchResourceScheme) {
+        TypedQuery<Long> query = createSearchReferenceDocumentResourcesQuery(Long.class, dbTargetResource, searchResourceIdentifier, searchResourceScheme);
+        return query.getSingleResult();
+    }
+
+    public List<DBSearchReferenceDocumentMapping> getSearchReferenceDocumentSubresource(DBSubresource dbTargetSubresource,
+                                                                                        String searchResourceIdentifier,
+                                                                                        String searchResourceScheme,
+                                                                                        String searchSubresourceIdentifier,
+                                                                                        String searchSubresourceScheme,
+                                                                                        int iPage, int iPageSize) {
+        TypedQuery<DBSearchReferenceDocumentMapping> query = createSearchReferenceDocumentSubResourcesQuery(DBSearchReferenceDocumentMapping.class,
+                dbTargetSubresource,
+                searchResourceIdentifier,
+                searchResourceScheme,
+                searchSubresourceIdentifier,
+                searchSubresourceScheme);
+        setPaginationParametersToQuery(query, iPage, iPageSize);
+        return query.getResultList();
+    }
+
+    public long getSearchReferenceDocumentSubresourceCount(DBSubresource dbTargetSubresource,
+                                                           String searchResourceIdentifier,
+                                                           String searchResourceScheme,
+                                                           String searchSubresourceIdentifier,
+                                                           String searchSubresourceScheme) {
+        TypedQuery<Long> query = createSearchReferenceDocumentSubResourcesQuery(Long.class,
+                dbTargetSubresource,
+                searchResourceIdentifier,
+                searchResourceScheme,
+                searchSubresourceIdentifier,
+                searchSubresourceScheme);
+
+        return query.getSingleResult();
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
index c312c1b63c6c149be2b8a2b294af4be7f23e7e82..972d001d954d4af71d768d220d6e318664f81351 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
@@ -20,7 +20,9 @@
 package eu.europa.ec.edelivery.smp.data.dao;
 
 import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.apache.commons.lang3.StringUtils;
@@ -78,17 +80,6 @@ public class DomainDao extends BaseDao<DBDomain> {
         return query.getResultList();
     }
 
-    /**
-     * Returns domain code records from smp_domain table.
-     *
-     * @return the list of domain codes from smp_domain table
-     */
-    public List<String> getAllDomainCodes() {
-        TypedQuery<String> query = memEManager.createNamedQuery(QUERY_DOMAIN_ALL_CODES, String.class);
-        return query.getResultList();
-    }
-
-
     public Optional<DBDomain> getFirstDomain() {
         TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_ALL, DBDomain.class);
         query.setMaxResults(1);
@@ -197,8 +188,9 @@ public class DomainDao extends BaseDao<DBDomain> {
      * Check if domain for domain code exists. If not SMPRuntimeException with DOMAIN_NOT_EXISTS is thrown.
      * If code is null or blank - then null is returned.
      *
-     * @param domainCode
-     * @return
+     * @param domainCode  - domain code to be validated
+     * @return DBDomain - domain if exists
+     * @throws SMPRuntimeException if domain does not exist
      */
     public DBDomain validateDomainCode(String domainCode) {
         DBDomain domain = null;
@@ -228,4 +220,36 @@ public class DomainDao extends BaseDao<DBDomain> {
         }
         return false;
     }
+
+    /**
+     * Method returns all public domains with all domains where user is direct or indirect member.
+     * and have some resources assigned. See the EDELIVERY-13793
+     * If user is null then only public domains are returned.
+     *
+     * @param user - user to search for
+     *             if null only public domains are returned
+     * @return list of domains
+     * @Param page - page number
+     * @Param pageSize - page size
+     */
+    public List<DBDomain> getAllDomainsForUser(DBUser user, int page, int pageSize) {
+        TypedQuery<DBDomain> query = createAllDomainsForUserQuery(DBDomain.class, user);
+        setPaginationParametersToQuery(query, page, pageSize);
+        return query.getResultList();
+    }
+
+    public long getAllDomainsForUserCount(DBUser user) {
+        TypedQuery<Long> query = createAllDomainsForUserQuery(Long.class, user);
+        return query.getSingleResult();
+    }
+
+    private <T> TypedQuery<T> createAllDomainsForUserQuery(Class<T> resultClass, DBUser user) {
+        String queryName = resultClass == Long.class ? QUERY_DOMAIN_FOR_USER_COUNT :
+                QUERY_DOMAIN_FOR_USER;
+        LOG.debug("Create search query [{}] for all users domain", queryName);
+        TypedQuery<T> query = memEManager.createNamedQuery(queryName, resultClass);
+        query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null);
+        query.setParameter(PARAM_DOMAIN_VISIBILITY, VisibilityType.PUBLIC);
+        return query;
+    }
 }
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 3906c65d563f0aa85a655082f999baed9da59e2f..7fb88e793b2061e34a9e1ad68de2d6696f804b8b 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
@@ -39,6 +39,8 @@ public class QueryNames {
 
     public static final String QUERY_DOMAIN_BY_USER_ROLES_COUNT = "DBDomain.getByUserAndRolesCount";
     public static final String QUERY_DOMAIN_BY_USER_ROLES = "DBDomain.getByUserAndRoles";
+    public static final String QUERY_DOMAIN_FOR_USER = "DBDomain.getAllDomainsForUser";
+    public static final String QUERY_DOMAIN_FOR_USER_COUNT = "DBDomain.getAllDomainsForUserCount";
 
     public static final String QUERY_DOMAIN_BY_USER_GROUP_ROLES_COUNT = "DBDomain.getByUserAndGroupRolesCount";
     public static final String QUERY_DOMAIN_BY_USER_GROUP_ROLES = "DBDomain.getByUserAndGroupRoles";
@@ -95,8 +97,8 @@ public class QueryNames {
     public static final String QUERY_RESOURCE_MEMBER_BY_USER_RESOURCE_COUNT = "DBResourceMember.getByUserAndResourceCount";
     public static final String QUERY_RESOURCE_MEMBER_BY_USER_DOMAIN_RESOURCE_COUNT = "DBResourceMember.getByUserAndDomainResourceCount";
     public static final String QUERY_RESOURCE_MEMBER_BY_USER_DOMAIN_RESOURCE_ROLE_COUNT = "DBResourceMember.getByUserAndDomainRoleResourceCount";
-    public static final String QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_ROLE_COUNT = "DBResourceMember.getByUserAndGroupsResourcesAndRoleCount";
-    public static final String QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_COUNT = "DBResourceMember.getByUserAndGroupsResourcesCount";
+    public static final String QUERY_RESOURCE_MEMBER_BY_USER_GROUPS_RESOURCES_ROLE_COUNT = "DBResourceMember.getByUserAndGroupsResourcesAndRoleCount";
+    public static final String QUERY_RESOURCE_MEMBER_BY_USER_GROUPS_RESOURCES_COUNT = "DBResourceMember.getByUserAndGroupsResourcesCount";
     public static final String QUERY_RESOURCE_MEMBERS_COUNT = "DBResourceMember.getByResourceCount";
     public static final String QUERY_RESOURCE_MEMBERS_FILTER_COUNT = "DBResourceMember.getByResourceFilterCount";
     public static final String QUERY_RESOURCE_MEMBERS = "DBResourceMember.getByResource";
@@ -119,19 +121,25 @@ public class QueryNames {
     public static final String QUERY_RESOURCE_DEF_URL_SEGMENT = "DBResourceDef.getResourceDefByURLSegment";
     public static final String QUERY_RESOURCE_DEF_BY_IDENTIFIER = "DBResourceDef.getResourceDefByIdentifier";
     public static final String QUERY_RESOURCE_DEF_BY_IDENTIFIER_EXTENSION = "DBExtResourceDef.getByIdentifierExtension";
+    public static final String QUERY_RESOURCE_DEF_FOR_USER = "DBResourceDef.getAllForUser";
+    public static final String QUERY_RESOURCE_DEF_FOR_USER_COUNT = "DBResourceDef.getAllForUserCount";
 
     public static final String QUERY_DOCUMENT_FOR_RESOURCE = "DBDocument.getForResource";
-    public static final String QUERY_DOCUMENT_BY_RESOURCE_DEF_SHARING = "DBDocument.getForResourceDEfAndSharingEnabled";
+    public static final String QUERY_SEARCH_DOCUMENT_REFERENCES = "DBDocument.getDocumentReferences";
+    public static final String QUERY_SEARCH_DOCUMENT_REFERENCES_COUNT = "DBDocument.getDocumentReferencesCount";
     public static final String QUERY_DOCUMENT_FOR_SUBRESOURCE = "DBDocument.getForSubresource";
-    public static final String QUERY_DOCUMENT_BY_SUBRESOURCE_DEF_SHARING = "DBDocument.getForSubresourceDEfAndSharingEnabled";
-
+    public static final String QUERY_SEARCH_DOCUMENT_REFERENCES_FOR_SUBRESOURCES = "DBDocument.getDocumentReferencesForSubresources";
+    public static final String QUERY_SEARCH_DOCUMENT_REFERENCES_FOR_SUBRESOURCES_COUNT = "DBDocument.getDocumentReferencesForSubresourcesCount";
     public static final String QUERY_DOCUMENT_VERSION_CURRENT_FOR_RESOURCE = "DBDocumentVersion.forCurrentForResource";
     public static final String QUERY_DOCUMENT_VERSION_LIST_FOR_RESOURCE = "DBDocumentVersion.getAllForResource";
 
 
+    public static final String QUERY_DOCUMENT_VERSION_CURRENT_FOR_DOCUMENT = "DBDocumentVersion.forCurrentForDocument";
+
     public static final String QUERY_DOCUMENT_VERSION_CURRENT_FOR_SUBRESOURCE = "DBDocumentVersion.forCurrentForSubresource";
     public static final String QUERY_DOCUMENT_VERSION_LIST_FOR_SUBRESOURCE = "DBDocumentVersion.getAllForSubresource";
     public static final String QUERY_DOCUMENT_VERSION_UNDER_REVIEW_FOR_USER = "DBDocumentVersion.getAllReviewTasksForUser";
+    public static final String QUERY_DOCUMENT_VERSION_UNDER_REVIEW_FOR_USER_COUNT = "DBDocumentVersion.getAllReviewTasksForUserCount";
 
     public static final String QUERY_GROUP_MEMBER_ALL = "DBGroupMember.getAll";
     public static final String QUERY_GROUP_MEMBER_BY_USER_GROUPS_COUNT = "DBGroupMember.getByUserAndGroupsCount";
@@ -172,6 +180,7 @@ public class QueryNames {
 
     public static final String PARAM_RESOURCE_ID = "resource_id";
     public static final String PARAM_RESOURCE_IDS = "resource_ids";
+    public static final String PARAM_RESOURCE_VISIBILITY = "resource_visibility";
     public static final String PARAM_SUBRESOURCE_ID = "subresource_id";
     // resource identifier value
     public static final String PARAM_RESOURCE_IDENTIFIER = "resource_identifier";
@@ -183,12 +192,12 @@ public class QueryNames {
     public static final String PARAM_RESOURCE_FILTER = "resource_filter";
     public static final String PARAM_RESOURCE_DEF_ID = "resource_def_id";
     public static final String PARAM_RESOURCE_DEF_IDENTIFIER = "resource_def_identifier";
-    public static final String PARAM_SUBRESOURCE_DEF_ID = "subresource_def_id";
-
     public static final String PARAM_REVIEW_ENABLED = "review_enabled";
 
+    public static final String PARAM_SUBRESOURCE_DEF_ID = "subresource_def_id";
     public static final String PARAM_SUBRESOURCE_DEF_IDENTIFIER = "subresource_def_identifier";
     public static final String PARAM_DOMAIN_ID = "domain_id";
+    public static final String PARAM_DOMAIN_VISIBILITY = "domain_visibility";
     public static final String PARAM_DOMAIN_CODE = "domain_code";
     public static final String PARAM_DOMAIN_SML_SMP_ID = "sml_smp_id";
 
@@ -199,6 +208,7 @@ public class QueryNames {
     public static final String PARAM_SHARING_ENABLED = "sharing_enabled";
     public static final String PARAM_STATUS = "status";
 
+    public static final String PARAM_GROUP_VISIBILITY = "group_visibility";
     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/dao/ResourceDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
index 93b25d5d66497fdd9cba54d4bb66bf05a981927a..ec87357c12858a960a1df8e149ae2ad15b511472 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDao.java
@@ -155,8 +155,8 @@ public class ResourceDao extends BaseDao<DBResource> {
             query.setMaxResults(iPageSize);
         }
         query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null);
-        query.setParameter(PARAM_RESOURCE_SCHEME, StringUtils.isBlank(schema) ? null : StringUtils.wrapIfMissing(schema, "%"));
-        query.setParameter(PARAM_RESOURCE_IDENTIFIER, StringUtils.isBlank(identifier) ? null : StringUtils.wrapIfMissing(identifier, "%"));
+        query.setParameter(PARAM_RESOURCE_SCHEME, getNormalizedLikeParameter(schema));
+        query.setParameter(PARAM_RESOURCE_IDENTIFIER, getNormalizedLikeParameter(identifier));
         query.setParameter(PARAM_DOMAIN_CODE, StringUtils.defaultIfBlank(domainCode, null));
         query.setParameter(PARAM_DOCUMENT_TYPE, StringUtils.defaultIfBlank(documentType, null));
         List<Tuple> resultList = query.getResultList();
@@ -170,6 +170,19 @@ public class ResourceDao extends BaseDao<DBResource> {
         }).collect(Collectors.toList());
     }
 
+    /**
+     * Method 'Escapes' the \ characters of the value and wraps it with % if the value is not empty.
+     * @param value value to be "Normalized" and wrapped
+     * @return escaped value
+     */
+    private  String getNormalizedLikeParameter(String value) {
+        if (StringUtils.isBlank(value)){
+            return null;
+        }
+        String escapedValue = value.replace("\\", "\\\\");
+        return StringUtils.wrapIfMissing(escapedValue, "%");
+    }
+
     public Long getPublicResourcesSearchCount(DBUser user, String schema, String identifier, String domainCode, String documentType) {
         LOG.debug("Get resources count for user [{}], search scheme [{}] and search value [{}]", user, schema, identifier);
         TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_ALL_FOR_USER_COUNT, Long.class);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDefDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDefDao.java
index 79f14e03792d7a19dc99c2b3edbca1828773dff4..f31898f58c937b23259bd5c87beb83dcd2cf885c 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDefDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDefDao.java
@@ -19,10 +19,13 @@
 
 package eu.europa.ec.edelivery.smp.data.dao;
 
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.ext.DBExtension;
 import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef;
+import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
+import org.slf4j.Logger;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.NoResultException;
@@ -41,7 +44,7 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INTERNAL_ERROR;
  */
 @Repository
 public class ResourceDefDao extends BaseDao<DBResourceDef> {
-
+    private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(ResourceDefDao.class);
 
     /**
      * Returns DBResourceDef records from the database.
@@ -133,4 +136,35 @@ public class ResourceDefDao extends BaseDao<DBResourceDef> {
             throw new SMPRuntimeException(CONFIGURATION_ERROR, "More than one resource type is registered for the name!");
         }
     }
+
+    /**
+     * Method returns all public domains with all domains where user is direct or indirect member.
+     * If user is null then only public domains are returned.
+     *
+     * @param user - user to search for
+     *             if null only public domains are returned
+     * @return list of domains
+     * @Param page - page number
+     * @Param pageSize - page size
+     */
+    public List<DBResourceDef> getAllResourceDefsForUser(DBUser user, int page, int pageSize) {
+        TypedQuery<DBResourceDef> query = createAllResourceDefForUserQuery(DBResourceDef.class, user);
+        setPaginationParametersToQuery(query, page, pageSize);
+        return query.getResultList();
+    }
+
+    public long getAllResourceDefsForUserCount(DBUser user) {
+        TypedQuery<Long> query = createAllResourceDefForUserQuery(Long.class, user);
+        return query.getSingleResult();
+    }
+
+    private <T> TypedQuery<T> createAllResourceDefForUserQuery(Class<T> resultClass, DBUser user) {
+        String queryName = resultClass == Long.class ? QUERY_RESOURCE_DEF_FOR_USER_COUNT :
+                QUERY_RESOURCE_DEF_FOR_USER;
+        LOG.debug("Create search query [{}] for user [{}]", queryName, user);
+        TypedQuery<T> query = memEManager.createNamedQuery(queryName, resultClass);
+        query.setParameter(PARAM_USER_ID, user != null ? user.getId() : null);
+        query.setParameter(PARAM_DOMAIN_VISIBILITY, VisibilityType.PUBLIC);
+        return query;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java
index 2107b59a4093387370d1154618cb3aa76db203c7..d1456bc756968d2e98a4aaf0d7b04ae1224278d1 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java
@@ -31,7 +31,9 @@ import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.TypedQuery;
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 
@@ -112,22 +114,34 @@ public class ResourceMemberDao extends BaseDao<DBResourceMember> {
         }
     }
 
-    public boolean isUserAnyGroupResourceMemberWithRole(Long userId, Long groupId, MembershipRoleType roleType) {
-        LOG.debug("User [{}], group [{}], Role [{}]", userId, groupId, roleType);
-        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_ROLE_COUNT,
+    public boolean isUserAnyGroupsResourceMemberWithRole(Long userId, List<Long> groupId, MembershipRoleType roleType) {
+        LOG.debug("User [{}], groups [{}], Role [{}]", userId, groupId, roleType);
+        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_MEMBER_BY_USER_GROUPS_RESOURCES_ROLE_COUNT,
                 Long.class);
         query.setParameter(PARAM_USER_ID, userId);
-        query.setParameter(PARAM_GROUP_ID, groupId);
+        query.setParameter(PARAM_GROUP_IDS, groupId);
         query.setParameter(PARAM_MEMBERSHIP_ROLE, roleType);
         return query.getSingleResult() > 0;
     }
 
+    public boolean isUserAnyGroupResourceMemberWithRole(Long userId, Long groupId, MembershipRoleType roleType) {
+        LOG.debug("User [{}], group [{}], Role [{}]", userId, groupId, roleType);
+        return isUserAnyGroupsResourceMemberWithRole(userId, Collections.singletonList(groupId), roleType);
+    }
+
     public boolean isUserAnyGroupResourceMember(DBUser user, DBGroup group) {
         LOG.debug("User [{}], group [{}]", user, group);
-        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_COUNT,
+        return isUserAnyGroupsResourceMember(user, Collections.singletonList(group));
+    }
+
+    public boolean isUserAnyGroupsResourceMember(DBUser user, List<DBGroup> groups) {
+        String list = groups.stream().map(DBGroup::getId).map(String::valueOf).reduce((a, b) -> a + "," + b).orElse("");
+        LOG.debug("User [{}], group [{}]", user, list);
+        List<Long> groupIds = groups.stream().map(DBGroup::getId).collect(Collectors.toList());
+        TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCE_MEMBER_BY_USER_GROUPS_RESOURCES_COUNT,
                 Long.class);
         query.setParameter(PARAM_USER_ID, user.getId());
-        query.setParameter(PARAM_GROUP_ID, group.getId());
+        query.setParameter(PARAM_GROUP_IDS, groupIds);
         return query.getSingleResult() > 0;
     }
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
index 72b0ecb81a2e7afec480067b7c6c58b5077bb57a..f5750d8f9cf75c28a8cdc7cd9b5acf9b8427ac65 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/UserDao.java
@@ -21,7 +21,7 @@ package eu.europa.ec.edelivery.smp.data.dao;
 
 import eu.europa.ec.edelivery.smp.data.enums.CredentialTargetType;
 import eu.europa.ec.edelivery.smp.data.enums.CredentialType;
-import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidation;
+import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidationMapping;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
@@ -210,9 +210,9 @@ public class UserDao extends BaseDao<DBUser> {
      * @param userIds
      * @return
      */
-    public List<DBUserDeleteValidation> validateUsersForDelete(List<Long> userIds) {
-        TypedQuery<DBUserDeleteValidation> query = memEManager.createNamedQuery("DBUserDeleteValidation.validateUsersForOwnership",
-                DBUserDeleteValidation.class);
+    public List<DBUserDeleteValidationMapping> validateUsersForDelete(List<Long> userIds) {
+        TypedQuery<DBUserDeleteValidationMapping> query = memEManager.createNamedQuery("DBUserDeleteValidation.validateUsersForOwnership",
+                DBUserDeleteValidationMapping.class);
         query.setParameter("idList", userIds);
         return query.getResultList();
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentReferenceType.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentReferenceType.java
new file mode 100644
index 0000000000000000000000000000000000000000..957bb58889463fa3360a554b6caf61ad949c0ea9
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentReferenceType.java
@@ -0,0 +1,14 @@
+package eu.europa.ec.edelivery.smp.data.enums;
+
+/**
+ * Document reference type enum.
+ * Enum is used to define the type of returned search reference document. It can be
+ * resource or subresource.
+ *
+ * @author Joze Rihtarsic
+ * @since 5.1
+ */
+public enum DocumentReferenceType {
+    RESOURCE,
+    SUBRESOURCE
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionEventType.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionEventType.java
index 7dc30b30b45f1a2e10dd5c7dec0c0a86acb922a4..84031c27c9a06a5570fc1626e07174e3abd25500 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionEventType.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionEventType.java
@@ -15,5 +15,6 @@ public enum DocumentVersionEventType {
     RETIRE,
     APPROVE,
     REJECT,
-    ERROR
+    ERROR,
+    SETTINGS_CHANGE,
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionStatusType.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionStatusType.java
index a19af0f902b29d62a39b5e0254d7c2e192a760c0..ee055a3ae563754f54b1629e93f9dbacfa7ba035 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionStatusType.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/enums/DocumentVersionStatusType.java
@@ -1,6 +1,11 @@
 package eu.europa.ec.edelivery.smp.data.enums;
 
-
+/**
+ * The enum Document version status type.
+ *
+ * @since 5.1
+ * @author Joze RIHTARSIC
+ */
 public enum DocumentVersionStatusType {
     DRAFT,
     PUBLISHED,
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java
index 21ffc472a4ad03f2210173d2e2ec86765f34ce26..bd1c32123bb77c4eab3afaa41d3bca55b3e41881 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/CommonColumnsLengths.java
@@ -21,8 +21,12 @@ package eu.europa.ec.edelivery.smp.data.model;
 
 /**
  * Created by gutowpa on 01/02/2017.
+ *
+ * @since 3.0
+ * @author  Pawel GUTOWSKI
  */
 public class CommonColumnsLengths {
+
     public static final int MAX_DOMAIN_CODE_LENGTH = 256;
     public static final int MAX_FREE_TEXT_LENGTH = 4000;
     public static final int MAX_MEDIUM_TEXT_LENGTH = 1024;
@@ -36,13 +40,14 @@ public class CommonColumnsLengths {
     public static final int MAX_SML_SUBDOMAIN_LENGTH = 256;
     public static final int MAX_SML_SMP_ID_LENGTH = 256;
     public static final int MAX_USER_ROLE_LENGTH = 256;
-    public static final int MAX_TEXT_LENGTH_256 = 512;
+    public static final int MAX_TEXT_LENGTH_256 = 256;
     public static final int MAX_TEXT_LENGTH_512 = 512;
     public static final int MAX_TEXT_LENGTH_128 = 128;
     public static final int MAX_TEXT_LENGTH_64 = 64;
 
-
-
-
-
+    /**
+     * Private constructor to prevent instantiation.
+     */
+    private CommonColumnsLengths() {
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
index 5bce6d7f38317030077a0fccba379a8ee992249d..674a3721bbbc1f516a7854090581291c1c4b0f56 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java
@@ -72,15 +72,33 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
         " JOIN DBResource r ON  g.id = r.group.id " +
         " JOIN DBResourceMember rm ON r.id = rm.resource.id " +
         " WHERE rm.role in (:membership_roles) and rm.user.id= :user_id")
-
-
 @NamedQuery(name = QUERY_DOMAIN_BY_USER_RESOURCE_ROLES, query = "SELECT distinct d FROM DBDomain d " +
         " JOIN DBGroup g ON d.id = g.domain.id " +
         " JOIN DBResource r ON  g.id = r.group.id " +
         " JOIN DBResourceMember rm ON r.id = rm.resource.id " +
         " WHERE rm.role in (:membership_roles) and rm.user.id= :user_id")
 
-@org.hibernate.annotations.Table(appliesTo = "SMP_DOMAIN", comment = "SMP can handle multiple domains. This table contains domain specific data")
+@NamedQuery(name = QUERY_DOMAIN_FOR_USER, query = "SELECT distinct d FROM DBDomain d " +
+        " JOIN DBGroup g ON d.id = g.domain.id " +
+        " JOIN DBResource r ON  g.id = r.group.id " +
+        " WHERE d.visibility = :domain_visibility " +
+        "   or (:user_id IS NOT NULL " +
+        "         AND  (" +
+        "               (select count(dm.id) FROM  DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = d.id) > 0 " +
+        "            OR (select count(gm.id) FROM  DBGroupMember gm where gm.user.id = :user_id and gm.group.id = g.id) > 0 " +
+        "            OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.id = r.id) > 0) " +
+        "   ) " )
+@NamedQuery(name = QUERY_DOMAIN_FOR_USER_COUNT, query = "SELECT distinct COUNT( distinct d.id) FROM DBDomain d " +
+        " JOIN DBGroup g ON d.id = g.domain.id " +
+        " JOIN DBResource r ON  g.id = r.group.id " +
+        " WHERE d.visibility = :domain_visibility " +
+        "   or (:user_id IS NOT NULL " +
+        "         AND  (" +
+        "               (select count(dm.id) FROM  DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = d.id) > 0 " +
+        "            OR (select count(gm.id) FROM  DBGroupMember gm where gm.user.id = :user_id and gm.group.id = g.id) > 0 " +
+        "            OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.id = r.id) > 0) " +
+        "   ) " )
+        @org.hibernate.annotations.Table(appliesTo = "SMP_DOMAIN", comment = "SMP can handle multiple domains. This table contains domain specific data")
 public class DBDomain extends BaseEntity {
 
     private static final long serialVersionUID = 1008583888835630004L;
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 933e20e77ccc313ea5633672853e8ed6a9552fd4..279918f3952f1920814bb6042d40a737158699d9 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
@@ -143,11 +143,16 @@ public class DBGroup extends BaseEntity {
         return this.groupMembers;
     }
 
+    /**
+     * Print the group information. To prevent lazy initialization which throws error
+     * for detached entities, the domain prints just a domain id.
+     * @return string information of the group
+     */
     @Override
     public String toString() {
         return "DBGroup{" +
                 "id=" + id +
-                ", domain=" + domain +
+                ", domain=" + (domain != null ? domain.getId() : null) +
                 ", groupName='" + groupName + '\'' +
                 '}';
     }
@@ -155,14 +160,11 @@ public class DBGroup extends BaseEntity {
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-
         if (o == null || getClass() != o.getClass()) return false;
-
         DBGroup group = (DBGroup) o;
-
         return new EqualsBuilder().appendSuper(super.equals(o))
                 .append(id, group.id)
-                .append(domain, group.domain)
+                .append(domain.id, group.domain.id) // to prevent lazy initialization
                 .append(groupName, group.groupName)
                 .append(groupDescription, group.groupDescription)
                 .append(visibility, group.visibility)
@@ -173,7 +175,7 @@ public class DBGroup extends BaseEntity {
     public int hashCode() {
         return new HashCodeBuilder(17, 37)
                 .appendSuper(super.hashCode()).append(id)
-                .append(domain)
+                .append(domain != null ? domain.getId() : null) // to prevent lazy initialization
                 .append(groupName)
                 .toHashCode();
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserDeleteValidation.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserDeleteValidationMapping.java
similarity index 89%
rename from smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserDeleteValidation.java
rename to smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserDeleteValidationMapping.java
index 34515c06fc582bb98bb7a781eea9dbde7feaccaa..bc75441126e4f967fc59903ec855a96e6b562c62 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserDeleteValidation.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBUserDeleteValidationMapping.java
@@ -19,17 +19,17 @@
 package eu.europa.ec.edelivery.smp.data.model;
 
 
-public class DBUserDeleteValidation {
+public class DBUserDeleteValidationMapping {
 
     Long id;
     String username;
     String certificateId;
     Integer count;
 
-    public DBUserDeleteValidation() {
+    public DBUserDeleteValidationMapping() {
     }
 
-    public DBUserDeleteValidation(Long id, String username, String certificateId, Integer count) {
+    public DBUserDeleteValidationMapping(Long id, String username, String certificateId, Integer count) {
         this.id = id;
         this.username = username;
         this.certificateId = certificateId;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java
index 9456463925e90f56e6aba2e52071701c130bf3b4..62244f48d24460ac1c1daada29af0357cc6623a1 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocument.java
@@ -47,16 +47,99 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @Table(name = "SMP_DOCUMENT")
 @org.hibernate.annotations.Table(appliesTo = "SMP_DOCUMENT", comment = "SMP document entity for resources and subresources")
 
-        @NamedQuery(name = QUERY_DOCUMENT_FOR_RESOURCE, query = "SELECT d FROM DBResource r JOIN r.document d WHERE r.id =:resource_id")
-        @NamedQuery(name = QUERY_DOCUMENT_BY_RESOURCE_DEF_SHARING, query = "SELECT d FROM DBResource r " +
-                "INNER JOIN r.document d " +
-                "INNER JOIN r.domainResourceDef.resourceDef rdef " +
-                "  WHERE rdef.identifier =:resource_def_identifier and d.sharingEnabled =:sharing_enabled")
-        @NamedQuery(name = QUERY_DOCUMENT_FOR_SUBRESOURCE, query = "SELECT d FROM DBSubresource  sr JOIN sr.document d WHERE sr.id =:subresource_id")
-        @NamedQuery(name = QUERY_DOCUMENT_BY_SUBRESOURCE_DEF_SHARING, query = "SELECT d FROM DBSubresource rs " +
-                "INNER JOIN rs.document d " +
-                "INNER JOIN rs.subresourceDef rdef " +
-                "  WHERE rdef.identifier =:subresource_def_identifier and d.sharingEnabled =:sharing_enabled")
+@NamedQuery(name = QUERY_DOCUMENT_FOR_RESOURCE, query = "SELECT d FROM DBResource r JOIN r.document d WHERE r.id =:resource_id")
+@NamedQuery(name = QUERY_SEARCH_DOCUMENT_REFERENCES, query =
+        "SELECT new eu.europa.ec.edelivery.smp.data.model.doc.DBSearchReferenceDocumentMapping(" +
+        "   d.id, " +
+        "   r.id, " +
+        "   d.name, " +
+        "   r.identifierValue, " +
+        "   r.identifierScheme, " +
+        "   dom.domainCode," +
+        "   rdef.urlSegment)" +
+        " FROM DBResource r " +
+        " INNER JOIN r.document d " +
+        " INNER JOIN r.group gr" +
+        " INNER JOIN r.domainResourceDef drd" +
+        " INNER JOIN drd.domain dom" +
+        " INNER JOIN drd.resourceDef rdef " +
+        "  WHERE rdef.id =:resource_def_id " +
+        "   AND r.id !=:resource_id " +
+        "   AND d.sharingEnabled =:sharing_enabled " +
+        "   AND r.visibility =:resource_visibility " +
+        "   AND (gr.visibility=:group_visibility OR gr.id =:group_id)" +
+        "   AND (dom.visibility=:domain_visibility OR dom.id =:domain_id)"  +
+        "   AND (:resource_identifier IS NULL OR lower(r.identifierValue) like (:resource_identifier))" +
+        "   AND (:resource_scheme IS NULL OR lower(r.identifierScheme) like (:resource_scheme))")
+@NamedQuery(name = QUERY_SEARCH_DOCUMENT_REFERENCES_COUNT, query = "SELECT count(d.id) " +
+        " FROM DBResource r " +
+        " INNER JOIN r.document d " +
+        " INNER JOIN r.group gr" +
+        " INNER JOIN r.domainResourceDef drd" +
+        " INNER JOIN drd.domain dom" +
+        " INNER JOIN drd.resourceDef rdef " +
+        "  WHERE rdef.id =:resource_def_id " +
+        "   AND r.id !=:resource_id " +
+        "   AND d.sharingEnabled =:sharing_enabled " +
+        "   AND r.visibility =:resource_visibility " +
+        "   AND (gr.visibility=:group_visibility OR gr.id =:group_id)" +
+        "   AND (dom.visibility=:domain_visibility OR dom.id =:domain_id)"  +
+        "   AND (:resource_identifier IS NULL OR lower(r.identifierValue) like (:resource_identifier))" +
+        "   AND (:resource_scheme IS NULL OR lower(r.identifierScheme) like (:resource_scheme))")
+@NamedQuery(name = QUERY_DOCUMENT_FOR_SUBRESOURCE, query = "SELECT d FROM DBSubresource  sr JOIN sr.document d WHERE sr.id =:subresource_id")
+@NamedQuery(name = QUERY_SEARCH_DOCUMENT_REFERENCES_FOR_SUBRESOURCES, query =
+        "SELECT new eu.europa.ec.edelivery.smp.data.model.doc.DBSearchReferenceDocumentMapping(" +
+                "   d.id, " +
+                "   r.id, " +
+                "   sr.id, " +
+                "   d.name, " +
+                "   r.identifierValue, " +
+                "   r.identifierScheme, " +
+                "   sr.identifierValue, " +
+                "   sr.identifierScheme, " +
+                "   dom.domainCode," +
+                "   rdef.urlSegment," +
+                "   srdef.urlSegment)" +
+                " FROM DBSubresource sr " +
+                " INNER JOIN sr.subresourceDef srdef " +
+                " INNER JOIN sr.document d " +
+                " INNER JOIN sr.resource r " +
+                " INNER JOIN r.domainResourceDef drd" +
+                " INNER JOIN r.group gr" +
+                " INNER JOIN drd.domain dom" +
+                " INNER JOIN drd.resourceDef rdef " +
+                "  WHERE " +
+                "   srdef.id =:subresource_def_id " +
+                "   AND sr.id !=:subresource_id " +
+                "   AND d.sharingEnabled =:sharing_enabled " +
+                "   AND r.visibility =:resource_visibility " +
+                "   AND (gr.visibility=:group_visibility OR gr.id =:group_id)" +
+                "   AND (dom.visibility=:domain_visibility OR dom.id =:domain_id)"  +
+                "   AND (:resource_identifier IS NULL OR lower(r.identifierValue) like (:resource_identifier))" +
+                "   AND (:resource_scheme IS NULL OR lower(r.identifierScheme) like (:resource_scheme))" +
+                "   AND (:subresource_identifier IS NULL OR lower(sr.identifierValue) like (:subresource_identifier))" +
+                "   AND (:subresource_scheme IS NULL OR lower(sr.identifierScheme) like (:subresource_scheme))")
+@NamedQuery(name = QUERY_SEARCH_DOCUMENT_REFERENCES_FOR_SUBRESOURCES_COUNT, query = "SELECT count(d.id) " +
+        " FROM DBSubresource sr " +
+        " INNER JOIN sr.subresourceDef srdef " +
+        " INNER JOIN sr.document d " +
+        " INNER JOIN sr.resource r " +
+        " INNER JOIN r.domainResourceDef drd" +
+        " INNER JOIN r.group gr" +
+        " INNER JOIN drd.domain dom" +
+        " INNER JOIN drd.resourceDef rdef " +
+        "  WHERE " +
+        "   srdef.id =:subresource_def_id " +
+        "   AND sr.id !=:subresource_id " +
+        "   AND d.sharingEnabled =:sharing_enabled " +
+        "   AND r.visibility =:resource_visibility " +
+        "   AND (gr.visibility=:group_visibility OR gr.id =:group_id)" +
+        "   AND (dom.visibility=:domain_visibility OR dom.id =:domain_id)"  +
+        "   AND (:resource_identifier IS NULL OR lower(r.identifierValue) like (:resource_identifier))" +
+        "   AND (:resource_scheme IS NULL OR lower(r.identifierScheme) like (:resource_scheme))" +
+        "   AND (:subresource_identifier IS NULL OR lower(sr.identifierValue) like (:subresource_identifier))" +
+        "   AND (:subresource_scheme IS NULL OR lower(sr.identifierScheme) like (:subresource_scheme))")
+
 public class DBDocument extends BaseEntity {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DBDocument.class);
     @Id
@@ -70,6 +153,9 @@ public class DBDocument extends BaseEntity {
     @JoinColumn(name = "FK_REF_DOCUMENT_ID")
     private DBDocument referenceDocument;
 
+    @Column(name = "REF_DOCUMENT_URL", length = CommonColumnsLengths.MAX_MEDIUM_TEXT_LENGTH)
+    private String referenceDocumentUrl;
+
     // list of all version with the latest version first!
     @OneToMany(
             mappedBy = "document",
@@ -118,6 +204,14 @@ public class DBDocument extends BaseEntity {
         this.referenceDocument = referenceDocument;
     }
 
+    public String getReferenceDocumentUrl() {
+        return referenceDocumentUrl;
+    }
+
+    public void setReferenceDocumentUrl(String referenceDocumentAddress) {
+        this.referenceDocumentUrl = referenceDocumentAddress;
+    }
+
     /**
      * Returns document version ordered from the latest version to first version
      *
@@ -142,11 +236,15 @@ public class DBDocument extends BaseEntity {
         if (documentVersion.getId() != null && getDocumentVersions().contains(documentVersion)) {
             LOG.info("Document version [{}] already exists on document [{}]", documentVersion, this);
             return documentVersion;
-       }
+        }
 
         documentVersion.setVersion(getNextVersionIndex());
         documentVersion.setDocument(this);
-        setCurrentVersion(documentVersion.getVersion());
+
+        if (getCurrentVersion() <= 0 || documentVersion.getStatus() == DocumentVersionStatusType.PUBLISHED) {
+            setCurrentVersion(documentVersion.getVersion());
+        }
+
         // ADD TO THE LIST to the first position (latest version)
         getDocumentVersions().add(0, documentVersion);
         return documentVersion;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersion.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersion.java
index 293fff778281519481adc9fda72d0cc2c4ea3e60..e9ea417d9687f9a85fbca880ef4aae2a3e46118e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersion.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersion.java
@@ -50,7 +50,13 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 
         })
 @org.hibernate.annotations.Table(appliesTo = "SMP_DOCUMENT_VERSION", comment = "Document content for the document version.")
-@NamedQuery(name = QUERY_DOCUMENT_VERSION_CURRENT_FOR_RESOURCE, query = "SELECT dv FROM DBResource r join r.document d join d.documentVersions dv " +
+@NamedQuery(name = QUERY_DOCUMENT_VERSION_CURRENT_FOR_DOCUMENT, query = "SELECT dv FROM DBDocument d " +
+        "  join d.documentVersions dv " +
+        " WHERE dv.version = d.currentVersion " +
+        " AND d.id= :document_id ")
+@NamedQuery(name = QUERY_DOCUMENT_VERSION_CURRENT_FOR_RESOURCE, query = "SELECT dv FROM DBResource r " +
+        "  join r.document d " +
+        "  join d.documentVersions dv " +
         " WHERE dv.version = d.currentVersion " +
         " AND r.id= :resource_id ")
 @NamedQuery(name = QUERY_DOCUMENT_VERSION_LIST_FOR_RESOURCE, query = "SELECT dv FROM DBResource r join r.document.documentVersions dv " +
@@ -90,12 +96,27 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
                 "    AND r.REVIEW_ENABLED = :review_enabled" +
                 "    AND rmu.FK_USER_ID = :user_id" +
                 "    AND rmu.PERMISSION_REVIEW = :permission_can_review",
-
         resultSetMapping = "DBReviewDocumentVersionsMapping")
 
+@NamedNativeQuery(name = QUERY_DOCUMENT_VERSION_UNDER_REVIEW_FOR_USER_COUNT,
+        query = "SELECT " +
+                "    count(dv.ID) AS CNT" +
+                " FROM " +
+                "    SMP_DOCUMENT_VERSION dv" +
+                "    INNER JOIN SMP_DOCUMENT d ON dv.FK_DOCUMENT_ID = d.ID" +
+                "    LEFT JOIN SMP_SUBRESOURCE sr ON d.ID = sr.FK_DOCUMENT_ID" +
+                "    LEFT JOIN SMP_RESOURCE r ON d.ID = r.FK_DOCUMENT_ID OR r.ID = sr.FK_RESOURCE_ID" +
+                "    INNER JOIN SMP_RESOURCE_MEMBER rmu ON r.ID = rmu.FK_RESOURCE_ID" +
+                " WHERE " +
+                "    dv.STATUS = :status" +
+                "    AND r.REVIEW_ENABLED = :review_enabled" +
+                "    AND rmu.FK_USER_ID = :user_id" +
+                "    AND rmu.PERMISSION_REVIEW = :permission_can_review",
+        resultSetMapping = "DBReviewDocumentVersionsCountMapping")
+
 @SqlResultSetMapping(name = "DBReviewDocumentVersionsMapping",
         classes = {
-                @ConstructorResult(targetClass = DBReviewDocumentVersion.class,
+                @ConstructorResult(targetClass = DBReviewDocumentVersionMapping.class,
                         columns = {
                                 @ColumnResult(name = "ID", type = Long.class),
                                 @ColumnResult(name = "DOCUMENT_ID", type = Long.class),
@@ -111,6 +132,14 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
                                 @ColumnResult(name = "LAST_UPDATED_ON", type = OffsetDateTime.class),
                         })
         })
+
+@SqlResultSetMapping(name = "DBReviewDocumentVersionsCountMapping",
+        classes = {
+                @ConstructorResult(targetClass = Long.class,
+                        columns = {
+                                @ColumnResult(name = "CNT", type = Long.class),
+                        })
+        })
 public class DBDocumentVersion extends BaseEntity {
     @Id
     @GeneratedValue(strategy = GenerationType.AUTO, generator = "SMP_DOCUMENT_VERSION_SEQ")
@@ -201,15 +230,30 @@ public class DBDocumentVersion extends BaseEntity {
     }
 
     /**
-     * Add new document version event. Beause of the order of the events,
+     * Add new document version event. Because of the order of the events,
      * the new event is added to the beginning of the list.*
      *
      * @param event event to be added
      * @return added event
      */
     public DBDocumentVersionEvent addNewDocumentVersionEvent(DBDocumentVersionEvent event) {
+        return addNewDocumentVersionEvent(event, true);
+    }
+
+    /**
+     * Add new document version event.
+     *
+     * @param event    event to be added
+     * @param addFirst if true event is added to the beginning of the list
+     * @return added event
+     */
+    public DBDocumentVersionEvent addNewDocumentVersionEvent(DBDocumentVersionEvent event, boolean addFirst) {
         event.setDocumentVersion(this);
-        getDocumentVersionEvents().add(0, event);
+        if (addFirst) {
+            getDocumentVersionEvents().add(0, event);
+        } else {
+            getDocumentVersionEvents().add(event);
+        }
         return event;
     }
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersionEvent.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersionEvent.java
index 54fa7c8dc2274b4164451c4c68b4e19067fdd3b6..1592cba7b57f940e92661e6ddfb33a21b356d738 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersionEvent.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBDocumentVersionEvent.java
@@ -20,6 +20,7 @@ package eu.europa.ec.edelivery.smp.data.model.doc;
 
 import eu.europa.ec.edelivery.smp.data.dao.utils.ColumnDescription;
 import eu.europa.ec.edelivery.smp.data.enums.DocumentVersionEventType;
+import eu.europa.ec.edelivery.smp.data.enums.DocumentVersionStatusType;
 import eu.europa.ec.edelivery.smp.data.enums.EventSourceType;
 import eu.europa.ec.edelivery.smp.data.model.BaseEntity;
 import eu.europa.ec.edelivery.smp.data.model.CommonColumnsLengths;
@@ -61,6 +62,11 @@ public class DBDocumentVersionEvent extends BaseEntity {
     @ColumnDescription(comment = "Document version event type")
     private DocumentVersionEventType eventType = DocumentVersionEventType.CREATE;
 
+    @Enumerated(EnumType.STRING)
+    @Column(name = "EVENT_STATUS", nullable = false)
+    @ColumnDescription(comment = "Document version event type")
+    private DocumentVersionStatusType status = DocumentVersionStatusType.DRAFT;
+
     @Column(name = "EVENT_ON")
     @ColumnDescription(comment = "Date time of the event")
     private OffsetDateTime eventOn;
@@ -127,6 +133,14 @@ public class DBDocumentVersionEvent extends BaseEntity {
         this.eventSourceType = eventSourceType;
     }
 
+    public DocumentVersionStatusType getStatus() {
+        return status;
+    }
+
+    public void setStatus(DocumentVersionStatusType status) {
+        this.status = status;
+    }
+
     public String getDetails() {
         return details;
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBReviewDocumentVersion.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBReviewDocumentVersionMapping.java
similarity index 96%
rename from smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBReviewDocumentVersion.java
rename to smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBReviewDocumentVersionMapping.java
index f34bfdcb66adf7f4aaef2eaaab1fe5d26a03998d..85fa9fb96fb7d8e204ce5b2aaaa48609f4836012 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBReviewDocumentVersion.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBReviewDocumentVersionMapping.java
@@ -13,7 +13,7 @@ import java.time.OffsetDateTime;
  * @author Joze RIHARSIC
  * @since 5.1
  */
-public class DBReviewDocumentVersion implements Serializable {
+public class DBReviewDocumentVersionMapping {
 
     private Long documentId;
     private Long documentVersionId;
@@ -28,10 +28,10 @@ public class DBReviewDocumentVersion implements Serializable {
     private String target;
     private OffsetDateTime lastUpdatedOn;
 
-    public DBReviewDocumentVersion() {
+    public DBReviewDocumentVersionMapping() {
     }
 
-    public DBReviewDocumentVersion(
+    public DBReviewDocumentVersionMapping(
             Long id,
             Long documentId,
             Long resourceId,
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBSearchReferenceDocumentMapping.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBSearchReferenceDocumentMapping.java
new file mode 100644
index 0000000000000000000000000000000000000000..28dda174bcd9fcda9fca04cca22cae1f67498e9f
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/doc/DBSearchReferenceDocumentMapping.java
@@ -0,0 +1,180 @@
+package eu.europa.ec.edelivery.smp.data.model.doc;
+
+import eu.europa.ec.edelivery.smp.data.enums.DocumentReferenceType;
+
+import java.util.StringJoiner;
+
+/**
+ * Class represents the document reference mapping. It is used with query
+ * to get all reference documents for target resource
+ */
+public class DBSearchReferenceDocumentMapping {
+
+    private Long documentId;
+    private Long resourceId;
+    private Long subresourceId;
+
+    private DocumentReferenceType referenceType;
+
+    private String documentName;
+    private String resourceValue;
+    private String resourceScheme;
+    private String subresourceValue;
+    private String subresourceScheme;
+
+    private String domainCode;
+    private String resourceDefUrlSegment;
+    private String subresourceDefUrlSegment;
+
+    public DBSearchReferenceDocumentMapping(Long documentId,
+                                            Long resourceId,
+                                            String documentName,
+                                            String resourceValue,
+                                            String resourceScheme,
+                                            String domainCode,
+                                            String resourceDefUrlSegment) {
+        referenceType = DocumentReferenceType.RESOURCE;
+        this.documentId = documentId;
+        this.resourceId = resourceId;
+        this.documentName = documentName;
+        this.resourceValue = resourceValue;
+        this.resourceScheme = resourceScheme;
+        this.domainCode = domainCode;
+        this.resourceDefUrlSegment = resourceDefUrlSegment;
+    }
+
+    public DBSearchReferenceDocumentMapping(Long documentId,
+                                            Long resourceId,
+                                            Long subresourceId,
+                                            String documentName,
+                                            String resourceValue,
+                                            String resourceScheme,
+                                            String subresourceValue,
+                                            String subresourceScheme,
+                                            String domainCode,
+                                            String resourceDefUrlSegment,
+                                            String subresourceDefUrlSegment) {
+        referenceType = DocumentReferenceType.SUBRESOURCE;
+        this.documentId = documentId;
+        this.resourceId = resourceId;
+        this.subresourceId = subresourceId;
+        this.documentName = documentName;
+        this.resourceValue = resourceValue;
+        this.resourceScheme = resourceScheme;
+        this.subresourceValue = subresourceValue;
+        this.subresourceScheme = subresourceScheme;
+        this.domainCode = domainCode;
+        this.resourceDefUrlSegment = resourceDefUrlSegment;
+        this.subresourceDefUrlSegment = subresourceDefUrlSegment;
+    }
+
+
+    public Long getDocumentId() {
+        return documentId;
+    }
+
+    public void setDocumentId(Long documentId) {
+        this.documentId = documentId;
+    }
+
+    public Long getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(Long resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public Long getSubresourceId() {
+        return subresourceId;
+    }
+
+    public void setSubresourceId(Long subresourceId) {
+        this.subresourceId = subresourceId;
+    }
+
+    public DocumentReferenceType getReferenceType() {
+        return referenceType;
+    }
+
+    public void setReferenceType(DocumentReferenceType referenceType) {
+        this.referenceType = referenceType;
+    }
+
+    public String getDocumentName() {
+        return documentName;
+    }
+
+    public void setDocumentName(String documentName) {
+        this.documentName = documentName;
+    }
+
+    public String getResourceValue() {
+        return resourceValue;
+    }
+
+    public void setResourceValue(String resourceValue) {
+        this.resourceValue = resourceValue;
+    }
+
+    public String getResourceScheme() {
+        return resourceScheme;
+    }
+
+    public void setResourceScheme(String resourceScheme) {
+        this.resourceScheme = resourceScheme;
+    }
+
+    public String getSubresourceValue() {
+        return subresourceValue;
+    }
+
+    public void setSubresourceValue(String subresourceValue) {
+        this.subresourceValue = subresourceValue;
+    }
+
+    public String getSubresourceScheme() {
+        return subresourceScheme;
+    }
+
+    public void setSubresourceScheme(String subresourceScheme) {
+        this.subresourceScheme = subresourceScheme;
+    }
+
+    public String getDomainCode() {
+        return domainCode;
+    }
+
+    public void setDomainCode(String domainCode) {
+        this.domainCode = domainCode;
+    }
+
+    public String getResourceDefUrlSegment() {
+        return resourceDefUrlSegment;
+    }
+
+    public void setResourceDefUrlSegment(String resourceDefUrlSegment) {
+        this.resourceDefUrlSegment = resourceDefUrlSegment;
+    }
+
+    public String getSubresourceDefUrlSegment() {
+        return subresourceDefUrlSegment;
+    }
+
+    public void setSubresourceDefUrlSegment(String subresourceDefUrlSegment) {
+        this.subresourceDefUrlSegment = subresourceDefUrlSegment;
+    }
+
+    @Override
+    public String toString() {
+        return new StringJoiner(", ", DBSearchReferenceDocumentMapping.class.getSimpleName() + "[", "]")
+                .add("documentId=" + documentId)
+                .add("resourceId=" + resourceId)
+                .add("subresourceId=" + subresourceId)
+                .add("resourceValue='" + resourceValue + "'")
+                .add("resourceScheme='" + resourceScheme + "'")
+                .add("subresourceValue='" + subresourceValue + "'")
+                .add("subresourceScheme='" + subresourceScheme + "'")
+                .toString();
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBExtension.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBExtension.java
index ab596200a43af59104856f1ad70b281590d8ae3f..1d0bf09decf5f0096247008152d1597b20623d32 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBExtension.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBExtension.java
@@ -68,7 +68,7 @@ public class DBExtension extends BaseEntity {
     @Column(name = "DESCRIPTION", length = CommonColumnsLengths.MAX_TEXT_LENGTH_512 )
     private String description;
 
-    @Column(name = "IMPLEMENTATION_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_256 )
+    @Column(name = "IMPLEMENTATION_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_512 )
     private String implementationName;
 
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBResourceDef.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBResourceDef.java
index 74fa363fb7827b9ac7f5b603c685dd6f0996772f..20ad5bfe7a0c3e0c95361171c594532d2b6efb9e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBResourceDef.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBResourceDef.java
@@ -51,6 +51,30 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @NamedQuery(name = QUERY_RESOURCE_DEF_BY_DOMAIN, query = "SELECT d FROM DBResourceDef d JOIN d.domainResourceDefs dr where dr.domain.id = :domain_id order by d.id asc")
 @NamedQuery(name = QUERY_RESOURCE_DEF_URL_SEGMENT, query = "SELECT d FROM DBResourceDef d WHERE d.urlSegment = :url_segment")
 @NamedQuery(name = QUERY_RESOURCE_DEF_BY_IDENTIFIER, query = "SELECT d FROM DBResourceDef d WHERE d.identifier = :identifier")
+@NamedQuery(name = QUERY_RESOURCE_DEF_FOR_USER, query = "SELECT distinct rd FROM DBResourceDef rd " +
+        " JOIN DBDomainResourceDef drd ON drd.resourceDef.id = rd.id " +
+        " JOIN DBDomain d ON d.id = drd.domain.id " +
+        " JOIN DBGroup g ON d.id = g.domain.id " +
+        " JOIN DBResource r ON  g.id = r.group.id " +
+        " WHERE d.visibility = :domain_visibility " +
+        "   or (:user_id IS NOT NULL " +
+        "         AND  (" +
+        "               (select count(dm.id) FROM  DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = d.id) > 0 " +
+        "            OR (select count(gm.id) FROM  DBGroupMember gm where gm.user.id = :user_id and gm.group.id = g.id) > 0 " +
+        "            OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.id = r.id) > 0) " +
+        "   ) " )
+@NamedQuery(name = QUERY_RESOURCE_DEF_FOR_USER_COUNT, query = "SELECT count(distinct rd.id) FROM DBResourceDef rd " +
+        " JOIN DBDomainResourceDef drd ON drd.resourceDef.id = rd.id " +
+        " JOIN DBDomain d ON d.id = drd.domain.id " +
+        " JOIN DBGroup g ON d.id = g.domain.id " +
+        " JOIN DBResource r ON  g.id = r.group.id " +
+        " WHERE d.visibility = :domain_visibility " +
+        "   or (:user_id IS NOT NULL " +
+        "         AND  (" +
+        "               (select count(dm.id) FROM  DBDomainMember dm where dm.user.id = :user_id and dm.domain.id = d.id) > 0 " +
+        "            OR (select count(gm.id) FROM  DBGroupMember gm where gm.user.id = :user_id and gm.group.id = g.id) > 0 " +
+        "            OR (select count(rm.id) from DBResourceMember rm where rm.user.id = :user_id and rm.resource.id = r.id) > 0) " +
+        "   ) " )
 public class DBResourceDef extends BaseEntity {
     private static final long serialVersionUID = 1008583888835630001L;
 
@@ -77,7 +101,7 @@ public class DBResourceDef extends BaseEntity {
     @ColumnDescription(comment = "resources are published under url_segment.")
     String urlSegment;
 
-    @Column(name = "HANDLER_IMPL_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_256 )
+    @Column(name = "HANDLER_IMPL_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_512 )
     private String handlerImplementationName;
 
     @ManyToOne(fetch = FetchType.LAZY)
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBSubresourceDef.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBSubresourceDef.java
index d25ff836c28e4d33cd386fa5da7c351b51a66000..453c9e470028fb112926bf65eb4af4e33cdb7533 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBSubresourceDef.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/ext/DBSubresourceDef.java
@@ -76,7 +76,7 @@ public class DBSubresourceDef extends BaseEntity {
     @ColumnDescription(comment = "Subresources are published under url_segment. It must be unique for resource type")
     private String urlSegment;
 
-    @Column(name = "HANDLER_IMPL_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_256 )
+    @Column(name = "HANDLER_IMPL_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_512 )
     private String handlerImplementationName;
 
     @Override
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBCredential.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBCredential.java
index 41db69e01bca7763cdbe5fcad4207ac7501b0ab6..3705afc388b2889138ebdc2c7b529f13319835b0 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBCredential.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBCredential.java
@@ -23,7 +23,7 @@ import eu.europa.ec.edelivery.smp.data.enums.CredentialTargetType;
 import eu.europa.ec.edelivery.smp.data.enums.CredentialType;
 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.DBUserDeleteValidation;
+import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidationMapping;
 import org.hibernate.annotations.GenericGenerator;
 import org.hibernate.envers.Audited;
 
@@ -36,9 +36,8 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 @Audited
 @Table(name = "SMP_CREDENTIAL",
         indexes = {
-            @Index(name = "SMP_CRD_USER_NAME_TYPE_IDX", columnList = "CREDENTIAL_NAME, CREDENTIAL_TYPE, CREDENTIAL_TARGET",  unique = true),
-            @Index(name = "SMP_CRD_USER_NAME_RESET_IDX", columnList = "RESET_TOKEN, CREDENTIAL_TYPE, CREDENTIAL_TARGET",  unique = true)
-        })
+            @Index(name = "SMP_CRD_USER_NAME_TYPE_IDX", columnList = "CREDENTIAL_NAME, CREDENTIAL_TYPE, CREDENTIAL_TARGET",  unique = true)
+})
 @org.hibernate.annotations.Table(appliesTo = "SMP_CREDENTIAL", comment = "Credentials for the users")
 @NamedQuery(name = QUERY_CREDENTIAL_ALL, query = "SELECT u FROM DBCredential u")
 @NamedQuery(name = QUERY_CREDENTIALS_BY_CI_USERNAME_CREDENTIAL_TYPE_TARGET, query = "SELECT c FROM DBCredential c " +
@@ -79,7 +78,7 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
                 " GROUP BY S.ID, S.USERNAME, C.CERTIFICATE_ID")
 
 @SqlResultSetMapping(name = "DBCredentialDeleteValidationMapping", classes = {
-        @ConstructorResult(targetClass = DBUserDeleteValidation.class,
+        @ConstructorResult(targetClass = DBUserDeleteValidationMapping.class,
                 columns = {@ColumnResult(name = "id", type = Long.class),
                         @ColumnResult(name = "username", type = String.class),
                         @ColumnResult(name = "certificateId", type = String.class),
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java
index b736ac5ca4aa0c24960c96904356a4db10060555..0510cd8aee8d1abc1339e83a8dbdeb7d89e23bc1 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java
@@ -28,6 +28,8 @@ import org.hibernate.envers.Audited;
 
 import javax.persistence.*;
 
+import java.util.Objects;
+
 import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
 
 /**
@@ -50,11 +52,11 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
         " WHERE c.user.id = :user_id AND d.id = :domain_id AND c.role=:membership_role")
 @NamedQuery(name = QUERY_RESOURCE_MEMBER_BY_USER_RESOURCE, query = "SELECT c FROM DBResourceMember c " +
         " WHERE c.user.id = :user_id AND c.resource.id = :resource_id")
-@NamedQuery(name = QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_ROLE_COUNT, query = "SELECT count(c) FROM DBResourceMember c " +
-        " WHERE c.user.id = :user_id AND c.resource.group.id = :group_id AND c.role= :membership_role ")
+@NamedQuery(name = QUERY_RESOURCE_MEMBER_BY_USER_GROUPS_RESOURCES_ROLE_COUNT, query = "SELECT count(c) FROM DBResourceMember c " +
+        " WHERE c.user.id = :user_id AND c.resource.group.id IN (:group_ids) AND c.role= :membership_role ")
 
-@NamedQuery(name = QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_COUNT, query = "SELECT count(c) FROM DBResourceMember c " +
-        " WHERE c.user.id = :user_id AND c.resource.group.id = :group_id")
+@NamedQuery(name = QUERY_RESOURCE_MEMBER_BY_USER_GROUPS_RESOURCES_COUNT, query = "SELECT count(c) FROM DBResourceMember c " +
+        " WHERE c.user.id = :user_id AND c.resource.group.id IN (:group_ids)")
 
 
 @NamedQuery(name = QUERY_RESOURCE_MEMBERS_COUNT, query = "SELECT count(c) FROM DBResourceMember c " +
@@ -135,7 +137,7 @@ public class DBResourceMember extends BaseEntity {
     }
 
     public Boolean hasPermissionToReview() {
-        return hasPermissionToReview;
+        return hasPermissionToReview==null?Boolean.FALSE:hasPermissionToReview;
     }
 
     public void setHasPermissionToReview(Boolean permissionReview) {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBUser.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBUser.java
index ab0d3831b39e06eabf1a230b8c13404e02b29bb4..d000f4f430a35c8fa216b07cb35c31c7eb2fc0f9 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBUser.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBUser.java
@@ -23,7 +23,7 @@ import eu.europa.ec.edelivery.smp.data.dao.utils.ColumnDescription;
 import eu.europa.ec.edelivery.smp.data.enums.ApplicationRoleType;
 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.DBUserDeleteValidation;
+import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidationMapping;
 import org.apache.commons.lang3.StringUtils;
 import org.hibernate.annotations.GenericGenerator;
 import org.hibernate.envers.Audited;
@@ -65,7 +65,7 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
                 " WHERE S.ID IN (:idList)" +
                 " GROUP BY S.ID, S.USERNAME, C.CERTIFICATE_ID")
 @SqlResultSetMapping(name = "DBUserDeleteValidationMapping", classes = {
-        @ConstructorResult(targetClass = DBUserDeleteValidation.class,
+        @ConstructorResult(targetClass = DBUserDeleteValidationMapping.class,
                 columns = {@ColumnResult(name = "id", type = Long.class),
                         @ColumnResult(name = "username", type = String.class),
                         @ColumnResult(name = "certificateId", type = String.class),
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentMetadataRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentConfigurationRO.java
similarity index 72%
rename from smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentMetadataRO.java
rename to smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentConfigurationRO.java
index 5f4399ff94336453cc5a133450a134ff33c2880b..281ad7e72ca21dbbdcce9e0eb005f5a9f67882b3 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentMetadataRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentConfigurationRO.java
@@ -27,23 +27,19 @@ import java.util.List;
  * @author Joze RIHTARSIC
  * @since 5.1
  */
-public class DocumentMetadataRO extends BaseRO {
+public class DocumentConfigurationRO extends BaseRO {
     private static final long serialVersionUID = 9008583888835630040L;
 
     String name;
     String mimeType;
-    String referenceDocumentId;
     Integer publishedVersion;
     List<Integer> allVersions;
     Boolean sharingEnabled = Boolean.FALSE;
+    String referenceDocumentId;
+    String referenceDocumentName;
+    String referenceDocumentUrl;
+    boolean referenceDocumentAccessible = true;
 
-    public String getReferenceDocumentId() {
-        return referenceDocumentId;
-    }
-
-    public void setReferenceDocumentId(String referenceDocumentId) {
-        this.referenceDocumentId = referenceDocumentId;
-    }
 
     public String getMimeType() {
         return mimeType;
@@ -83,4 +79,37 @@ public class DocumentMetadataRO extends BaseRO {
     public void setSharingEnabled(Boolean sharingEnabled) {
         this.sharingEnabled = sharingEnabled;
     }
+
+    public String getReferenceDocumentId() {
+        return referenceDocumentId;
+    }
+
+    public void setReferenceDocumentId(String referenceDocumentId) {
+        this.referenceDocumentId = referenceDocumentId;
+    }
+
+    public String getReferenceDocumentName() {
+        return referenceDocumentName;
+    }
+
+    public void setReferenceDocumentName(String referenceDocumentName) {
+        this.referenceDocumentName = referenceDocumentName;
+    }
+
+    public String getReferenceDocumentUrl() {
+        return referenceDocumentUrl;
+    }
+
+    public void setReferenceDocumentUrl(String referenceDocumentUrl) {
+        this.referenceDocumentUrl = referenceDocumentUrl;
+    }
+
+    public boolean isReferenceDocumentAccessible() {
+        return referenceDocumentAccessible;
+    }
+
+    public void setReferenceDocumentAccessible(boolean referenceDocumentAccessible) {
+        this.referenceDocumentAccessible = referenceDocumentAccessible;
+    }
 }
+
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentRO.java
index a9f335b672b971433b918c67bf4d5f5629bd5a60..9c2b47402aab1805bfe3a13dd0cec0e751a2b9b6 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentRO.java
@@ -28,21 +28,21 @@ import java.util.List;
 
 public class DocumentRO extends BaseRO {
     private static final long serialVersionUID = 9008583888835630038L;
-    String documentId;
-    String mimeType;
-    Integer currentResourceVersion;
-    List<Integer> allVersions;
-    String name;
-    Integer payloadVersion;
-    String payload;
+    private String documentId;
+    private String mimeType;
+    private Integer currentResourceVersion;
+    private List<Integer> allVersions;
+    private String name;
+    private Integer payloadVersion;
+    private String payload;
+    private String referencePayload;
     private int payloadStatus = EntityROStatus.PERSISTED.getStatusNumber();
-    OffsetDateTime payloadCreatedOn;
-    DocumentVersionStatusType documentVersionStatus;
-
-    List<DocumentPropertyRO> properties = new ArrayList<>();
-    List<DocumentVersionEventRO> documentVersionEvents = new ArrayList<>();
-    List<DocumentVersionRO> documentVersions = new ArrayList<>();
-    DocumentMetadataRO metadata;
+    private OffsetDateTime payloadCreatedOn;
+    private DocumentVersionStatusType documentVersionStatus;
+    private List<DocumentPropertyRO> properties = new ArrayList<>();
+    private List<DocumentVersionEventRO> documentVersionEvents = new ArrayList<>();
+    private List<DocumentVersionRO> documentVersions = new ArrayList<>();
+    private DocumentConfigurationRO documentConfiguration;
 
     public String getDocumentId() {
         return documentId;
@@ -52,12 +52,12 @@ public class DocumentRO extends BaseRO {
         this.documentId = documentId;
     }
 
-    public DocumentMetadataRO getMetadata() {
-        return metadata;
+    public DocumentConfigurationRO getDocumentConfiguration() {
+        return documentConfiguration;
     }
 
-    public void setMetadata(DocumentMetadataRO metadata) {
-        this.metadata = metadata;
+    public void setDocumentConfiguration(DocumentConfigurationRO documentConfiguration) {
+        this.documentConfiguration = documentConfiguration;
     }
 
     public String getMimeType() {
@@ -95,10 +95,19 @@ public class DocumentRO extends BaseRO {
         return payloadVersion;
     }
 
+    public String getReferencePayload() {
+        return referencePayload;
+    }
+
+    public void setReferencePayload(String referencePayload) {
+        this.referencePayload = referencePayload;
+    }
+
     public void setPayloadVersion(Integer payloadVersion) {
         this.payloadVersion = payloadVersion;
     }
 
+
     public DocumentVersionStatusType getDocumentVersionStatus() {
         return documentVersionStatus;
     }
@@ -157,4 +166,5 @@ public class DocumentRO extends BaseRO {
     public void addDocumentVersionEvent(DocumentVersionEventRO event) {
         this.documentVersionEvents.add(event);
     }
+
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentVersionEventRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentVersionEventRO.java
index da9f630f73c4f35957b6e49d93901da5494efd00..3c57005fbeb227a5235c0e50de5051846450bc14 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentVersionEventRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DocumentVersionEventRO.java
@@ -2,6 +2,7 @@ package eu.europa.ec.edelivery.smp.data.ui;
 
 
 import eu.europa.ec.edelivery.smp.data.enums.DocumentVersionEventType;
+import eu.europa.ec.edelivery.smp.data.enums.DocumentVersionStatusType;
 import eu.europa.ec.edelivery.smp.data.enums.EventSourceType;
 
 import java.time.OffsetDateTime;
@@ -18,6 +19,7 @@ public class DocumentVersionEventRO extends BaseRO {
     private static final long serialVersionUID = 9008583888835630037L;
 
     private DocumentVersionEventType eventType = DocumentVersionEventType.CREATE;
+    private DocumentVersionStatusType documentVersionStatus = DocumentVersionStatusType.DRAFT;
     private OffsetDateTime eventOn;
     private String username;
     private EventSourceType eventSourceType = EventSourceType.OTHER;
@@ -63,4 +65,13 @@ public class DocumentVersionEventRO extends BaseRO {
     public void setDetails(String details) {
         this.details = details;
     }
+
+
+    public DocumentVersionStatusType getDocumentVersionStatus() {
+        return documentVersionStatus;
+    }
+
+    public void setDocumentVersionStatus(DocumentVersionStatusType status) {
+        this.documentVersionStatus = status;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java
index 73cb52ccc8af8fdcac9c5fa1a7e0e48820707216..6ee12b9a0c7abc74ccc082f6b9bd724e35e91d52 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/DomainPublicRO.java
@@ -20,7 +20,7 @@ package eu.europa.ec.edelivery.smp.data.ui;
 
 
 /**
- * Domain resource object containing only public data
+ * Domain resource object containing only public data. Mainly used for search filtering.
  *
  * @author Joze Rihtarsic
  * @since 5.0
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceRO.java
index 52021bf363a96cada90c8e2a84732ab5522747d8..2b76889e5a670002e226cdd1fb187b9a22714e2a 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceRO.java
@@ -37,13 +37,10 @@ public class ResourceRO extends BaseRO {
     private String resourceTypeIdentifier;
 
     private String identifierValue;
-
     private String identifierScheme;
-
     private boolean smlRegistered = false;
-
     private Boolean reviewEnabled;
-
+    private Boolean hasCurrentUserReviewPermission;
     private VisibilityType visibility = VisibilityType.PUBLIC;
 
     public String getResourceId() {
@@ -102,6 +99,14 @@ public class ResourceRO extends BaseRO {
         this.visibility = visibility;
     }
 
+    public Boolean getHasCurrentUserReviewPermission() {
+        return hasCurrentUserReviewPermission;
+    }
+
+    public void setHasCurrentUserReviewPermission(Boolean hasCurrentUserReviewPermission) {
+        this.hasCurrentUserReviewPermission = hasCurrentUserReviewPermission;
+    }
+
     @Override
     public String toString() {
         return "ResourceRO{" +
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SearchReferenceDocumentRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SearchReferenceDocumentRO.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7c3960abbf05330aa8f7990beda4e5b62f5b8a1
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/SearchReferenceDocumentRO.java
@@ -0,0 +1,107 @@
+package eu.europa.ec.edelivery.smp.data.ui;
+
+import eu.europa.ec.edelivery.smp.data.enums.DocumentReferenceType;
+
+/**
+ *
+ *
+ * @since 5.0
+ * @author Joze RIHTARSIC
+ */
+public class SearchReferenceDocumentRO extends BaseRO {
+
+    private static final long serialVersionUID = 9008583888835630041L;
+
+    private String documentId;
+    private String resourceId;
+    private String subresourceId;
+
+    private DocumentReferenceType referenceType;
+    private String referenceUrl;
+    private String documentName;
+    private String resourceValue;
+    private String resourceScheme;
+    private String subresourceValue;
+    private String subresourceScheme;
+
+    public String getDocumentId() {
+        return documentId;
+    }
+
+    public void setDocumentId(String documentId) {
+        this.documentId = documentId;
+    }
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public String getSubresourceId() {
+        return subresourceId;
+    }
+
+    public void setSubresourceId(String subresourceId) {
+        this.subresourceId = subresourceId;
+    }
+
+
+    public String getReferenceUrl() {
+        return referenceUrl;
+    }
+
+    public void setReferenceUrl(String referenceUrl) {
+        this.referenceUrl = referenceUrl;
+    }
+
+    public DocumentReferenceType getReferenceType() {
+        return referenceType;
+    }
+
+    public void setReferenceType(DocumentReferenceType referenceType) {
+        this.referenceType = referenceType;
+    }
+
+    public String getDocumentName() {
+        return documentName;
+    }
+
+    public void setDocumentName(String documentName) {
+        this.documentName = documentName;
+    }
+
+    public String getResourceValue() {
+        return resourceValue;
+    }
+
+    public void setResourceValue(String resourceValue) {
+        this.resourceValue = resourceValue;
+    }
+
+    public String getResourceScheme() {
+        return resourceScheme;
+    }
+
+    public void setResourceScheme(String resourceScheme) {
+        this.resourceScheme = resourceScheme;
+    }
+
+    public String getSubresourceValue() {
+        return subresourceValue;
+    }
+
+    public void setSubresourceValue(String subresourceValue) {
+        this.subresourceValue = subresourceValue;
+    }
+
+    public String getSubresourceScheme() {
+        return subresourceScheme;
+    }
+
+    public void setSubresourceScheme(String subresourceScheme) {
+        this.subresourceScheme = subresourceScheme;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java
index 3ba836cfc21c9f1e0409ca95b208010c152d56cd..8e3f75e6ba717b7be3eda5fd42464bab9c8990a1 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/exceptions/ErrorResponseRO.java
@@ -28,6 +28,7 @@ import java.util.Objects;
  */
 public class ErrorResponseRO {
     protected String businessCode;
+    protected String errorCode;
     protected String errorDescription;
     protected String errorUniqueId;
 
@@ -67,6 +68,13 @@ public class ErrorResponseRO {
         this.errorDescription = value;
     }
 
+    public String getErrorCode() {
+        return errorCode;
+    }
+
+    public void setErrorCode(String errorCode) {
+        this.errorCode = errorCode;
+    }
 
     public String getErrorUniqueId() {
         return errorUniqueId;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/ErrorCode.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/ErrorCode.java
index 77f5a3dd9f385e5195f72187b6aa6e0238262ca8..1bbda1d3f3be80a85f64e156ae6be83f5b37af5e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/ErrorCode.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/exceptions/ErrorCode.java
@@ -32,7 +32,10 @@ public enum ErrorCode {
     UNAUTHORIZED(401, "SMP:003",ErrorBusinessCode.UNAUTHORIZED, "User not authorized!"),
     UNAUTHORIZED_INVALID_USER_IDENTIFIER(401, "SMP:004",ErrorBusinessCode.UNAUTHORIZED, "Invalid user identifier! User not authorized."),
     UNAUTHORIZED_INVALID_IDENTIFIER(401, "SMP:005",ErrorBusinessCode.UNAUTHORIZED, "Invalid entity identifier!  User not authorized to access the entity data"),
-    UNAUTHORIZED_INVALID_RESET_TOKEN(401, "SMP:006",ErrorBusinessCode.UNAUTHORIZED, "Reset token; Invalid or not active reset token!"),
+    UNAUTHORIZED_INVALID_RESET_TOKEN(401, "SMP:006",ErrorBusinessCode.UNAUTHORIZED, "The reset token it is invalid or not active any more. Please try to reset your password again."),
+
+    USER_CHANGE_INVALID_NEW_CREDENTIAL(400, "SMP:010",ErrorBusinessCode.INVALID_INPUT_DATA, "Password change failed. %s"),
+
 
     INVALID_ENCODING (500, "SMP:100",ErrorBusinessCode.TECHNICAL, "Unsupported or invalid encoding for %s!"),
     SML_INVALID_IDENTIFIER (400,"SMP:101",ErrorBusinessCode.FORMAT_ERROR,"Malformed identifier, scheme and id should be delimited by double colon: %s "),
@@ -41,6 +44,7 @@ public enum ErrorCode {
     NO_DOMAIN (500,"SMP:110",ErrorBusinessCode.TECHNICAL, "No domain configured on SMP, at least one domain is mandatory!"),
     DOMAIN_NOT_EXISTS(404,"SMP:111",ErrorBusinessCode.NOT_FOUND, "Invalid domain '%s'!"),
     INVALID_DOMAIN_CODE(400,"SMP:112",ErrorBusinessCode.FORMAT_ERROR,"Provided Domain Code '%s' does not match required pattern: '%s'"),
+    GROUP_NOT_EXISTS(404,"SMP:111",ErrorBusinessCode.NOT_FOUND, "Invalid domain '%s'!"),
     ILLEGAL_STATE_DOMAIN_MULTIPLE_ENTRY(500,"SMP:113",ErrorBusinessCode.TECHNICAL,"More than one domain entry  (domain: '%s') is defined in database!"),
     MISSING_DOMAIN(400,"SMP:114",ErrorBusinessCode.MISSING_FIELD,"More than one domain registered on SMP. The domain must be defined!"),
     ILLEGAL_STATE_DOMAIN_GROUP_MULTIPLE_ENTRY(500,"SMP:115",ErrorBusinessCode.TECHNICAL,"More than one group for domain entry  (group: '%s',  domain: '%s') is defined in database!"),
@@ -78,6 +82,7 @@ public enum ErrorCode {
     // SML integration
     SML_INTEGRATION_EXCEPTION (500,"SMP:150",ErrorBusinessCode.TECHNICAL,"SML integration error! Error: %s "),
     XML_SIGNING_EXCEPTION (500,"SMP:500",ErrorBusinessCode.TECHNICAL,"Error occurred while signing response!"),
+    INTERNAL_ERROR_GENERIC (500,"SMP:501",ErrorBusinessCode.TECHNICAL, "Internal error!"),
     JAXB_INITIALIZATION (500,"SMP:511",ErrorBusinessCode.TECHNICAL, "Could not create Unmarshaller for class [%s]!"),
     XML_PARSE_EXCEPTION (500,"SMP:512",ErrorBusinessCode.TECHNICAL, "Error occurred while parsing input stream for [%s].  Error: %s!"),
     INVALID_REQUEST(400,"SMP:513",ErrorBusinessCode.TECHNICAL, "Invalid request [%s]. Error: %s!"),
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/DomainGuard.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/DomainGroupGuard.java
similarity index 52%
rename from smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/DomainGuard.java
rename to smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/DomainGroupGuard.java
index 35e9c89c23b1d2ecf6da09775dfc86a5c9be6127..ffda74cb3f8dfbae975dffc233afea71ce202343 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/DomainGuard.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/DomainGroupGuard.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -20,11 +20,13 @@ package eu.europa.ec.edelivery.smp.security;
 
 import eu.europa.ec.edelivery.smp.auth.SMPUserDetails;
 import eu.europa.ec.edelivery.smp.data.dao.DomainMemberDao;
+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.dao.ResourceMemberDao;
 import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBGroup;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
@@ -32,23 +34,41 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.resource.DomainResolverService;
 import eu.europa.ec.edelivery.smp.servlet.ResourceAction;
 import eu.europa.ec.edelivery.smp.servlet.ResourceRequest;
+import eu.europa.ec.edelivery.smp.utils.EntityLoggingUtils;
 import org.springframework.security.authentication.AuthenticationServiceException;
 import org.springframework.stereotype.Component;
 
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * The class is responsible for guarding the domain groups, resources and sub-resources.
+ * It validates if users have any "permission to" execute the http action on the domain and groups.
+ *
+ * @since 5.0
+ * @author Joze RIHTARSIC
+ */
 @Component
-public class DomainGuard {
-    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainGuard.class);
+public class DomainGroupGuard {
+    private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainGroupGuard.class);
+    public static final String NOT_DEFINED = "Not defined";
 
     final DomainResolverService domainResolverService;
-    DomainMemberDao domainMemberDao;
-    GroupMemberDao groupMemberDao;
-    ResourceMemberDao resourceMemberDao;
+    final GroupDao groupDao;
+    final DomainMemberDao domainMemberDao;
+    final GroupMemberDao groupMemberDao;
+    final ResourceMemberDao resourceMemberDao;
 
-    public DomainGuard(DomainResolverService domainResolverService, DomainMemberDao domainMemberDao, GroupMemberDao groupMemberDao, ResourceMemberDao resourceMemberDao) {
+    public DomainGroupGuard(DomainResolverService domainResolverService,
+                            DomainMemberDao domainMemberDao,
+                            GroupMemberDao groupMemberDao,
+                            ResourceMemberDao resourceMemberDao,
+                            GroupDao groupDao) {
         this.domainResolverService = domainResolverService;
         this.domainMemberDao = domainMemberDao;
         this.groupMemberDao = groupMemberDao;
         this.resourceMemberDao = resourceMemberDao;
+        this.groupDao = groupDao;
     }
 
 
@@ -72,6 +92,28 @@ public class DomainGuard {
         throw new AuthenticationServiceException("User is not authorized for the domain!");
     }
 
+    /**
+     * Method resolves the domain and authorize the user for the action on the domain
+     *
+     * @param resourceRequest a resource request
+     * @param user            a user trying to execute the action on the resource
+     * @return the DBDomain
+     */
+    public List<DBGroup> resolveAndAuthorizeForGroup(ResourceRequest resourceRequest, SMPUserDetails user) {
+
+        List<DBGroup> groups = domainResolverService.resolveGroup(
+                user != null ? user.getUser() : null,
+                resourceRequest.getAuthorizedDomain(),
+                resourceRequest.getResourceGroupParameter()
+        );
+
+        if (isUserAuthorizedForGroup(groups, user, resourceRequest.getAction())) {
+            resourceRequest.getAuthorizedGroups().addAll(groups);
+            return groups;
+        }
+        throw new AuthenticationServiceException("User is not authorized for the group!");
+    }
+
     /**
      * Purpose of the method is to guard domain resources and sub-resources. It validates if users has any
      * "permission to" execute the http action on the domain resources and subresources. More accurate check is done
@@ -83,9 +125,10 @@ public class DomainGuard {
      * @return true if user is authorized to execute the action on the domain
      */
     public boolean isUserIsAuthorizedForDomainResourceAction(DBDomain domain, SMPUserDetails user, ResourceAction action) {
-        LOG.debug("Authorize check for user [{}], domain [{}] and action [{}]", user, domain, action);
+        String userInfo = user != null ? user.getUsername() : "anonymous";
+        LOG.debug("Authorize check for user [{}], domain [{}] and action [{}]", userInfo, domain, action);
         if (action == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Null http action", "Action cannot be null!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Null http action ", "Action cannot be null!");
         }
         switch (action) {
             case READ:
@@ -95,13 +138,13 @@ public class DomainGuard {
             case DELETE:
                 return canDelete(user, domain);
         }
-        throw new SMPRuntimeException(ErrorCode.INTERNAL_ERROR, "Unknown user action: [" + action + "]");
+        throw new SMPRuntimeException(ErrorCode.INTERNAL_ERROR, "Unknown user [" + userInfo + "] action: [" + action + "]");
     }
 
     /**
      * Method validates of the user can read resources on the domain!
      *
-     * @param user  user to be authorized for READ action
+     * @param user   user to be authorized for READ action
      * @param domain domain to be authorized
      * @return true if user is authorized to execute the action on the domain, else it returns false
      */
@@ -168,11 +211,98 @@ public class DomainGuard {
         boolean isAuthorized = groupMemberDao.isUserAnyDomainGroupResourceMemberWithRole(user.getUser(), domain, MembershipRoleType.ADMIN)
                 || resourceMemberDao.isUserAnyDomainResourceMemberWithRole(user.getUser(), domain, MembershipRoleType.ADMIN);
 
-        if (isAuthorized){
+        if (isAuthorized) {
             LOG.info(SMPLogger.SECURITY_MARKER, "User: [{}] is authorized to create/update resources from Domain: [{}]", user, domain);
         } else {
             LOG.warn(SMPLogger.SECURITY_MARKER, "User: [{}] is NOT authorized to create/update resources from Domain: [{}]", user, domain);
         }
         return isAuthorized;
     }
+
+
+    public boolean isUserAuthorizedForGroup(List<DBGroup> groups, SMPUserDetails user, ResourceAction action) {
+        String userInfo = EntityLoggingUtils.userDetailToString(user);
+        LOG.debug("Authorize check for user [{}], group size [{}] and action [{}]", userInfo, groups.size(), action);
+        if (action == null) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Null http action", "Action cannot be null!");
+        }
+        switch (action) {
+            case READ:
+                return canRead(user, groups);
+            case CREATE_UPDATE:
+                return canCreateUpdate(user, groups);
+            case DELETE:
+                return canDelete(user, groups);
+        }
+        throw new SMPRuntimeException(ErrorCode.INTERNAL_ERROR, "Unknown user action: [" + action + "]");
+    }
+
+    protected boolean canRead(SMPUserDetails user, List<DBGroup> groups) {
+        String userInfo = EntityLoggingUtils.userDetailToString(user);
+        String groupsInfo = groups.stream().map(DBGroup::getGroupName).reduce((a, b) -> a + ", " + b).orElse(NOT_DEFINED);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to read groups [{}]", userInfo, groupsInfo);
+        if (groups.isEmpty()) {
+            LOG.debug(SMPLogger.SECURITY_MARKER, "Group is not defined for user [{}] the READ action. Authorization will be determinate at resource level", userInfo);
+            return true;
+        }
+        // all public groups are visible to all users
+        if (groups.stream().anyMatch(group -> group.getVisibility() == VisibilityType.PUBLIC)) {
+            // if any group is public, user can read it return true. The rest of the groups will be checked at resource level
+            LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is authorized to read public groups [{}]", userInfo, groupsInfo);
+            return true;
+        }
+        // group is private, only members can read it
+        if (user == null || user.getUser() == null) {
+            LOG.warn(SMPLogger.SECURITY_MARKER, "Anonymous user [{}] is not authorized to read groups [{}]", userInfo, groupsInfo);
+            return false;
+        }
+        // check if user is admin of any group or member of any group
+        boolean isAuthorized = groupMemberDao.isUserGroupMember(user.getUser(), groups)
+                || resourceMemberDao.isUserAnyGroupsResourceMember(user.getUser(), groups);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is authorized:[{}] to read resources from groups [{}]", userInfo, isAuthorized, groupsInfo);
+        return isAuthorized;
+    }
+
+    protected boolean canCreateUpdate(SMPUserDetails user, List<DBGroup> groups) {
+        String userInfo = EntityLoggingUtils.userDetailToString(user);
+        String groupsInfo = groups.stream().map(DBGroup::getGroupName).reduce((a, b) -> a + ", " + b).orElse(NOT_DEFINED);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to create/update group [{}]", userInfo, groupsInfo);
+        Long userId = user == null || user.getUser() == null ? null : user.getUser().getId();
+        // group is private, only members can read it
+        if (userId == null) {
+            LOG.warn(SMPLogger.SECURITY_MARKER, "Anonymous user [{}] is not authorized to create/update resources on groups [{}]", userInfo, groupsInfo);
+            return false;
+        }
+        // allow only group admins to create/delete resources and group members to update resources
+        List<Long> groupIds = groups.stream().map(DBGroup::getId).collect(Collectors.toList());
+        boolean isAuthorized =
+                resourceMemberDao.isUserAnyGroupsResourceMemberWithRole(userId, groupIds, MembershipRoleType.ADMIN)
+                        || groupMemberDao.isUserGroupMemberWithRole(userId, groupIds, MembershipRoleType.ADMIN);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is authorized: [{}] to create/update resources from Group [{}]", userInfo, isAuthorized, groups);
+        return isAuthorized;
+    }
+
+    protected boolean canDelete(SMPUserDetails user, List<DBGroup> groups) {
+        String userInfo = EntityLoggingUtils.userDetailToString(user);
+        String groupsInfo = groups.stream().map(DBGroup::getGroupName).reduce((a, b) -> a + ", " + b).orElse(NOT_DEFINED);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to delete resource on groups [{}]", userInfo, groupsInfo);
+        if (groups.isEmpty()) {
+            LOG.warn(SMPLogger.SECURITY_MARKER, "Group must be specified for action DELETE. User is not authorized [{}],", userInfo);
+            return false;
+        }
+
+        // group is private, only members can read it
+        Long userId = user == null || user.getUser() == null ? null : user.getUser().getId();
+        if (userId == null) {
+            LOG.warn(SMPLogger.SECURITY_MARKER, "Anonymous user [{}] is not authorized to delete resources on groups [{}]", userInfo, groupsInfo);
+            return false;
+        }
+        // allow only group admins to delete resources
+        List<Long> groupIds = groups.stream().map(DBGroup::getId).collect(Collectors.toList());
+        boolean isAuthorized =
+                resourceMemberDao.isUserAnyGroupsResourceMemberWithRole(userId, groupIds, MembershipRoleType.ADMIN)
+                        || groupMemberDao.isUserGroupMemberWithRole(userId, groupIds, MembershipRoleType.ADMIN);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is authorized: [{}] to delete resources from groups [{}]", userInfo, isAuthorized, groupsInfo);
+        return isAuthorized;
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/ResourceGuard.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/ResourceGuard.java
index ddb816aec16a52e9b42637e753f4abec12312ad0..23156f0c6ea1764f8512b48cc42f73df30beb597 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/ResourceGuard.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/security/ResourceGuard.java
@@ -36,16 +36,20 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.servlet.ResourceAction;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
+
 /**
  * Service implements logic if user can activate action on the resource
  */
 
 @Service
 public class ResourceGuard {
+
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ResourceGuard.class);
-    DomainMemberDao domainMemberDao;
-    GroupMemberDao groupMemberDao;
-    ResourceMemberDao resourceMemberDao;
+    private static final String LOG_NOT_LOGGED_IN = "Anonymous users are not permitted to execute action [{}]!";
+    private DomainMemberDao domainMemberDao;
+    private GroupMemberDao groupMemberDao;
+    private ResourceMemberDao resourceMemberDao;
 
     public ResourceGuard(DomainMemberDao domainMemberDao, GroupMemberDao groupMemberDao, ResourceMemberDao resourceMemberDao) {
         this.domainMemberDao = domainMemberDao;
@@ -97,12 +101,23 @@ public class ResourceGuard {
         DBDomain domain = group.getDomain();
         DBUser dbuser = user == null ? null : user.getUser();
         // if domain is internal check if user is member of domain, or any internal resources, groups
+
+        if (resource.getVisibility() == VisibilityType.PRIVATE ) {
+            LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to read private resource [{}]", user, resource);
+            return dbuser!=null && resourceMemberDao.isUserResourceMember(dbuser, resource);
+        }
+
+        if (group.getVisibility() == VisibilityType.PRIVATE) {
+            LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to read public resource in a private group [{}]", user, group);
+            return dbuser!=null &&  (groupMemberDao.isUserGroupMember(dbuser, Collections.singletonList(group)) ||
+                    resourceMemberDao.isUserAnyGroupResourceMember(dbuser, group));
+        }
+
         if ((resource.getVisibility() == null || domain.getVisibility() == VisibilityType.PRIVATE)
                 && (dbuser == null ||
                 !(domainMemberDao.isUserDomainMember(dbuser, domain)
                         || groupMemberDao.isUserAnyDomainGroupResourceMember(dbuser, domain)
-                        || resourceMemberDao.isUserAnyDomainResourceMember(dbuser, domain)))
-        ) {
+                        || resourceMemberDao.isUserAnyDomainResourceMember(dbuser, domain)))) {
             LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is not authorized to read internal domain [{}] resources", user, domain);
             return false;
         }
@@ -131,7 +146,7 @@ public class ResourceGuard {
     public boolean canUpdate(SMPUserDetails user, DBResource resource) {
         LOG.info(SMPLogger.SECURITY_MARKER, "User [{}] is trying to update resource [{}]", user, resource);
         if (user == null || user.getUser() == null) {
-            LOG.warn("Not user is logged in!");
+            LOG.warn(LOG_NOT_LOGGED_IN, "UPDATE");
             return false;
         }
         // only resource member with admin rights can update resource
@@ -147,7 +162,7 @@ public class ResourceGuard {
     public boolean canCreate(SMPUserDetails user, DBResource resource, DBDomain domain) {
         LOG.info(SMPLogger.SECURITY_MARKER, "User [{}] is trying to create resource [{}]", user, resource);
         if (user == null || user.getUser() == null) {
-            LOG.warn("Not user is logged in!");
+            LOG.warn(LOG_NOT_LOGGED_IN, "CREATE");
             return false;
         }
         return groupMemberDao.isUserAnyDomainGroupResourceMemberWithRole(user.getUser(),
@@ -160,20 +175,20 @@ public class ResourceGuard {
         LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to delete resource [{}]", user, resource);
         // same as for create
         if (user == null || user.getUser() == null) {
-            LOG.warn("Not user is logged in!");
+            LOG.warn(LOG_NOT_LOGGED_IN, "DELETE");
             return false;
         }
         return canCreate(user, resource, domain);
     }
 
     public boolean canDelete(SMPUserDetails user, DBSubresource subresource) {
-        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to delete resource [{}]", user, subresource);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to delete subresource [{}]", user, subresource);
         // Subresource can be created by the resource admin, the same as for update
         return canUpdate(user, subresource);
     }
 
     public boolean canCreateUpdate(SMPUserDetails user, DBSubresource subresource) {
-        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to delete resource [{}]", user, subresource);
+        LOG.debug(SMPLogger.SECURITY_MARKER, "User [{}] is trying to create/update subresource [{}]", user, subresource);
         // Subresource can be created by the resource admin, the same as for update
         return canUpdate(user, subresource);
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialService.java
index 38791f45918a3b337dab826ae98c5ead3ab414f2..d5413871072d2f6b693d31356d872b88409f31a7 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialService.java
@@ -26,6 +26,7 @@ import eu.europa.ec.edelivery.smp.auth.UILoginAuthenticationToken;
 import eu.europa.ec.edelivery.smp.config.SMPEnvironmentProperties;
 import eu.europa.ec.edelivery.smp.data.dao.CredentialDao;
 import eu.europa.ec.edelivery.smp.data.dao.UserDao;
+import eu.europa.ec.edelivery.smp.data.enums.CredentialTargetType;
 import eu.europa.ec.edelivery.smp.data.enums.CredentialType;
 import eu.europa.ec.edelivery.smp.data.model.user.DBCertificate;
 import eu.europa.ec.edelivery.smp.data.model.user.DBCredential;
@@ -76,6 +77,8 @@ public class CredentialService {
     protected static final BadCredentialsException SUSPENDED_CREDENTIALS_EXCEPTION = new BadCredentialsException(ErrorCode.UNAUTHORIZED_CREDENTIAL_SUSPENDED.getMessage());
     protected static final int RESET_TOKEN_LENGTH = 64;
 
+    private static final String USER_ID_REQUEST_TYPE = "UserId";
+
     final UserDao userDao;
     final CredentialDao credentialDao;
     final ConversionService conversionService;
@@ -341,7 +344,7 @@ public class CredentialService {
         // retrieve user Optional credentials by username
         Optional<DBCredential> optCredential = getActiveCredentialsForUsernameToReset(username, true);
         if (!optCredential.isPresent()) {
-            LOG.info("Skip generating reset token for username [{}]!", username);
+            LOG.info("Skip generating reset token for username [{}]. User is not active!", username);
             return;
         }
         DBCredential dbCredential = optCredential.get();
@@ -363,23 +366,24 @@ public class CredentialService {
         // retrieve user Optional credentials by username
         Optional<DBCredential> optCredential = getActiveCredentialsForUsernameToReset(username, false);
         if (!optCredential.isPresent()) {
+            LOG.warn("User [{}] does not have active reset token!", username);
             throw UNAUTHORIZED_INVALID_RESET_TOKEN;
         }
         DBCredential dbCredential = optCredential.get();
         if (!resetToken.equals(dbCredential.getResetToken())) {
-            LOG.warn("User [{}] reset token does not match the active reset token! The request is ignored", username);
-            return;
+            LOG.warn("User [{}] reset token does not match the active reset token!", username);
+            throw UNAUTHORIZED_INVALID_RESET_TOKEN;
         }
 
         Pattern pattern = configurationService.getPasswordPolicyRexExp();
         if (pattern != null && !pattern.matcher(newPassword).matches()) {
             LOG.info(SMPLogger.SECURITY_MARKER, "Change/set password failed because it does not match password policy!: [{}]", username);
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "PasswordChange", configurationService.getPasswordPolicyValidationMessage());
+            throw new SMPRuntimeException(ErrorCode.USER_CHANGE_INVALID_NEW_CREDENTIAL, configurationService.getPasswordPolicyValidationMessage());
         }
 
         if (StringUtils.isNotBlank(dbCredential.getValue()) && BCrypt.checkpw(newPassword, dbCredential.getValue())) {
             LOG.info(SMPLogger.SECURITY_MARKER, "Change/set password failed because 'new' password match the old password for user: [{}]", username);
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "PasswordChange", configurationService.getPasswordPolicyValidationMessage());
+            throw new SMPRuntimeException(ErrorCode.USER_CHANGE_INVALID_NEW_CREDENTIAL, configurationService.getPasswordPolicyValidationMessage());
         }
 
         OffsetDateTime now = OffsetDateTime.now();
@@ -407,13 +411,24 @@ public class CredentialService {
      * @return Optional of DBCredential: if the user has active credentials and active else empty is returned
      */
     private Optional<DBCredential> getActiveCredentialsForUsernameToReset(String username, boolean toGenerateResetToken) {
-        // retrieve user Optional credentials by username
+
         Optional<DBCredential> optCredential = credentialDao.findUsernamePasswordCredentialForUsernameAndUI(username);
+        DBCredential dbCredential;
         if (!optCredential.isPresent()) {
-            LOG.warn("There is not credentials for User [{}]!", username);
-            return optCredential;
+            DBUser user = userDao.findUserByUsername(username).orElseThrow(() -> {
+                LOG.warn("There is no user with username [{}]!", username);
+                return new SMPRuntimeException(ErrorCode.UNAUTHORIZED_INVALID_USERNAME_PASSWORD, "User not found!");
+            });
+            LOG.info("User [{}] does not have username/password credentials. Create new credentials!", username);
+            dbCredential = createCredentialsForUser(user.getId(),
+                    CredentialType.USERNAME_PASSWORD,
+                    CredentialTargetType.UI);
+            // persist new credential
+            credentialDao.persist(dbCredential);
+            optCredential = Optional.of(dbCredential);
+        } else {
+            dbCredential = optCredential.get();
         }
-        DBCredential dbCredential = optCredential.get();
 
         if (!dbCredential.getUser().isActive() || !dbCredential.isActive()) {
             LOG.info("User [{}] or credentials are not active. Skip reset password request!", username);
@@ -434,6 +449,31 @@ public class CredentialService {
         return optCredential;
     }
 
+
+    /**
+     * Method creates Username/passwords credentials for the user with given userId.
+     * The method must be called inside active transactions.
+     *
+     * @param userID               to change/create username-password credentials
+     * @param credentialType       the credential type
+     * @param credentialTargetType the credential target
+     */
+    public DBCredential createCredentialsForUser(Long userID, CredentialType credentialType, CredentialTargetType credentialTargetType) {
+
+        DBUser dbUserToUpdate = userDao.find(userID);
+        if (dbUserToUpdate == null) {
+            LOG.error("Can not create user password credentials, because user [{}] does not exist!", userID);
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, USER_ID_REQUEST_TYPE, "Can not find user id to update!");
+        }
+        DBCredential credential = new DBCredential();
+        credential.setUser(dbUserToUpdate);
+        credential.setName(dbUserToUpdate.getUsername());
+        credential.setCredentialType(credentialType);
+        credential.setCredentialTarget(credentialTargetType);
+        return credential;
+    }
+
+
     public void validatePasswordResetToken(String resetToken){
         Optional<DBCredential> optCredential = credentialDao.findUCredentialForUsernamePasswordTypeAndResetToken(resetToken);
         if (!optCredential.isPresent()) {
@@ -478,8 +518,9 @@ public class CredentialService {
      * Method validates if the certificate contains one of allowed Certificate policy. At the moment it does not validates
      * the whole chain. Because in some configuration cases does not use the truststore
      *
-     * @param certificateId
-     * @throws CertificateException
+     * @param certificateId certificate id to be validated
+     * @param certPolicyList certificate policy list
+     * @throws AuthenticationServiceException
      */
     protected void validateCertificatePolicyMatchLegacy(String certificateId, List<String> certPolicyList) throws AuthenticationServiceException {
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialsAlertService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialsAlertService.java
index 82dbb170da9ca5ee490c9136e23f97bc11912910..88956c554f8704f701d8e5c9920ce86991364f36 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialsAlertService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialsAlertService.java
@@ -49,7 +49,7 @@ import java.time.OffsetDateTime;
 import java.util.Date;
 
 import static eu.europa.ec.edelivery.smp.cron.CronTriggerConfig.TRIGGER_BEAN_CREDENTIAL_ALERTS;
-import static java.time.format.DateTimeFormatter.ISO_DATE_TIME;
+import static eu.europa.ec.edelivery.smp.utils.DateTimeUtils.formatOffsetDateTimeWithLocal;
 import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME;
 
 /**
@@ -239,18 +239,16 @@ public class CredentialsAlertService {
                                           String credentialId,
                                           OffsetDateTime expirationDate
     ) {
-
-        String serverName = HttpUtils.getServerAddress();
+        DBUser user = credential.getUser();
         // add alert properties
         alert.addProperty(CredentialsExpirationProperties.CREDENTIAL_TYPE.name(), credentialType.name());
         alert.addProperty(CredentialsExpirationProperties.CREDENTIAL_ID.name(), credentialId);
-        alert.addProperty(CredentialsExpirationProperties.EXPIRATION_DATETIME.name(), expirationDate);
-        alert.addProperty(CredentialsExpirationProperties.REPORTING_DATETIME.name(), alert.getReportingTime());
+        alert.addProperty(CredentialsExpirationProperties.EXPIRATION_DATETIME.name(), formatOffsetDateTimeWithLocal(expirationDate, user.getSmpLocale()));
+        alert.addProperty(CredentialsExpirationProperties.REPORTING_DATETIME.name(), formatOffsetDateTimeWithLocal(expirationDate, user.getSmpLocale()));
         alert.addProperty(CredentialsExpirationProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name());
-        alert.addProperty(CredentialsExpirationProperties.SERVER_NAME.name(), serverName);
         alertDao.persistFlushDetach(alert);
         // submit alerts
-        submitAlertMail(alert, credential.getUser());
+        submitAlertMail(alert, user);
         // when alert about to expire - check if the next cron execution is expired
         // and set date sent tp null to ensure alert submission in next cron execution
         credentialDao.updateAlertSentForUserCredentials(credential,
@@ -267,15 +265,13 @@ public class CredentialsAlertService {
                                                   OffsetDateTime lastFailedLoginDate
     ) {
         LOG.info("Prepare alert for credentials [{}] ", credentialId);
-        String serverName = HttpUtils.getServerAddress();
         // add alert properties
         alert.addProperty(CredentialVerificationFailedProperties.CREDENTIAL_TYPE.name(), credentialType.name());
         alert.addProperty(CredentialVerificationFailedProperties.CREDENTIAL_ID.name(), credentialId);
         alert.addProperty(CredentialVerificationFailedProperties.FAILED_LOGIN_ATTEMPT.name(), failedLoginCount.toString());
-        alert.addProperty(CredentialVerificationFailedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), lastFailedLoginDate);
-        alert.addProperty(CredentialVerificationFailedProperties.REPORTING_DATETIME.name(), alert.getReportingTime());
+        alert.addProperty(CredentialVerificationFailedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), formatOffsetDateTimeWithLocal(lastFailedLoginDate, user.getSmpLocale()));
+        alert.addProperty(CredentialVerificationFailedProperties.REPORTING_DATETIME.name(), formatOffsetDateTimeWithLocal(alert.getReportingTime(), user.getSmpLocale()));
         alert.addProperty(CredentialVerificationFailedProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name());
-        alert.addProperty(CredentialVerificationFailedProperties.SERVER_NAME.name(), serverName);
         alertDao.persistFlushDetach(alert);
         // submit alerts
         submitAlertMail(alert, user);
@@ -289,16 +285,15 @@ public class CredentialsAlertService {
                                          OffsetDateTime lastFailedLoginDate,
                                          OffsetDateTime suspendedUtil) {
 
-        String serverName = HttpUtils.getServerAddress();
+
         // add alert properties
         alert.addProperty(CredentialSuspendedProperties.CREDENTIAL_TYPE.name(), credentialType.name());
         alert.addProperty(CredentialSuspendedProperties.CREDENTIAL_ID.name(), credentialId);
         alert.addProperty(CredentialSuspendedProperties.FAILED_LOGIN_ATTEMPT.name(), failedLoginCount.toString());
-        alert.addProperty(CredentialSuspendedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), lastFailedLoginDate);
-        alert.addProperty(CredentialSuspendedProperties.SUSPENDED_UNTIL_DATETIME.name(), suspendedUtil);
-        alert.addProperty(CredentialSuspendedProperties.REPORTING_DATETIME.name(), alert.getReportingTime());
+        alert.addProperty(CredentialSuspendedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), formatOffsetDateTimeWithLocal(lastFailedLoginDate, user.getSmpLocale()));
+        alert.addProperty(CredentialSuspendedProperties.SUSPENDED_UNTIL_DATETIME.name(), formatOffsetDateTimeWithLocal(suspendedUtil, user.getSmpLocale()));
+        alert.addProperty(CredentialSuspendedProperties.REPORTING_DATETIME.name(), formatOffsetDateTimeWithLocal(alert.getReportingTime(), user.getSmpLocale()));
         alert.addProperty(CredentialSuspendedProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name());
-        alert.addProperty(CredentialSuspendedProperties.SERVER_NAME.name(), serverName);
         alertDao.persistFlushDetach(alert);
         // submit alerts
         submitAlertMail(alert, user);
@@ -404,7 +399,7 @@ public class CredentialsAlertService {
         // add alert properties
         alert.addProperty(CredentialsResetRequestProperties.CREDENTIAL_TYPE.name(), credentialType.name());
         alert.addProperty(CredentialsResetRequestProperties.CREDENTIAL_ID.name(), credentialId);
-        alert.addProperty(CredentialsResetRequestProperties.REPORTING_DATETIME.name(), alert.getReportingTime());
+        alert.addProperty(CredentialsResetRequestProperties.REPORTING_DATETIME.name(), formatOffsetDateTimeWithLocal(alert.getReportingTime(), user.getSmpLocale()));
         alert.addProperty(CredentialsResetRequestProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name());
         alert.addProperty(CredentialsResetRequestProperties.RESET_URL.name(), resetUrlPath);
         alert.addProperty(CredentialsResetRequestProperties.SERVER_NAME.name(), serverName);
@@ -437,13 +432,11 @@ public class CredentialsAlertService {
                                        CredentialType credentialType,
                                        String credentialId) {
 
-        String serverName = HttpUtils.getServerAddress();
         // add alert properties
         alert.addProperty(CredentialsChangedProperties.CREDENTIAL_TYPE.name(), credentialType.name());
         alert.addProperty(CredentialsChangedProperties.CREDENTIAL_ID.name(), credentialId);
-        alert.addProperty(CredentialsChangedProperties.REPORTING_DATETIME.name(), alert.getReportingTime());
+        alert.addProperty(CredentialsChangedProperties.REPORTING_DATETIME.name(), formatOffsetDateTimeWithLocal(alert.getReportingTime(), user.getSmpLocale()));
         alert.addProperty(CredentialsChangedProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name());
-        alert.addProperty(CredentialsChangedProperties.SERVER_NAME.name(), serverName);
         alertDao.persistFlushDetach(alert);
         // submit alerts
         submitAlertMail(alert, user);
@@ -463,6 +456,9 @@ public class CredentialsAlertService {
                                   AlertLevelEnum level,
                                   AlertTypeEnum alertType) {
 
+
+        String serverName = HttpUtils.getServerAddress();
+
         DBAlert alert = new DBAlert();
         alert.setMailSubject(mailSubject);
         alert.setMailTo(mailTo);
@@ -471,6 +467,7 @@ public class CredentialsAlertService {
         alert.setAlertType(alertType);
         alert.setAlertLevel(level);
         alert.setAlertStatus(AlertStatusEnum.PROCESS);
+        alert.addProperty(CredentialSuspendedProperties.SERVER_NAME.name(), serverName);
         return alert;
     }
 
@@ -487,13 +484,14 @@ public class CredentialsAlertService {
             return;
         }
 
-
         String mailFrom = configurationService.getAlertEmailFrom();
         MailDataModel props = new MailDataModel(user.getSmpLocale(), alert);
+
+        // add additional common properties to the model
         props.getModel().put(MailDataModel.CommonProperties.SMP_INSTANCE_NAME.name(),
                 configurationService.getSMPInstanceName());
         props.getModel().put(MailDataModel.CommonProperties.CURRENT_DATETIME.name(),
-                OffsetDateTime.now().format(ISO_DATE_TIME));
+                formatOffsetDateTimeWithLocal(OffsetDateTime.now(), user.getSmpLocale()));
 
         try {
             mailService.sendMail(props, mailFrom, alert.getMailTo());
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/IdentifierFormatterService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/IdentifierFormatterService.java
index b941fdb59fe4a6765d9d7118a5c89fc4bc9f2840..f52efaa953d24ed1339eb345d83af0bc6c69bef1 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/IdentifierFormatterService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/IdentifierFormatterService.java
@@ -69,7 +69,8 @@ public class IdentifierFormatterService {
                 .build();
 
         identifierFormatter.setCaseSensitiveSchemas(getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_CASE_SENSITIVE_SCHEMES));
-        identifierFormatter.setSchemeMandatory(getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_SCH_MANDATORY));
+        Boolean mandatory = getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_SCH_MANDATORY);
+        identifierFormatter.setSchemeMandatory(Boolean.TRUE.equals(mandatory));
         identifierFormatter.setSchemeValidationPattern(getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_SCH_VALIDATION_REGEXP));
 
         return identifierFormatter;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailDataModel.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailDataModel.java
index d0ee71f9403e259cf75cf0840b90e2862501e605..02d6ae8ab000e8a6b7702aceafc8fc064678175c 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailDataModel.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailDataModel.java
@@ -20,11 +20,17 @@ package eu.europa.ec.edelivery.smp.services.mail;
 
 import eu.europa.ec.edelivery.smp.data.model.DBAlert;
 import eu.europa.ec.edelivery.smp.data.ui.enums.AlertTypeEnum;
+import eu.europa.ec.edelivery.smp.utils.DateTimeUtils;
 import org.apache.commons.lang3.StringUtils;
 
+import java.time.OffsetDateTime;
 import java.util.HashMap;
 import java.util.Map;
 
+/**
+ * Mail data model for mail content. The class is used to create mail messages from templates and message
+ * translations. It contains common properties like current date time, SMP instance name, etc.
+ */
 public class MailDataModel {
     private static final String DEFAULT_LANGUAGE = "en";
     public enum CommonProperties {
@@ -33,21 +39,30 @@ public class MailDataModel {
     }
     private final String language;
     private final AlertTypeEnum alertType;
-    Map<String, Object> model = new HashMap<>();
-
+    Map<String, String> model = new HashMap<>();
 
     public MailDataModel(String language, AlertTypeEnum alertType, Map<String, Object> model) {
         this.language = language;
         this.alertType = alertType;
-        this.model.putAll(model);
+        model.forEach((key, value) -> this.model.put(key, valueToString(value)));
     }
 
     public MailDataModel(String language, final DBAlert alert) {
         this.language = language;
         this.alertType = alert.getAlertType();
-        alert.getProperties().forEach((key, prop) ->  this.model.put(key, prop.getValue()));
+        alert.getProperties().forEach((key, prop) ->  this.model.put(key,valueToString(prop.getValue())));
     }
 
+    private String valueToString(Object value) {
+        if (value instanceof OffsetDateTime) {
+            OffsetDateTime odt = (OffsetDateTime) value;
+            return DateTimeUtils.formatOffsetDateTimeWithLocal(odt, getLanguage(), null);
+        }
+        if (value == null) {
+            return "";
+        }
+        return String.valueOf(value);
+    }
     /**
      * Get language of the mail. If not set, default language "en" is used.
      * @return language of the mail or "en" if not set
@@ -60,7 +75,7 @@ public class MailDataModel {
         return alertType;
     }
 
-    public Map<String, Object> getModel() {
+    public Map<String, String> getModel() {
         return model;
     }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailTemplateService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailTemplateService.java
index 0abf9a4ac5061cfbf50782e6d31783c8db442abe..9858cc54d002ddeccb861116c9ad10bc8875993f 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailTemplateService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/mail/MailTemplateService.java
@@ -58,7 +58,7 @@ public class MailTemplateService {
     public String getMailHtmlContent(MailDataModel model) {
         InputStream templateIS = MailTemplateService.class.getResourceAsStream(MAIL_TEMPLATE);
         try {
-            Map<String, Object> modelData = new HashMap<>();
+            Map<String, String> modelData = new HashMap<>();
             modelData.put(MAIL_HEADER, getMailHeader(model));
             modelData.put(MAIL_FOOTER, getMailFooter(model));
             modelData.put(MAIL_TITLE, getMailTitle(model));
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/AbstractResourceHandler.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/AbstractResourceHandler.java
index 456f6987542ca902631482e3291fa4d9ea82856c..e5cf4f68b7995a6326cf922eeb5911aab81134af 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/AbstractResourceHandler.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/AbstractResourceHandler.java
@@ -110,12 +110,13 @@ public class AbstractResourceHandler {
      * @return data handler request data
      */
     public RequestData buildRequestDataForResource(DBDomain domain, DBResource resource) {
+
         byte[] content = resourceStorage.getDocumentContentForResource(resource);
         if (content == null || content.length == 0) {
             throw new SMPRuntimeException(ErrorCode.RESOURCE_DOCUMENT_MISSING, resource.getIdentifierValue(), resource.getIdentifierScheme());
         }
         // read and replace properties
-        Map<String, Object> docProp = resourceStorage.getResourceProperties(resource);
+        Map<String, String> docProp = resourceStorage.getResourceProperties(resource);
 
         try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
             StringNamedSubstitutor.resolve(new ByteArrayInputStream(content), docProp, baos, EXPECTED_RESOURCE_CHARSET);
@@ -143,7 +144,7 @@ public class AbstractResourceHandler {
                     resource.getIdentifierValue(), resource.getIdentifierScheme());
         }
 
-        Map<String, Object> docProp = resourceStorage.getSubresourceProperties(resource, subresource);
+        Map<String, String> docProp = resourceStorage.getSubresourceProperties(resource, subresource);
 
         try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
             StringNamedSubstitutor.resolve(new ByteArrayInputStream(content), docProp, baos, EXPECTED_RESOURCE_CHARSET);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DocumentVersionService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DocumentVersionService.java
index c3ba7d8e7fb5b479a9734d86e2fba7f3cb62523b..a11e2e11818cd90a5eb60ffe8a7138ccb5155d8e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DocumentVersionService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DocumentVersionService.java
@@ -47,12 +47,14 @@ public class DocumentVersionService {
                                                             String details, boolean publish) {
 
         DBDocumentVersion dbDocumentVersion = new DBDocumentVersion();
-        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.CREATE, eventSourceType, details);
+        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.CREATE,
+                DocumentVersionStatusType.DRAFT,
+                eventSourceType, details);
         dbDocumentVersion.addNewDocumentVersionEvent(dbEvent);
         dbDocumentVersion.setStatus(DocumentVersionStatusType.DRAFT);
         if (publish) {
             LOG.debug("Creating And Publish event for document version");
-            publishDocumentVersion(dbDocumentVersion, eventSourceType);
+            publishDocumentVersion(dbDocumentVersion, eventSourceType, false);
         }
         return dbDocumentVersion;
     }
@@ -65,7 +67,8 @@ public class DocumentVersionService {
      * @param details           details of the event
      */
     public void retireDocumentVersion(DBDocumentVersion dbDocumentVersion, EventSourceType eventSourceType, String details) {
-        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.RETIRE, eventSourceType, details);
+        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.RETIRE,
+                DocumentVersionStatusType.RETIRED, eventSourceType, details);
         dbDocumentVersion.addNewDocumentVersionEvent(dbEvent);
         dbDocumentVersion.setStatus(DocumentVersionStatusType.RETIRED);
     }
@@ -73,12 +76,15 @@ public class DocumentVersionService {
     /**
      * Method sets document version status to published and adds Publish event to the document version list of events
      *
-     * @param dbDocumentVersion document version to be published
-     * @param eventSourceType   event source type
+     * @param dbDocumentVersion    document version to be published
+     * @param eventSourceType      event source type
+     * @param addFirstPublishEvent if true, the event will be added to fist place in the list of events (because the list is in reverse order it is
+     *                             necessary to add it to the first place when adding single event, but when adding multiple events, the order should be reversed)
      */
-    public void publishDocumentVersion(DBDocumentVersion dbDocumentVersion, EventSourceType eventSourceType) {
-        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.PUBLISH, eventSourceType, null);
-        dbDocumentVersion.addNewDocumentVersionEvent(dbEvent);
+    public void publishDocumentVersion(DBDocumentVersion dbDocumentVersion, EventSourceType eventSourceType, boolean addFirstPublishEvent) {
+        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.PUBLISH,
+                DocumentVersionStatusType.PUBLISHED, eventSourceType, null);
+        dbDocumentVersion.addNewDocumentVersionEvent(dbEvent, addFirstPublishEvent);
         dbDocumentVersion.setStatus(DocumentVersionStatusType.PUBLISHED);
     }
 
@@ -91,7 +97,8 @@ public class DocumentVersionService {
      * @param message           message to be sent to the resource administrators
      */
     public void rejectDocumentVersion(DBDocumentVersion dbDocumentVersion, EventSourceType eventSourceType, String message) {
-        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.REJECT, eventSourceType, message);
+        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.REJECT,
+                DocumentVersionStatusType.REJECTED, eventSourceType, message);
         dbDocumentVersion.addNewDocumentVersionEvent(dbEvent);
         dbDocumentVersion.setStatus(DocumentVersionStatusType.REJECTED);
     }
@@ -105,7 +112,8 @@ public class DocumentVersionService {
      * @param message           message to be sent to the resource administrators
      */
     public void approveDocumentVersion(DBDocumentVersion dbDocumentVersion, EventSourceType eventSourceType, String message) {
-        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.APPROVE, eventSourceType, message);
+        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.APPROVE,
+                DocumentVersionStatusType.APPROVED, eventSourceType, message);
         dbDocumentVersion.addNewDocumentVersionEvent(dbEvent);
         dbDocumentVersion.setStatus(DocumentVersionStatusType.APPROVED);
     }
@@ -118,7 +126,9 @@ public class DocumentVersionService {
      * @param eventSourceType   event source type
      */
     public void requestReviewDocumentVersion(DBDocumentVersion dbDocumentVersion, EventSourceType eventSourceType) {
-        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.REQUEST_REVIEW, eventSourceType, null);
+        DBDocumentVersionEvent dbEvent = createDocumentVersionEvent(DocumentVersionEventType.REQUEST_REVIEW,
+                DocumentVersionStatusType.UNDER_REVIEW,
+                eventSourceType, null);
         dbDocumentVersion.addNewDocumentVersionEvent(dbEvent);
         dbDocumentVersion.setStatus(DocumentVersionStatusType.UNDER_REVIEW);
     }
@@ -133,6 +143,7 @@ public class DocumentVersionService {
      * @return
      */
     public DBDocumentVersionEvent createDocumentVersionEvent(DocumentVersionEventType eventType,
+                                                             DocumentVersionStatusType statusType,
                                                              EventSourceType eventSourceType,
                                                              String details) {
 
@@ -144,7 +155,7 @@ public class DocumentVersionService {
         } else {
             LOG.debug("User details not found for event creation ");
         }
-
+        dbEvent.setStatus(statusType);
         dbEvent.setEventOn(OffsetDateTime.now());
         dbEvent.setEventType(eventType);
         dbEvent.setEventSourceType(eventSourceType);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DomainResolverService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DomainResolverService.java
index 4b381614288bc4878b26e5b60c2825f78d0e1186..b8045b9eb4e24d0d1ef57292a4b6aee9cc8e30cf 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DomainResolverService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/DomainResolverService.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -20,19 +20,27 @@ package eu.europa.ec.edelivery.smp.services.resource;
 
 import eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum;
 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.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBGroup;
+import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
 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 eu.europa.ec.edelivery.smp.services.ConfigurationService;
+import eu.europa.ec.edelivery.smp.servlet.ResourceAction;
+import eu.europa.ec.edelivery.smp.utils.EntityLoggingUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Optional;
 import java.util.regex.Pattern;
 
 import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INVALID_DOMAIN_CODE;
+import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
 
 
 /**
@@ -49,10 +57,12 @@ public class DomainResolverService {
      */
     public static final Pattern DOMAIN_ID_PATTERN = Pattern.compile("[a-zA-Z0-9]{1,50}");
     final DomainDao domainDao;
+    final GroupDao groupDao;
     final ConfigurationService configurationService;
 
-    public DomainResolverService(DomainDao domainDao, ConfigurationService configurationService) {
+    public DomainResolverService(DomainDao domainDao, ConfigurationService configurationService, GroupDao groupDao) {
         this.domainDao = domainDao;
+        this.groupDao = groupDao;
         this.configurationService = configurationService;
     }
 
@@ -126,4 +136,53 @@ public class DomainResolverService {
         // get domain by code
         return domainDao.getDomainByCode(domain);
     }
+
+
+    /**
+     * Method resolves the group for the given domain, admin user and group name.
+     * If the group name is null/not given, the first group is returned. If the group name is provided
+     * but the user is not admin for the group, the exception is thrown.
+     *
+     * @param user        admin user creating the resource
+     * @param domain      domain where the resource is created
+     * @param domainGroup group name
+     * @return DBGroup for the given domain, user and group name.
+     * @throws SMPRuntimeException if the user is not admin authorized to create the resource for the given group/domain
+     */
+    public List<DBGroup> resolveGroup(DBUser user, DBDomain domain, String domainGroup) {
+        String userInfo = EntityLoggingUtils.entityToString(user, EntityLoggingUtils.NULL_USER);
+        LOG.debug("Resolve group for domain [{}] and user [{}] and group [{}]", domain.getDomainCode(),
+                userInfo,
+                domainGroup);
+        if (user == null) {
+            LOG.debug("User is null, return null");
+            return Collections.emptyList();
+        }
+
+        String username = user.getUsername();
+        String domainCode = domain.getDomainCode();
+        // return all groups for domain. groups will be filtered on
+        // authorization for action step
+        List<DBGroup> authorizedGroup = groupDao.getAllGroupsForDomain(domain);
+
+
+        if (StringUtils.isBlank(domainGroup)) {
+            // if no group is provided, return the first group
+            LOG.debug("No group is provided, can not determine the group, return al domain authorized groups");
+            return authorizedGroup;
+        }
+
+        if (authorizedGroup.stream().filter(entity -> equalsIgnoreCase(entity.getGroupName(), domainGroup)).count() == 0) {
+            throw new SMPRuntimeException(ErrorCode.GROUP_NOT_EXISTS, domainCode);
+        }
+
+        DBGroup group = authorizedGroup.stream()
+                .filter(entity -> equalsIgnoreCase(entity.getGroupName(), domainGroup))
+                .findFirst()
+                .orElseThrow(() -> new SMPRuntimeException(ErrorCode.UNAUTHORIZED,
+                        "User [" + username + "] is not authorized for group ["
+                                + domainGroup + "] in domain [" + domainCode + "]"));
+        return Collections.singletonList(group);
+
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceHandlerService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceHandlerService.java
index d4c8e3081342c07b54e05eede1dc4bee0f5a3bdb..b39e3f326a2c33874833d7b209c8e16bc8c50a64 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceHandlerService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceHandlerService.java
@@ -70,20 +70,18 @@ public class ResourceHandlerService extends AbstractResourceHandler {
     final GroupDao groupDao;
     final SMLIntegrationService integrationService;
     final DocumentVersionService documentVersionService;
-    private final ResourceDao resourceDao;
 
     public ResourceHandlerService(List<ResourceDefinitionSpi> resourceDefinitionSpiList,
                                   ResourceMemberDao resourceMemberDao,
                                   GroupDao groupDao,
                                   ResourceStorage resourceStorage,
                                   SMLIntegrationService integrationService,
-                                  DocumentVersionService documentVersionService, ResourceDao resourceDao) {
+                                  DocumentVersionService documentVersionService) {
         super(resourceDefinitionSpiList, resourceStorage);
         this.resourceMemberDao = resourceMemberDao;
         this.groupDao = groupDao;
         this.integrationService = integrationService;
         this.documentVersionService = documentVersionService;
-        this.resourceDao = resourceDao;
     }
 
     public void readResource(ResourceRequest resourceRequest,
@@ -178,9 +176,7 @@ public class ResourceHandlerService extends AbstractResourceHandler {
         if (isNewResource) {
             // associate owners to new resource
             owners.forEach(owner -> resourceMemberDao.setAdminMemberShip(owner, managedResource));
-
             if (managedResource.getGroup() == null) {
-
                 if (resolvedData.getGroup() != null) {
                     managedResource.setGroup(resolvedData.getGroup());
                 } else {
@@ -198,7 +194,6 @@ public class ResourceHandlerService extends AbstractResourceHandler {
                                   ResourceResponse resourceResponse) {
 
         LOG.debug("Handle the CREATE action for resource request [{}]", resourceRequest);
-
         // locate the resource handler
         ResolvedData resolvedData = resourceRequest.getResolvedData();
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceResolverService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceResolverService.java
index b1c08892925c2b52c7e4a9165add6f36bf6d24a7..80b4b30b5da009e04c3d6c2210e1476f70bbf87f 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceResolverService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceResolverService.java
@@ -34,6 +34,7 @@ import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.identifiers.Identifier;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
+import eu.europa.ec.edelivery.smp.security.DomainGroupGuard;
 import eu.europa.ec.edelivery.smp.security.ResourceGuard;
 import eu.europa.ec.edelivery.smp.services.ConfigurationService;
 import eu.europa.ec.edelivery.smp.services.IdentifierService;
@@ -44,6 +45,7 @@ import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
@@ -65,6 +67,7 @@ public class ResourceResolverService {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ResourceResolverService.class);
 
     final ResourceGuard resourceGuard;
+    final DomainGroupGuard domainGroupGuard;
     final ConfigurationService configurationService;
     final IdentifierService identifierService;
     final DomainDao domainDao;
@@ -76,6 +79,7 @@ public class ResourceResolverService {
 
 
     public ResourceResolverService(ResourceGuard resourceGuard,
+                                      DomainGroupGuard domainGroupGuard,
                                    ConfigurationService configurationService,
                                    IdentifierService identifierService,
                                    DomainDao domainDao,
@@ -94,6 +98,7 @@ public class ResourceResolverService {
         this.resourceDefinitionDao = resourceDefinitionDao;
         this.resourceDao = resourceDao;
         this.subresourceDao = subresourceDao;
+        this.domainGroupGuard = domainGroupGuard;
     }
 
     @Transactional
@@ -140,11 +145,22 @@ public class ResourceResolverService {
             }
             resource = createNewResource(resourceId, resourceDef, domain);
             // determine the group for the resource
-            DBGroup group = resolveResourceGroup(user.getUser(), domain,
+            DBGroup group = resolveAdminResourceGroup(user.getUser(), domain,
                     trimToNull(resourceRequest.getResourceGroupParameter()));
-
             resource.setVisibility(resourceRequest.getResourceVisibilityParameter());
             resource.setGroup(group);
+        } else {
+            // initially the GroupGuard checked for all groups on the domain
+            // but now recheck if the user is authorized for the group
+            if (!domainGroupGuard.isUserAuthorizedForGroup(Collections.singletonList(resource.getGroup()),
+                    user, resourceRequest.getAction())) {
+
+                LOG.warn(SECURITY_MARKER, "User [{}] is NOT authorized for action [{}] on group [{}] in domain [{}]",
+                        resourceRequest.getAction(),
+                        getUsername(user),
+                        resource.getGroup().getGroupName(), domain.getDomainCode());
+                throw new SMPRuntimeException(ErrorCode.UNAUTHORIZED);
+            }
         }
 
         locationVector.setResource(resource);
@@ -304,7 +320,7 @@ public class ResourceResolverService {
      * @return DBGroup for the given domain, user and group name.
      * @throws SMPRuntimeException if the user is not admin authorized to create the resource for the given group/domain
      */
-    protected DBGroup resolveResourceGroup(DBUser user, DBDomain domain, String domainGroup) {
+    protected DBGroup resolveAdminResourceGroup(DBUser user, DBDomain domain, String domainGroup) {
         LOG.debug("Resolve group for domain [{}] and user [{}] and group [{}]", domain.getDomainCode(),
                 user.getUsername(),
                 domainGroup);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceStorage.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceStorage.java
index f348d62c29b2ae4b7f319e4c3e2f2869c5ffea76..6d762d33a3661e5cea765f87ecf3e5bf10a29027 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceStorage.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/resource/ResourceStorage.java
@@ -63,71 +63,72 @@ public class ResourceStorage {
         this.documentVersionService = documentVersionService;
     }
 
+    /**
+     * Method returns the document content for the resource. If the document has
+     * reference to the document, the content of the document is returned
+     *
+     * @param dbResource resource
+     * @return document content
+     */
+    @Transactional
     public byte[] getDocumentContentForResource(DBResource dbResource) {
         LOG.debug("getDocumentContentForResource: [{}]", dbResource);
-        Optional<DBDocumentVersion> documentVersion = this.documentDao.getCurrentDocumentVersionForResource(dbResource);
-        return documentVersion.isPresent() ? documentVersion.get().getContent() : null;
+        DBDocument document = documentDao.getDocumentForResource(dbResource).orElseGet(null);
+        return getDocumentContent(document, true);
     }
 
-    public byte[] getDocumentContentForSubresource(DBSubresource subresource) {
-        LOG.debug("getDocumentContentForSubresource: [{}]", subresource);
-        Optional<DBDocumentVersion> documentVersion = documentDao.getCurrentDocumentVersionForSubresource(subresource);
+    public byte[] getDocumentContent(DBDocument document, boolean followReference) {
+        if (document == null) {
+            LOG.debug("Cam not get bytearray for null document");
+            return null;
+        }
+        DBDocument referenceDocument = document.getReferenceDocument();
+        if (followReference && referenceDocument != null) {
+            if (Boolean.TRUE.equals(referenceDocument.getSharingEnabled())) {
+                // target reference document can not be a reference (prevent cycling)
+                return getDocumentContent(referenceDocument, false);
+            }
+            LOG.warn("Content resolution: Document [{}] has reference document [{}] which is not shared!",document,  document.getReferenceDocument());
+        }
 
+        LOG.debug("getDocumentContent: [{}]", document);
+        Optional<DBDocumentVersion> documentVersion = documentDao.getCurrentDocumentVersionForDocument(document);
         return documentVersion.isPresent() ? documentVersion.get().getContent() : null;
     }
 
-
+    public byte[] getDocumentContentForSubresource(DBSubresource subresource) {
+        LOG.debug("getDocumentContentForSubresource: [{}]", subresource);
+        DBDocument document = documentDao.getDocumentForSubresource(subresource).orElseGet(null);
+        return getDocumentContent(document, true);
+    }
     @Transactional
-    public Map<String, Object> getResourceProperties(DBResource resource) {
+    public Map<String, String> getResourceProperties(DBResource resource) {
 
         DBDocument document = documentDao.getDocumentForResource(resource).orElseGet(null);
         if (document == null) {
             LOG.debug("Document not found for resource [{}]", resource);
             return Collections.emptyMap();
         }
-
-        Map<String, Object> documentProperties = new HashMap<>();
+        Map<String, String> documentProperties = getDocumentProperties(document, true);
+        // then overwrite with document properties
         documentProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_VALUE.getPropertyName(), resource.getIdentifierValue());
         if (resource.getIdentifierScheme() != null) {
             documentProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_SCHEME.getPropertyName(), resource.getIdentifierScheme());
         }
-        // add document properties
-        documentProperties.putAll(getDocumentProperties(document));
-        return documentProperties;
-    }
-
-    /**
-     * Method returns the 'transient' and custom document properties as map. If
-     * document is null, empty map is returned.
-     *
-     * @param document document
-     * @return document properties the key, value map
-     */
-    private Map<String, Object> getDocumentProperties(DBDocument document) {
-        if (document == null) {
-            return Collections.emptyMap();
-        }
-        Map<String, Object> documentProperties = new HashMap<>();
-        documentProperties.put(DOCUMENT_NAME.getPropertyName(), document.getName());
-        documentProperties.put(DOCUMENT_MIMETYPE.getPropertyName(), document.getMimeType());
-        documentProperties.put(DOCUMENT_VERSION.getPropertyName(), document.getCurrentVersion());
-
-        document.getDocumentProperties().forEach(property -> {
-            documentProperties.put(property.getProperty(), property.getValue());
-        });
         return documentProperties;
     }
 
     @Transactional
-    public Map<String, Object> getSubresourceProperties(DBResource resource, DBSubresource subresource) {
+    public Map<String, String> getSubresourceProperties(DBResource resource, DBSubresource subresource) {
 
-        Map<String, Object> documentProperties = new HashMap<>();
         DBDocument document = documentDao.getDocumentForSubresource(subresource).orElseGet(null);
         if (document == null) {
             LOG.debug("Document not found for subresource [{}]", resource);
             return Collections.emptyMap();
         }
-        // add identifiers
+
+        Map<String, String> documentProperties = getDocumentProperties(document, true);
+        // add resource and subresource properties
         documentProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_VALUE.getPropertyName(), resource.getIdentifierValue());
         if (resource.getIdentifierScheme() != null) {
             documentProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_SCHEME.getPropertyName(), resource.getIdentifierScheme());
@@ -136,9 +137,36 @@ public class ResourceStorage {
         if (subresource.getIdentifierScheme() != null) {
             documentProperties.put(SUBRESOURCE_IDENTIFIER_SCHEME.getPropertyName(), subresource.getIdentifierScheme());
         }
+        return documentProperties;
+    }
+
+    /**
+     * Method returns the 'transient' and custom document properties as map. If
+     * document is null, empty map is returned.
+     *
+     * @param document document
+     * @return document properties the key, value map
+     */
+    private Map<String, String> getDocumentProperties(DBDocument document, boolean followReference) {
+        if (document == null) {
+            return Collections.emptyMap();
+        }
 
-        // add document properties
-        documentProperties.putAll(getDocumentProperties(document));
+        Map<String, String> documentProperties = new HashMap<>();
+        DBDocument referenceDocument = document.getReferenceDocument();
+        if (followReference && referenceDocument != null) {
+            if (Boolean.TRUE.equals(referenceDocument.getSharingEnabled())) {
+                // target reference document can not be a reference (prevent cycling)
+                documentProperties.putAll(getDocumentProperties(referenceDocument, false));
+            }
+            LOG.warn("Property resolution: Document [{}] has reference document [{}] which is not shared!",document,  document.getReferenceDocument());
+        }
+        //add/overwrite with document properties
+        documentProperties.put(DOCUMENT_NAME.getPropertyName(), document.getName());
+        documentProperties.put(DOCUMENT_MIMETYPE.getPropertyName(), document.getMimeType());
+        documentProperties.put(DOCUMENT_VERSION.getPropertyName(), String.valueOf(document.getCurrentVersion()));
+        document.getDocumentProperties().forEach(property ->
+            documentProperties.put(property.getProperty(), property.getValue()));
         return documentProperties;
     }
 
@@ -173,7 +201,9 @@ public class ResourceStorage {
         document.getDocumentVersions().stream()
                 .filter(v -> v.getStatus() == DocumentVersionStatusType.PUBLISHED)
                 .forEach(v -> {v.setStatus(DocumentVersionStatusType.RETIRED);
-                    v.getDocumentVersionEvents().add(documentVersionService.createDocumentVersionEvent(DocumentVersionEventType.RETIRE, EventSourceType.REST_API, null));});
+                    v.getDocumentVersionEvents().add(documentVersionService.createDocumentVersionEvent(DocumentVersionEventType.RETIRE,
+                            DocumentVersionStatusType.RETIRED,
+                            EventSourceType.REST_API, null));});
         managedResource.getDocument().addNewDocumentVersion(version);
         return managedResource;
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentService.java
index 2401db31a256de099025d230b032387fe09b596c..aa5794db32df91cab09452598ccceabf299c650b 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentService.java
@@ -43,6 +43,7 @@ import eu.europa.ec.smp.spi.api.model.ResponseData;
 import eu.europa.ec.smp.spi.enums.TransientDocumentPropertyType;
 import eu.europa.ec.smp.spi.exceptions.ResourceException;
 import eu.europa.ec.smp.spi.resource.ResourceHandlerSpi;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.stereotype.Service;
@@ -51,18 +52,29 @@ import org.springframework.transaction.annotation.Transactional;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static eu.europa.ec.smp.spi.enums.TransientDocumentPropertyType.*;
 
+/**
+ * Service for handling document operations for the UI
+ *
+ * @author Joze RIHTARSIC
+ * @since 5.0
+ */
 @Service
 public class UIDocumentService {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDocumentService.class);
+    private static final List<DocumentVersionStatusType> REVIEW_STATUSES = Arrays.asList(DocumentVersionStatusType.UNDER_REVIEW, DocumentVersionStatusType.APPROVED, DocumentVersionStatusType.REJECTED);
+    public static final String DOCUMENT_VERSION_NOT_FOUND = "Document version not found";
+    public static final String DOCUMENT_VERSION_NOT_FOUND_TAG = "DocumentVersionNotFound";
+    public static final String DOCUMENT_ID_MISMATCH_TAG = "DocumentIdMismatch";
+    public static final String DOCUMENT_ID_MISMATCH = "Document id does not match the resource document id";
+
+
+
     final ResourceDao resourceDao;
     final SubresourceDao subresourceDao;
     final DocumentDao documentDao;
@@ -74,7 +86,8 @@ public class UIDocumentService {
                              SubresourceDao subresourceDao,
                              DocumentDao documentDao,
                              ResourceHandlerService resourceHandlerService,
-                             DocumentVersionService documentVersionService, ConversionService conversionService) {
+                             DocumentVersionService documentVersionService,
+                             ConversionService conversionService) {
         this.resourceDao = resourceDao;
         this.subresourceDao = subresourceDao;
         this.documentDao = documentDao;
@@ -111,11 +124,12 @@ public class UIDocumentService {
 
     @Transactional
     public DocumentRO publishDocumentVersionForResource(Long resourceId, Long documentId, int version) {
-        LOG.info("Publish Document For Resource [{}], version [{}]", resourceId, version);
+        LOG.info("Publish Document For Resource [{}], document [{}], version [{}]", resourceId, documentId, version);
         DBResource resource = resourceDao.find(resourceId);
         DBDocument document = resource.getDocument();
-        if (!Objects.equals(document.getId() ,documentId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentIdMismatch", "Document id does not match the resource document id");
+        if (!Objects.equals(document.getId(), documentId)) {
+            LOG.warn("Document id [{}] does not match the resource document id [{}]", documentId, document.getId());
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_ID_MISMATCH_TAG, DOCUMENT_ID_MISMATCH);
         }
         return publishDocumentVersion(document, version, resource.isReviewEnabled(), getInitialProperties(resource));
     }
@@ -127,8 +141,8 @@ public class UIDocumentService {
         DBSubresource subresource = subresourceDao.find(subresourceId);
         DBResource resource = resourceDao.find(resourceId);
         DBDocument document = subresource.getDocument();
-        if (!Objects.equals(document.getId() ,documentId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentIdMismatch", "Document id does not match the resource document id");
+        if (!Objects.equals(document.getId(), documentId)) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_ID_MISMATCH_TAG, DOCUMENT_ID_MISMATCH);
         }
         return publishDocumentVersion(document, version, resource.isReviewEnabled(), getInitialProperties(subresource));
     }
@@ -140,7 +154,7 @@ public class UIDocumentService {
                 .filter(dv -> dv.getVersion() == version)
                 .findFirst().orElse(null);
         if (documentVersion == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentVersionNotFound", "Document version not found");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_VERSION_NOT_FOUND_TAG, DOCUMENT_VERSION_NOT_FOUND);
         }
         if (isReviewEnabled && documentVersion.getStatus() != DocumentVersionStatusType.APPROVED) {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentVersionAlreadyPublished", "Document version has wrong status");
@@ -155,7 +169,7 @@ public class UIDocumentService {
                 .filter(dv -> dv.getStatus() == DocumentVersionStatusType.PUBLISHED)
                 .forEach(dv -> documentVersionService.retireDocumentVersion(dv, EventSourceType.UI, "Retire document version"));
         document.setCurrentVersion(documentVersion.getVersion());
-        documentVersionService.publishDocumentVersion(documentVersion, EventSourceType.UI);
+        documentVersionService.publishDocumentVersion(documentVersion, EventSourceType.UI, true);
         // return the document with the new version
         return convertWithVersion(document, version, initialProperties);
     }
@@ -165,8 +179,8 @@ public class UIDocumentService {
         LOG.info("Request review Document For Resource [{}], version [{}]", resourceId, version);
         DBResource resource = resourceDao.find(resourceId);
         DBDocument document = resource.getDocument();
-        if (!Objects.equals(document.getId() ,documentId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentIdMismatch", "Document id does not match the resource document id");
+        if (!Objects.equals(document.getId(), documentId)) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_ID_MISMATCH_TAG, DOCUMENT_ID_MISMATCH);
         }
         return requestReviewDocumentVersion(document, version, resource.isReviewEnabled(), getInitialProperties(resource));
     }
@@ -178,7 +192,7 @@ public class UIDocumentService {
         DBSubresource subresource = subresourceDao.find(subresourceId);
         DBDocument document = subresource.getDocument();
         if (!Objects.equals(document.getId(), documentId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentIdMismatch", "Document id does not match the resource document id");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_ID_MISMATCH_TAG, DOCUMENT_ID_MISMATCH);
         }
         return requestReviewDocumentVersion(document, version, resource.isReviewEnabled(), getInitialProperties(subresource));
     }
@@ -189,7 +203,7 @@ public class UIDocumentService {
                 .filter(dv -> dv.getVersion() == version)
                 .findFirst().orElse(null);
         if (documentVersion == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentVersionNotFound", "Document version not found");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_VERSION_NOT_FOUND_TAG, DOCUMENT_VERSION_NOT_FOUND);
         }
 
         if (!isReviewEnabled) {
@@ -218,7 +232,7 @@ public class UIDocumentService {
         DBResource resource = resourceDao.find(resourceId);
         DBDocument document = resource.getDocument();
         if (!Objects.equals(document.getId(), documentId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentIdMismatch", "Document id does not match the resource document id");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_ID_MISMATCH_TAG, DOCUMENT_ID_MISMATCH);
         }
         return reviewActionDocumentVersion(document, version, resource.isReviewEnabled(), action, message, getInitialProperties(resource));
     }
@@ -230,7 +244,7 @@ public class UIDocumentService {
         DBSubresource subresource = subresourceDao.find(subresourceId);
         DBDocument document = subresource.getDocument();
         if (!Objects.equals(document.getId(), documentId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentIdMismatch", "Document id does not match the subresource document id");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_ID_MISMATCH_TAG, "Document id does not match the subresource document id");
         }
         return reviewActionDocumentVersion(document, version, resource.isReviewEnabled(), action, message, getInitialProperties(subresource));
     }
@@ -246,7 +260,7 @@ public class UIDocumentService {
         DBDocumentVersion documentVersion = document.getDocumentVersions().stream()
                 .filter(dv -> dv.getVersion() == version)
                 .findFirst()
-                .orElseThrow(() -> new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentVersionNotFound", "Document version not found"));
+                .orElseThrow(() -> new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_VERSION_NOT_FOUND_TAG, DOCUMENT_VERSION_NOT_FOUND));
 
         if (!reviewEnabled) {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentReviewNotEnabled", "Document Review is not enabled for the document");
@@ -279,7 +293,7 @@ public class UIDocumentService {
 
         String genDoc = bos.toString();
         DocumentRO result = new DocumentRO();
-        result.setMetadata(new DocumentMetadataRO());
+        result.setDocumentConfiguration(new DocumentConfigurationRO());
         result.setPayload(genDoc);
         return result;
     }
@@ -339,7 +353,6 @@ public class UIDocumentService {
     }
 
 
-
     /**
      * Method persists the document property. If property has status DELETED removes the property from database
      * if property is UPDATED, the existing property entity is updated and if property is new then new property is
@@ -434,41 +447,34 @@ public class UIDocumentService {
     private DBDocumentVersion storeResourcePayload(DBResource resource, DBDocument document, DocumentRO documentRo) {
         DBDomainResourceDef domainResourceDef = resource.getDomainResourceDef();
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        byte[] payload = documentRo.getPayload().getBytes();
         // invoke the resource handler for the document type
         ResourceHandlerSpi resourceHandler = resourceHandlerService.getResourceHandler(
                 domainResourceDef.getResourceDef());
         RequestData data = resourceHandlerService.buildRequestDataForResource(domainResourceDef.getDomain(),
-                resource, new ByteArrayInputStream(documentRo.getPayload().getBytes()));
+                resource, new ByteArrayInputStream(payload));
+
         ResponseData responseData = new SpiResponseData(baos);
         try {
             resourceHandler.storeResource(data, responseData);
         } catch (ResourceException e) {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "StoreResourceValidation", ExceptionUtils.getRootCauseMessage(e));
         }
-        DBDocumentVersion documentVersion = null;
-        if (documentRo.getPayloadVersion() == null) {
-            documentVersion = createNewDocumentVersion(resource.isReviewEnabled(), document, baos.toByteArray());
-        } else {
-            documentVersion = document.getDocumentVersions().stream()
-                    .filter(dv -> dv.getVersion() == documentRo.getPayloadVersion())
-                    .findFirst().orElse(null);
-            if (documentVersion == null) {
-                throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentVersionNotFound", "Document version not found");
-            }
-            documentVersion.setContent(baos.toByteArray());
-        }
-        return documentVersion;
 
+        // create new version to document or update existing version
+        return documentRo.getPayloadVersion() == null ?
+                createNewDocumentVersion(document, payload) :
+                updatedDocumentVersion(document, payload, documentRo.getPayloadVersion());
     }
 
     private DBDocumentVersion storeSubresourcePayload(DBSubresource subresource, DBResource parentResource, DBDocument document, DocumentRO documentRo) {
 
         DBSubresourceDef subresourceDef = subresource.getSubresourceDef();
-
+        byte[] payload = documentRo.getPayload().getBytes();
         ResourceHandlerSpi resourceHandler = resourceHandlerService.getSubresourceHandler(subresourceDef, subresourceDef.getResourceDef());
         RequestData data = resourceHandlerService.buildRequestDataForSubResource(
                 parentResource.getDomainResourceDef().getDomain(), parentResource,
-                subresource, new ByteArrayInputStream(documentRo.getPayload().getBytes()));
+                subresource, new ByteArrayInputStream(payload));
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ResponseData responseData = new SpiResponseData(baos);
         try {
@@ -476,29 +482,42 @@ public class UIDocumentService {
         } catch (ResourceException e) {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "StoreSubresourceValidation", ExceptionUtils.getRootCauseMessage(e));
         }
+        // create new version to document or update existing version
+        return documentRo.getPayloadVersion() == null ?
+                createNewDocumentVersion(document, payload) :
+                updatedDocumentVersion(document, payload, documentRo.getPayloadVersion());
+    }
 
-        DBDocumentVersion documentVersion = null;
-        if (documentRo.getPayloadVersion() == null) {
-            documentVersion = createNewDocumentVersion(parentResource.isReviewEnabled(), document, baos.toByteArray());
-        } else {
-            documentVersion = document.getDocumentVersions().stream()
-                    .filter(dv -> dv.getVersion() == documentRo.getPayloadVersion())
-                    .findFirst().orElse(null);
-            if (documentVersion == null) {
-                throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentVersionNotFound", "Document version not found");
-            }
-            documentVersion.setContent(baos.toByteArray());
+    /**
+     * Method sets new payload to the existing documentVersion with the given version and loges the event to documentVersion
+     * event list. The method returns the updated document version.
+     *
+     * @param document document to update
+     * @param payload  new payload
+     * @param version  version of the document to update
+     */
+    protected DBDocumentVersion updatedDocumentVersion(DBDocument document, byte[] payload, int version) {
+        DBDocumentVersion documentVersion = document.getDocumentVersions().stream()
+                .filter(dv -> dv.getVersion() == version)
+                .findFirst().orElse(null);
+        if (documentVersion == null) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, DOCUMENT_VERSION_NOT_FOUND_TAG, DOCUMENT_VERSION_NOT_FOUND);
         }
-        return documentVersion;
+        documentVersion.setContent(payload);
 
+        DBDocumentVersionEvent event = documentVersionService.createDocumentVersionEvent(
+                DocumentVersionEventType.UPDATE, DocumentVersionStatusType.DRAFT, EventSourceType.UI, null);
+        documentVersion.addNewDocumentVersionEvent(event);
+        return documentVersion;
     }
 
-    public DBDocumentVersion createNewDocumentVersion(boolean isReviewEnabled, DBDocument document, byte[] payload) {
+    protected DBDocumentVersion createNewDocumentVersion(DBDocument document, byte[] payload) {
         // create new version to document
         int version = document.getDocumentVersions().stream().mapToInt(DBDocumentVersion::getVersion)
                 .max().orElse(0);
 
-        DBDocumentVersion documentVersion = documentVersionService.createDocumentVersionForCreate(EventSourceType.UI, "Create and publish resource by group admin", false);
+        DBDocumentVersion documentVersion = documentVersionService.createDocumentVersionForCreate(EventSourceType.UI,
+                "Create and publish resource by group admin", false);
         documentVersion.setVersion(version + 1);
         documentVersion.setDocument(document);
         documentVersion.setContent(payload);
@@ -506,32 +525,46 @@ public class UIDocumentService {
         // to get the current persist time
         documentVersion.prePersist();
         document.getDocumentVersions().add(0, documentVersion);
-        if (Boolean.FALSE.equals(isReviewEnabled)) {
-            document.setCurrentVersion(documentVersion.getVersion());
-        }
         return documentVersion;
     }
 
 
-
     @Transactional
-    public DocumentRO saveDocumentForResource(Long resourceId, DocumentRO documentRo, Long documentReference) {
+    public DocumentRO saveDocumentForResource(Long resourceId, DocumentRO documentRo) {
 
         final DBResource resource = resourceDao.find(resourceId);
         final DBDocument document = resource.getDocument();
+        return saveDocument(resource, null, document, documentRo);
+
+    }
+
+    /**
+     * Method saves the document for resource or  subresource. if the subresource is null then it is resource document
+     * otherwise it is subresource document.
+     *
+     * @param resource
+     * @param subresource
+     * @param document
+     * @param documentRo
+     * @return
+     */
+    public DocumentRO saveDocument(DBResource resource, DBSubresource subresource, DBDocument document, DocumentRO documentRo) {
+
         // check if the document is new or existing document. If payload version is not null then
         // return the current payload version otherwise return the current version
-        int returnDocVersion = documentRo.getPayloadVersion()!=null?
-                documentRo.getPayloadVersion():
+        int returnDocVersion = documentRo.getPayloadVersion() != null ?
+                documentRo.getPayloadVersion() :
                 document.getCurrentVersion();
 
         boolean isPayloadChanged = documentRo.getPayloadStatus() != EntityROStatus.PERSISTED.getStatusNumber();
         if (isPayloadChanged) {
-            LOG.debug("Store resource payload for resource [{}]", resource.getIdentifierValue());
-            DBDocumentVersion docVersion = storeResourcePayload(resource, document, documentRo);
+            LOG.debug("Store (sub) resource payload for resource [{}], subresource [{}]", resource, subresource);
+            DBDocumentVersion docVersion = subresource == null ?
+                    storeResourcePayload(resource, document, documentRo)
+                    : storeSubresourcePayload(subresource, resource, document, documentRo);
             returnDocVersion = docVersion.getVersion();
-        }
 
+        }
 
         if (isDocumentPropertiesChanged(documentRo)) {
             // persist non-transient properties
@@ -540,23 +573,50 @@ public class UIDocumentService {
                     .forEach(p -> persistDocumentProperty(p, document));
         }
 
-        DocumentMetadataRO documentMetadataRO =documentRo.getMetadata();
-        if (Boolean.TRUE.equals(documentMetadataRO.getSharingEnabled()) && documentReference!=null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentSharingNotAllowed", "Document sharing is not allowed for the document with reference document");
+        DocumentConfigurationRO docConfig = documentRo.getDocumentConfiguration();
+        if (docConfig != null) {
+
+            if (Boolean.TRUE.equals(docConfig.getSharingEnabled()) && StringUtils.isNotBlank(docConfig.getReferenceDocumentId())) {
+                throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentSharingNotAllowed", "Document sharing is not allowed for the document with reference document");
+            }
+            document.setSharingEnabled(docConfig.getSharingEnabled());
+            document.setName(docConfig.getName());
+
+            // update document reference
+            updateDocumentReferenceToDocument(document, docConfig);
         }
-        document.setSharingEnabled(documentMetadataRO.getSharingEnabled());
 
-        DBDocument documentReferenceEntity = null;
-        if (documentReference != null) {
-            if (Objects.equals(documentReference, document.getId())) {
+        List<DocumentPropertyRO> initialProperties = subresource == null ? getInitialProperties(resource) : getInitialProperties(subresource);
+        return convertWithVersion(document, returnDocVersion, initialProperties);
+    }
+
+    /**
+     * Method updates the document reference to the document.
+     *
+     * @param document                target document
+     * @param documentConfigurationRO document configuration from request
+     */
+    public void updateDocumentReferenceToDocument(DBDocument document, DocumentConfigurationRO documentConfigurationRO) {
+        if (documentConfigurationRO == null) {
+            return;
+        }
+        String referenceDocumentEncId = documentConfigurationRO.getReferenceDocumentId();
+        Long documentReferenceId = null;
+        if (StringUtils.isNotBlank(referenceDocumentEncId)) {
+            documentReferenceId = SessionSecurityUtils.decryptEntityId(referenceDocumentEncId);
+        }
+
+        if (documentReferenceId != null) {
+            if (Objects.equals(documentReferenceId, document.getId())) {
                 throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentReferenceNotAllowed", "Document reference cannot be the same as the document id");
             }
-            documentReferenceEntity = documentDao.find(documentReference);
+            DBDocument documentReferenceEntity = documentDao.find(documentReferenceId);
             if (documentReferenceEntity == null) {
                 throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentReferenceNotFound", "Document reference not found");
             }
 
-            if (documentReferenceEntity.getSharingEnabled() != null) {
+            // compare Boolean.TRUE to catch null values
+            if (!Boolean.TRUE.equals(documentReferenceEntity.getSharingEnabled())) {
                 throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentReferenceNotValid", "Can not reference to not shared document");
             }
 
@@ -564,10 +624,12 @@ public class UIDocumentService {
                 throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "DocumentReferenceNotValid", "Can not reference to a document that already has a reference");
             }
             document.setReferenceDocument(documentReferenceEntity);
+            LOG.info("Document [{}] is referencing to document [{}] and reference url [{}]", document.getId(), documentReferenceEntity.getId(), documentConfigurationRO.getReferenceDocumentUrl());
+            document.setReferenceDocumentUrl(documentConfigurationRO.getReferenceDocumentUrl());
         } else {
             document.setReferenceDocument(null);
+            document.setReferenceDocumentUrl(null);
         }
-        return convertWithVersion(document, returnDocVersion, getInitialProperties(resource));
     }
 
     @Transactional
@@ -576,21 +638,7 @@ public class UIDocumentService {
         DBResource parentResource = resourceDao.find(resourceId);
         DBSubresource entity = subresourceDao.find(subresource);
         DBDocument document = entity.getDocument();
-        DBSubresourceDef subresourceDef = entity.getSubresourceDef();
-        // check if the document is new or existing document. If payload version is not null then
-        // return the current payload version otherwise return the current version
-        int returnDocVersion = documentRo.getPayloadVersion()!=null?
-                documentRo.getPayloadVersion():
-                document.getCurrentVersion();
-
-        boolean isPayloadChanged = documentRo.getPayloadStatus() != EntityROStatus.PERSISTED.getStatusNumber();
-        if (isPayloadChanged) {
-            LOG.debug("Store  subresource payload for resource [{}]", entity.getIdentifierValue());
-            DBDocumentVersion docVersion = storeSubresourcePayload(entity, parentResource, document, documentRo);
-            returnDocVersion = docVersion.getVersion();
-        }
-
-        return convertWithVersion(document, returnDocVersion, getInitialProperties(entity));
+        return saveDocument(parentResource, entity, document, documentRo);
     }
 
     /**
@@ -615,6 +663,78 @@ public class UIDocumentService {
         return convertWithVersion(document, version, getInitialProperties(subresource));
     }
 
+
+    /**
+     * Method returns the list of reference documents for the given resource and filter paramters
+     *
+     * @param targetResourceId         resource id for which the reference documents are searched
+     * @param page                     page number
+     * @param pageSize                 page size
+     * @param searchResourceIdentifier
+     * @param searchResourceScheme
+     * @return
+     */
+    @Transactional
+    public ServiceResult<SearchReferenceDocumentRO> getSearchReferenceDocumentListForResource(Long targetResourceId, int page, int pageSize,
+                                                                                              String searchResourceIdentifier, String searchResourceScheme) {
+        DBResource targetResource = resourceDao.find(targetResourceId);
+        ServiceResult<SearchReferenceDocumentRO> result = new ServiceResult<>();
+        result.setPage(page);
+        result.setPageSize(pageSize);
+        Long count = documentDao.getSearchReferenceDocumentResourcesCount(targetResource, searchResourceIdentifier, searchResourceScheme);
+        if (count < 1) {
+            result.setCount(0L);
+            return result;
+        }
+        result.setCount(count);
+        List<SearchReferenceDocumentRO> refList = documentDao.getSearchReferenceDocumentResources(targetResource,
+                        searchResourceIdentifier, searchResourceScheme, page, pageSize).stream()
+                .map(doc -> conversionService.convert(doc, SearchReferenceDocumentRO.class))
+                .collect(Collectors.toList());
+        result.getServiceEntities().addAll(refList);
+        return result;
+    }
+
+    /**
+     * Method returns the list of reference documents for the given subresource and filter paramters by searchResourceIdentifier and searchResourceScheme
+     * and searchSubresourceIdentifier and searchSubresourceScheme.
+     *
+     * @param targetSubresourceId         the subresource id for which the reference documents are searched
+     * @param page                        the page index/number
+     * @param pageSize                    number of items per page
+     * @param searchResourceIdentifier    the partial identifier of the resource to search for
+     * @param searchResourceScheme        the partial scheme of the resource to search for
+     * @param searchSubresourceIdentifier the partial identifier of the subresource to search for
+     * @param searchSubresourceScheme     the partial scheme of the subresource to search for
+     * @return list of reference documents
+     */
+    @Transactional
+    public ServiceResult<SearchReferenceDocumentRO> getSearchReferenceDocumentListForSubresource(Long targetSubresourceId, Long resourceId, int page, int pageSize,
+                                                                                                 String searchResourceIdentifier, String searchResourceScheme,
+                                                                                                 String searchSubresourceIdentifier, String searchSubresourceScheme) {
+        DBSubresource targetResource = subresourceDao.find(targetSubresourceId);
+        if (!Objects.equals(targetResource.getResource().getId(), resourceId)) {
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "ResourceMismatch", "Resource id does not match the subresource resource id");
+        }
+        ServiceResult<SearchReferenceDocumentRO> result = new ServiceResult<>();
+        result.setPage(page);
+        result.setPageSize(pageSize);
+        Long count = documentDao.getSearchReferenceDocumentSubresourceCount(targetResource, searchResourceIdentifier,
+                searchResourceScheme, searchSubresourceIdentifier, searchSubresourceScheme);
+        if (count < 1) {
+            result.setCount(0L);
+            return result;
+        }
+        result.setCount(count);
+        List<SearchReferenceDocumentRO> refList = documentDao.getSearchReferenceDocumentSubresource(targetResource,
+                        searchResourceIdentifier, searchResourceScheme, searchSubresourceIdentifier, searchSubresourceScheme, page, pageSize).stream()
+                .map(doc -> conversionService.convert(doc, SearchReferenceDocumentRO.class))
+                .collect(Collectors.toList());
+        result.getServiceEntities().addAll(refList);
+        return result;
+    }
+
+
     private List<DocumentPropertyRO> getInitialProperties(DBResource resource) {
         List<DocumentPropertyRO> propertyROS = new ArrayList<>();
         propertyROS.add(new DocumentPropertyRO(RESOURCE_IDENTIFIER_VALUE.getPropertyName(),
@@ -635,23 +755,29 @@ public class UIDocumentService {
 
 
     public DocumentRO convertWithVersion(DBDocument document, int version, List<DocumentPropertyRO> initialProperties) {
-        DBDocumentVersion currentVersion = null;
-        DBDocumentVersion documentVersion = null;
-        for (DBDocumentVersion dv : document.getDocumentVersions()) {
-            if (dv.getVersion() == version) {
-                documentVersion = dv;
-            }
-            if (dv.getVersion() == document.getCurrentVersion()) {
-                currentVersion = dv;
-            }
-        }
-        documentVersion = documentVersion == null ? currentVersion : documentVersion;
-        if (documentVersion == null && !document.getDocumentVersions().isEmpty()) {
-            documentVersion = document.getDocumentVersions().get(document.getDocumentVersions().size() - 1);
-        }
+        DBDocumentVersion documentVersion = getDocumentVersionOrCurrentVersion(document, version);
         return convert(document, documentVersion, initialProperties);
     }
 
+    /**
+     * Method returns the documentVersion for the given version. If the version does not exist
+     * return the current version
+     *
+     * @param document with list of versions
+     * @param version  to get the document version
+     * @return documentVersion for the given version or current version
+     */
+    public DBDocumentVersion getDocumentVersionOrCurrentVersion(DBDocument document, int version) {
+        return document.getDocumentVersions().stream()
+                .filter(dv -> dv.getVersion() == version)
+                .findFirst()
+                .orElse(document.getDocumentVersions().stream()
+                        .filter(dv -> dv.getVersion() == document.getCurrentVersion())
+                        .findFirst()
+                        .orElse(document.getDocumentVersions().isEmpty()
+                                ? null : document.getDocumentVersions().get(document.getDocumentVersions().size() - 1)));
+    }
+
 
     /**
      * Convert DBDocument to DocumentRo with given document version
@@ -664,28 +790,33 @@ public class UIDocumentService {
     public DocumentRO convert(DBDocument document, DBDocumentVersion version, List<DocumentPropertyRO> initialProperties) {
         DocumentRO documentRo = new DocumentRO();
         documentRo.addProperty(DOCUMENT_NAME.getPropertyName(),
-                document.getName(), "Document Name", SMPPropertyTypeEnum.STRING, true);
+                document.getName(), DOCUMENT_MIMETYPE.getPropertyDescription(), SMPPropertyTypeEnum.STRING, true);
         documentRo.addProperty(DOCUMENT_MIMETYPE.getPropertyName(),
-                document.getMimeType(), "Document Mimetype", SMPPropertyTypeEnum.STRING, true);
+                document.getMimeType(), DOCUMENT_MIMETYPE.getPropertyDescription(), SMPPropertyTypeEnum.STRING, true);
         documentRo.getProperties().addAll(initialProperties);
 
-
-        DocumentMetadataRO metadataRo = new DocumentMetadataRO();
         documentRo.setDocumentId(SessionSecurityUtils.encryptedEntityId(document.getId()));
-        if (document.getReferenceDocument() != null) {
-            metadataRo.setReferenceDocumentId(SessionSecurityUtils.encryptedEntityId(document.getReferenceDocument().getId()));
-        }
-        metadataRo.setSharingEnabled(document.getSharingEnabled());
-        metadataRo.setMimeType(document.getMimeType());
-        metadataRo.setPublishedVersion(document.getCurrentVersion());
-        metadataRo.setName(document.getName());
+        DocumentConfigurationRO docConfigRo = new DocumentConfigurationRO();
+        DBDocument reference = document.getReferenceDocument();
+        if (reference != null) {
+            docConfigRo.setReferenceDocumentId(SessionSecurityUtils.encryptedEntityId(reference.getId()));
+            docConfigRo.setReferenceDocumentName(reference.getName());
+            docConfigRo.setReferenceDocumentUrl(document.getReferenceDocumentUrl());
+            docConfigRo.setReferenceDocumentAccessible(Boolean.TRUE.equals(reference.getSharingEnabled()));
+            // allways get default version for referenced document
+            DBDocumentVersion referencedVersion = getDocumentVersionOrCurrentVersion(document.getReferenceDocument(), -1);
+            documentRo.setReferencePayload(new String(referencedVersion.getContent()));
+        }
+
+        docConfigRo.setSharingEnabled(document.getSharingEnabled());
+        docConfigRo.setMimeType(document.getMimeType());
+        docConfigRo.setPublishedVersion(document.getCurrentVersion());
+        docConfigRo.setName(document.getName());
         // set list of versions
-        document.getDocumentVersions().forEach(dv -> {
-            metadataRo.getAllVersions().add(dv.getVersion());
-        });
-        documentRo.setMetadata(metadataRo);
+        document.getDocumentVersions().forEach(dv ->
+            docConfigRo.getAllVersions().add(dv.getVersion()));
+        documentRo.setDocumentConfiguration(docConfigRo);
 
-        // TODO remove duplicate properties use only metadataRo
         document.getDocumentVersions().forEach(dv -> {
             documentRo.getAllVersions().add(dv.getVersion());
             documentRo.getDocumentVersions().add(conversionService.convert(dv, DocumentVersionRO.class));
@@ -703,7 +834,7 @@ public class UIDocumentService {
                     LOG.info("Document property [{}] added to document [{}]", p);
                 });
 
-        metadataRo.setMimeType(document.getMimeType());
+        docConfigRo.setMimeType(document.getMimeType());
 
         if (version != null) {
             documentRo.setPayloadCreatedOn(version.getCreatedOn());
@@ -711,50 +842,48 @@ public class UIDocumentService {
             documentRo.setPayload(new String(version.getContent()));
             documentRo.setDocumentVersionStatus(version.getStatus());
             // set ven
-            version.getDocumentVersionEvents().stream().forEach(e -> {
-                DocumentVersionEventRO eventRo = new DocumentVersionEventRO();
-                eventRo.setEventType(e.getEventType());
-                eventRo.setEventOn(e.getEventOn());
-                eventRo.setUsername(e.getUsername());
-                eventRo.setEventSourceType(e.getEventSourceType());
-                eventRo.setDetails(e.getDetails());
-                documentRo.addDocumentVersionEvent(eventRo);
-            });
+            version.getDocumentVersionEvents().stream().forEach(e ->
+                    documentRo.addDocumentVersionEvent(
+                            conversionService.convert(e, DocumentVersionEventRO.class))
+            );
         }
-
         return documentRo;
     }
 
+    /**
+     * Method validates all document versions and updates version in review process
+     * to NON REVIEW status. The change is logged as new event on version list.
+     *
+     * @param document
+     */
+    public void updateToNonReviewStatuses(DBDocument document) {
+        updateDocumentVersionStatus(document, DocumentVersionEventType.SETTINGS_CHANGE,
+                REVIEW_STATUSES,
+                DocumentVersionStatusType.DRAFT);
+    }
 
-    public ServiceResult<ReviewDocumentVersionRO> getDocumentReviewListForUser(
-            Long userId,
-            int page, int pageSize,
-            String sortField,
-            String sortOrder, Object filter) {
-
-        ServiceResult<ReviewDocumentVersionRO> sg = new ServiceResult<>();
-        sg.setPage(page < 0 ? 0 : page);
-        List<DBReviewDocumentVersion> listTask = documentDao.getDocumentReviewListForUser(userId);
-        long iCnt = listTask.size();
-
-        if (pageSize < 0) { // if page size iz -1 return all results and set pageSize to maxCount
-            pageSize = (int) iCnt;
-        }
-        sg.setPageSize(pageSize);
-        sg.setCount(iCnt);
-
-        if (iCnt > 0) {
-            int iStartIndex = pageSize < 0 ? -1 : page * pageSize;
-            if (iStartIndex >= iCnt && page > 0) {
-                page = page - 1;
-                sg.setPage(page); // go back for a page
-                iStartIndex = pageSize < 0 ? -1 : page * pageSize;
+    /*
+     * Method updates the document version status for the given document. The method updates the status for all
+     * document versions that have the old status. The change is logged as new event on version list.
+     */
+    private void updateDocumentVersionStatus(DBDocument document, DocumentVersionEventType eventType,
+                                             List<DocumentVersionStatusType> oldStatus,
+                                             DocumentVersionStatusType newStatus) {
+        if (document == null) {
+            LOG.debug("DBDocument  is null, cannot update document version status");
+            return;
+        }
+        List<DBDocumentVersion> documentVersions = document.getDocumentVersions();
+        documentVersions.forEach(version -> {
+            if (oldStatus.contains(version.getStatus())) {
+                DBDocumentVersionEvent docEvent = documentVersionService.createDocumentVersionEvent(eventType,
+                        newStatus,
+                        EventSourceType.UI,
+                        null);
+                version.addNewDocumentVersionEvent(docEvent);
+                version.setStatus(newStatus);
             }
-        }
-
-        List<ReviewDocumentVersionRO> result = listTask.stream().map(resource -> conversionService.convert(resource, ReviewDocumentVersionRO.class))
-                .collect(Collectors.toList());
-        sg.getServiceEntities().addAll(result);
-        return sg;
+        });
     }
+
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainAdminService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainAdminService.java
index cbe6ffc578069cd1e58ffcf2bb295fb9ef08607f..c2048e8b1e647c683587fce700b2aafbfee00e1b 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainAdminService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainAdminService.java
@@ -57,6 +57,7 @@ import java.util.stream.Collectors;
 public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainAdminService.class);
+    public static final String DOMAIN_DOES_NOT_EXIST_IN_DATABASE = "Domain does not exist in database!";
 
     private final DomainDao domainDao;
     private final DomainConfigurationDao domainConfigurationDao;
@@ -65,7 +66,6 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
     private final ResourceDefDao resourceDefDao;
     private final DomainResourceDefDao domainResourceDefDao;
     private final ConversionService conversionService;
-    private final GroupDao groupDao;
     private final GroupMemberDao groupMemberDao;
     private final SMLIntegrationService smlIntegrationService;
 
@@ -76,7 +76,6 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
                                 ResourceDao resourceDao,
                                 ResourceDefDao resourceDefDao,
                                 DomainResourceDefDao domainResourceDefDao,
-                                GroupDao groupDao,
                                 GroupMemberDao groupMemberDao,
                                 SMLIntegrationService smlIntegrationService) {
         this.conversionService = conversionService;
@@ -86,7 +85,6 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
         this.resourceDefDao = resourceDefDao;
         this.domainResourceDefDao = domainResourceDefDao;
         this.domainMemberDao = domainMemberDao;
-        this.groupDao = groupDao;
         this.groupMemberDao = groupMemberDao;
         this.smlIntegrationService = smlIntegrationService;
     }
@@ -146,14 +144,13 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
      *
      * @param domainId
      * @param data
-     * @return
      */
     @Transactional
     public void updateBasicDomainData(Long domainId, DomainRO data) {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
             LOG.warn("Can not update domain for ID [{}], because it does not exists!", domainId);
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         domain.setDomainCode(data.getDomainCode());
         domain.setDefaultResourceTypeIdentifier(data.getDefaultResourceTypeIdentifier());
@@ -165,7 +162,7 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
     public void updateDomainSmlIntegrationData(Long domainId, DomainRO data) {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         if (domain.isSmlRegistered() && !StringUtils.equals(data.getSmlSmpId(), domain.getSmlSmpId())) {
             String msg = "SMP-SML identifier must not change for registered domain [" + domain.getDomainCode() + "]!";
@@ -196,7 +193,7 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
         LOG.info("add resources: [{}]", resourceDefIds);
         if (domain == null) {
             LOG.warn("Can not delete domain for ID [{}], because it does not exists!", domainId);
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND,DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
 
         //filter and validate resources to be removed
@@ -239,7 +236,7 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
     public List<DomainPropertyRO> getDomainProperties(Long domainId) {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND,DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         return domainConfigurationDao.getDomainPropertiesForRole(domain, SMPRole.SYSTEM_ADMIN).stream()
                 .map(domainConfiguration -> conversionService.convert(domainConfiguration, DomainPropertyRO.class))
@@ -250,7 +247,7 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
     public List<DomainPropertyRO> updateDomainProperties(Long domainId, List<DomainPropertyRO> domainProperties) {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         return domainConfigurationDao.updateDomainPropertiesForRole(domain, domainProperties, SMPRole.SYSTEM_ADMIN)
         .stream()
@@ -275,7 +272,7 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
             LOG.warn("Can not delete domain for ID [{}], because it does not exists!", domainId);
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         if (domain.isSmlRegistered()) {
             LOG.info("Can not delete domain for ID [{}], is registered to SML!", domainId);
@@ -294,10 +291,10 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
             domainMemberDao.remove(member);
         }
         // delete all groups
-        List<DBGroup> groupList = domain.getDomainGroups();
+        List<DBGroup> groupList = Collections.unmodifiableList(domain.getDomainGroups());
         for (DBGroup group : groupList) {
             // all groups should be without resources see the check above:  getResourceCountForDomain
-            deleteDomainGroup(group);
+            deleteGroupMembers(group);
         }
         // finally remove the domain
         domainDao.remove(domain);
@@ -306,11 +303,10 @@ public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
         return domainRO;
     }
 
-    private void deleteDomainGroup(DBGroup group) {
+    private void deleteGroupMembers(DBGroup group) {
         List<DBGroupMember> memberList = groupMemberDao.getGroupMembers(group.getId(), -1, -1, null);
         for (DBGroupMember member : memberList) {
             groupMemberDao.remove(member);
         }
-        groupDao.remove(group);
     }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainEditService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainEditService.java
index d2bfbec09cf3adefdc3e4b45512029ed0409f41e..48de159a15bea51c0386ab4172e054debc92c2fb 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainEditService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainEditService.java
@@ -18,6 +18,7 @@
  */
 package eu.europa.ec.edelivery.smp.services.ui;
 
+import eu.europa.ec.edelivery.smp.auth.SMPUserDetails;
 import 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;
@@ -32,6 +33,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 eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.springframework.core.convert.ConversionService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -51,6 +53,7 @@ import java.util.stream.Collectors;
 public class UIDomainEditService extends UIServiceBase<DBDomain, DomainPublicRO> {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainEditService.class);
+    public static final String DOMAIN_DOES_NOT_EXIST_IN_DATABASE = "Domain does not exist in database!";
     private final DomainDao domainDao;
     private final DomainConfigurationDao domainConfigurationDao;
     private final DomainMemberDao domainMemberDao;
@@ -91,6 +94,35 @@ public class UIDomainEditService extends UIServiceBase<DBDomain, DomainPublicRO>
         return super.getTableList(page, pageSize, sortField, sortOrder, filter);
     }
 
+
+    /**
+     * Method returns only domains  current users have access to.
+     *
+     * @param page      - page number
+     * @param pageSize  - page size
+     * @return ServiceResult<DomainPublicRO> - list of domain resource objects
+     */
+    public ServiceResult<DomainPublicRO> getUserPermittedDomains(int page, int pageSize) {
+        LOG.debug("Query for public domain data: page: [{}], page size [{}].", page, pageSize);
+        SMPUserDetails userDetails = SessionSecurityUtils.getSessionUserDetails();
+        DBUser user = userDetails!=null?userDetails.getUser():null;
+
+        ServiceResult<DomainPublicRO> result = new ServiceResult<>();
+        result.setPage(page);
+        result.setPageSize(pageSize);
+        Long count = domainDao.getAllDomainsForUserCount(user);
+        if (count < 1) {
+            result.setCount(0L);
+            return result;
+        }
+        result.setCount(count);
+        List<DomainPublicRO> refList = domainDao.getAllDomainsForUser(user, page, pageSize).stream()
+                .map(doc -> conversionService.convert(doc, DomainPublicRO.class))
+                .collect(Collectors.toList());
+        result.getServiceEntities().addAll(refList);
+        return result;
+    }
+
     @Transactional
     public List<DomainRO> getAllDomainsForDomainAdminUser(Long userId) {
         List<DBDomain> domains = domainDao.getDomainsByUserIdAndDomainRoles(userId, MembershipRoleType.ADMIN);
@@ -171,7 +203,7 @@ public class UIDomainEditService extends UIServiceBase<DBDomain, DomainPublicRO>
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
             LOG.warn("Can not get domain for ID [{}], because it does not exists!", domainId);
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
 
         //filter and validate resources to be removed
@@ -189,7 +221,7 @@ public class UIDomainEditService extends UIServiceBase<DBDomain, DomainPublicRO>
     public List<DomainPropertyRO> getDomainEditProperties(Long domainId) {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         return domainConfigurationDao.getDomainPropertiesForRole(domain, SMPRole.USER).stream()
                 .map(property -> conversionService.convert(property, DomainPropertyRO.class))
@@ -207,7 +239,7 @@ public class UIDomainEditService extends UIServiceBase<DBDomain, DomainPublicRO>
     public List<DomainPropertyRO> updateDomainEditProperties(Long domainId, List<DomainPropertyRO> domainProperties) {
         DBDomain domain = domainDao.find(domainId);
         if (domain == null) {
-            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
+            throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, DOMAIN_DOES_NOT_EXIST_IN_DATABASE);
         }
         return domainConfigurationDao.updateDomainPropertiesForRole(domain, domainProperties, SMPRole.USER).stream()
                 .map(property -> conversionService.convert(property, DomainPropertyRO.class))
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java
index 44be22aa37259580cb71975b934e6ebcb1bf9332..b38234ae00ef00821d750c31137cd99403214705 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchService.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -18,7 +18,12 @@
  */
 package eu.europa.ec.edelivery.smp.services.ui;
 
-import eu.europa.ec.edelivery.smp.data.dao.*;
+import eu.europa.ec.edelivery.smp.auth.SMPUserDetails;
+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.ResourceDao;
+import eu.europa.ec.edelivery.smp.data.dao.ResourceDefDao;
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
 import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
@@ -30,7 +35,6 @@ import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.filters.ResourceFilter;
 import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
-import org.springframework.core.convert.ConversionService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -46,18 +50,12 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr
 
     private final ResourceDao resourceDao;
 
-    private final UserDao userDao;
-
     private final ResourceDefDao resourceDefDao;
 
-    private final ConversionService conversionService;
-
-    public UIResourceSearchService(DomainDao domainDao, ResourceDao resourceDao, UserDao userDao, ResourceDefDao resourceDefDao, ConversionService conversionService) {
+    public UIResourceSearchService(DomainDao domainDao, ResourceDao resourceDao, ResourceDefDao resourceDefDao) {
         this.domainDao = domainDao;
         this.resourceDao = resourceDao;
-        this.userDao = userDao;
         this.resourceDefDao = resourceDefDao;
-        this.conversionService = conversionService;
     }
 
 
@@ -77,16 +75,16 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr
      * @return
      */
     @Transactional
-    public ServiceResult<ServiceGroupSearchRO> getTableList(int page, int pageSize,
-                                                            String sortField,
-                                                            String sortOrder, ResourceFilter filter) {
-
+    public ServiceResult<ServiceGroupSearchRO> getTableList(int page, int pageSize, String sortField, String sortOrder, ResourceFilter filter) {
+        LOG.debug("Get table list for page: [{}], page size: [{}], sort field: [{}], sort order: [{}], filter: [{}]", page, pageSize, sortField, sortOrder, filter);
         ServiceResult<ServiceGroupSearchRO> sg = new ServiceResult<>();
         sg.setPage(page < 0 ? 0 : page);
         sg.setPageSize(pageSize);
-        DBUser user = SessionSecurityUtils.getSessionUserDetails() != null ? SessionSecurityUtils.getSessionUserDetails().getUser() : null;
+        DBUser user = SessionSecurityUtils.getSessionUserDetails() != null ?
+                SessionSecurityUtils.getSessionUserDetails().getUser() : null;
 
-        long iCnt = resourceDao.getPublicResourcesSearchCount(user, filter.getIdentifierSchemeLike(), filter.getIdentifierValueLike(), filter.getDomainCode(), filter.getDocumentType());
+        long iCnt = resourceDao.getPublicResourcesSearchCount(user, filter.getIdentifierSchemeLike(),
+                filter.getIdentifierValueLike(), filter.getDomainCode(), filter.getDocumentType());
         sg.setCount(iCnt);
 
         if (iCnt > 0) {
@@ -111,7 +109,7 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr
     /**
      * Convert Database object to Rest object for UI
      *
-     * @param resource     - database entity wrapper
+     * @param resource - database entity wrapper
      * @return ServiceGroupRO
      */
     private ServiceGroupSearchRO convert(ResourceDao.DBResourceWrapper resource) {
@@ -136,8 +134,12 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr
     }
 
     public ResourceFilterOptionsResult getResourceMetadata() {
-        List<String> domainCodes = domainDao.getAllDomainCodes();
-        List<String> documentTypes = resourceDefDao.getAllResourceDef().stream().map(DBResourceDef::getName).collect(Collectors.toList());
+        SMPUserDetails userDetails = SessionSecurityUtils.getSessionUserDetails();
+        DBUser user = userDetails != null ? userDetails.getUser() : null;
+        List<String> domainCodes = domainDao.getAllDomainsForUser(user, -1, -1)
+                .stream().map(DBDomain::getDomainCode).collect(Collectors.toList());
+        List<String> documentTypes = resourceDefDao.getAllResourceDefsForUser(user, -1, -1)
+                .stream().map(DBResourceDef::getName).collect(Collectors.toList());
         return new ResourceFilterOptionsResult(domainCodes, documentTypes);
     }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java
index 7441f3305774c621f2fefda9d43af6ac7ea2bee4..66f218822763248d09989295785298a1b1f4287f 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java
@@ -69,6 +69,8 @@ public class UIResourceService {
     private static final String ACTION_RESOURCE_UPDATE = "UpdateResource";
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIResourceService.class);
+    public static final String GROUP_DOES_NOT_EXIST = "Group does not exist!";
+    public static final String GROUP_DOES_NOT_BELONG_TO_THE_GIVEN_DOMAIN = "Group does not belong to the given domain!";
 
 
     private final ResourceDao resourceDao;
@@ -110,7 +112,7 @@ public class UIResourceService {
 
         DBGroup group = groupDao.find(groupId);
         if (group == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_LIST, "Group does not exist!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_LIST, GROUP_DOES_NOT_EXIST);
         }
 
         DBResourceFilter filter = DBResourceFilter.createBuilder()
@@ -141,7 +143,7 @@ public class UIResourceService {
 
         DBGroup group = groupDao.find(groupId);
         if (group == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_LIST, "Group does not exist!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_LIST, GROUP_DOES_NOT_EXIST);
         }
         DBUser user = userDao.find(userId);
         if (user == null) {
@@ -182,7 +184,7 @@ public class UIResourceService {
             throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_DELETE, "Resource does not belong to the group!");
         }
         if (!Objects.equals(resource.getGroup().getDomain().getId(), domainId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_DELETE, "Group does not belong to the given domain!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_DELETE, GROUP_DOES_NOT_BELONG_TO_THE_GIVEN_DOMAIN);
         }
         DBDomain resourceDomain = resource.getGroup().getDomain();
         if (smlIntegrationService.isSMLIntegrationEnabled() &&
@@ -199,12 +201,12 @@ public class UIResourceService {
 
         DBGroup group = groupDao.find(groupId);
         if (group == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_CREATE, "Group does not exist!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_CREATE, GROUP_DOES_NOT_EXIST);
         }
 
         DBDomain domain = group.getDomain();
         if (!Objects.equals(domain.getId(), domainId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_CREATE, "Group does not belong to the given domain!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_CREATE, GROUP_DOES_NOT_BELONG_TO_THE_GIVEN_DOMAIN);
         }
 
         Optional<DBResourceDef> optRedef = resourceDefDao.getResourceDefByIdentifier(resourceRO.getResourceTypeIdentifier());
@@ -230,6 +232,7 @@ public class UIResourceService {
         resource.setIdentifierScheme(resourceIdentifier.getScheme());
         resource.setIdentifierValue(resourceIdentifier.getValue());
         resource.setVisibility(resourceRO.getVisibility());
+        resource.setReviewEnabled(resourceRO.isReviewEnabled());
         resource.setGroup(group);
         resource.setDomainResourceDef(optDoredef.get());
         resource.setReviewEnabled(resourceRO.isReviewEnabled());
@@ -268,11 +271,11 @@ public class UIResourceService {
 
         DBGroup group = groupDao.find(groupId);
         if (group == null) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_UPDATE, "Group does not exist!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_UPDATE, GROUP_DOES_NOT_EXIST);
         }
 
         if (!Objects.equals(group.getDomain().getId(), domainId)) {
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_UPDATE, "Group does not belong to the given domain!");
+            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_UPDATE, GROUP_DOES_NOT_BELONG_TO_THE_GIVEN_DOMAIN);
         }
 
         Optional<DBResourceDef> optRedef = resourceDefDao.getResourceDefByIdentifier(resourceRO.getResourceTypeIdentifier());
@@ -290,9 +293,26 @@ public class UIResourceService {
         DBResource resource = resourceDao.find(resourceId);
         resource.setVisibility(resourceRO.getVisibility());
         if (resourceRO.isReviewEnabled() != null) {
+            Boolean newValue = isTrue(resourceRO.isReviewEnabled());
+            Boolean oldValue = isTrue(resource.isReviewEnabled());
+            // update resource review enabled in case if it was null before
+            resource.setReviewEnabled(newValue);
+            // check if new status is disabled  and changed
+            if (oldValue != newValue && !newValue) {
+                // update all document versions to non review status
+                uiDocumentService.updateToNonReviewStatuses(resource.getDocument());
+                // update statuses for all subresources
+                resource.getSubresources().stream().forEach(subResource ->
+                    uiDocumentService.updateToNonReviewStatuses(subResource.getDocument()));
+            }
             resource.setReviewEnabled(isTrue(resourceRO.isReviewEnabled()));
         }
-        return conversionService.convert(resource, ResourceRO.class);
+        ResourceRO resourceROResult = conversionService.convert(resource, ResourceRO.class);
+        if (StringUtils.isNotBlank(resourceRO.getResourceId())) {
+            // return the same encrypted id so the UI can use update old resource
+            resourceROResult.setResourceId(resourceRO.getResourceId());
+        }
+        return resourceROResult;
     }
 
     @Transactional
@@ -389,7 +409,6 @@ public class UIResourceService {
         DBResourceDef domainResourceDef = resource.getDomainResourceDef().getResourceDef();
         DBDocument document = new DBDocument();
 
-        document.setCurrentVersion(1);
         document.setMimeType(domainResourceDef.getMimeType());
         document.setName(domainResourceDef.getName());
         // create first version of the document
@@ -398,6 +417,7 @@ public class UIResourceService {
         version.setStatus(DocumentVersionStatusType.PUBLISHED);
         version.setDocument(document);
         version.setVersion(1);
+        document.setCurrentVersion(1);
         // generate document content
         document.addNewDocumentVersion(version);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
@@ -405,5 +425,4 @@ public class UIResourceService {
         version.setContent(baos.toByteArray());
         return document;
     }
-
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIReviewService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIReviewService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3b0fc38f84a4a43f56a364cf39a7012d12aa0ec
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIReviewService.java
@@ -0,0 +1,66 @@
+package eu.europa.ec.edelivery.smp.services.ui;
+
+import eu.europa.ec.edelivery.smp.data.dao.DocumentDao;
+import eu.europa.ec.edelivery.smp.data.model.doc.DBReviewDocumentVersionMapping;
+import eu.europa.ec.edelivery.smp.data.ui.ReviewDocumentVersionRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * This class is used to provide the UI Document Review Services.
+ *
+ * @since 5.1
+ * @author Joze RIHTARSIC
+ */
+@Service
+public class UIReviewService {
+
+
+    private DocumentDao documentDao;
+    private ConversionService conversionService;
+    public UIReviewService(DocumentDao documentDao, ConversionService conversionService) {
+        this.documentDao = documentDao;
+        this.conversionService = conversionService;
+    }
+
+
+    /**
+     * Method returns Users list of review tasks. To access the list user must be logged in.
+     *
+     * @param userId
+     * @param page
+     * @param pageSize
+     * @param sortField
+     * @param sortOrder
+     * @param filter
+     * @return
+     */
+    public ServiceResult<ReviewDocumentVersionRO> getDocumentReviewListForUser(
+            Long userId,
+            int page, int pageSize,
+            String sortField,
+            String sortOrder, Object filter) {
+
+        ServiceResult<ReviewDocumentVersionRO> sg = new ServiceResult<>();
+        long iCnt = documentDao.getDocumentReviewListForUserCount(userId);
+
+        sg.setPage(page < 0 ? 0 : page);
+        if (pageSize < 0) { // if page size iz -1 return all results and set pageSize to maxCount
+            pageSize = (int) iCnt;
+        }
+        sg.setPageSize(pageSize);
+        sg.setCount(iCnt);
+
+        if (iCnt > 0) {
+            List<DBReviewDocumentVersionMapping> listTask = documentDao.getDocumentReviewListForUser(userId, page, pageSize);
+            List<ReviewDocumentVersionRO> result = listTask.stream().map(resource -> conversionService.convert(resource, ReviewDocumentVersionRO.class))
+                    .collect(Collectors.toList());
+            sg.getServiceEntities().addAll(result);
+        }
+        return sg;
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
index 60ce2a0ad12116b6de94e7089ff53cff82798678..84a66481321d1569663c218749cd87b0f6f21431 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -52,15 +52,12 @@ import java.io.*;
 import java.security.*;
 import java.security.cert.Certificate;
 import java.security.cert.*;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.regex.Pattern;
 
 import static eu.europa.ec.edelivery.smp.logging.SMPMessageCode.SEC_TRUSTSTORE_CERT_INVALID;
 import static eu.europa.ec.edelivery.smp.logging.SMPMessageCode.SEC_USER_CERT_INVALID;
 import static java.util.Collections.list;
-import static java.util.Locale.US;
 
 /**
  * @author Joze Rihtarsic
@@ -179,7 +176,8 @@ public class UITruststoreService extends BasicKeystoreService {
     protected void validateAndLogError(X509Certificate x509Certificate, String alias) {
         try {
             x509Certificate.checkValidity();
-        } catch (CertificateExpiredException | CertificateNotYetValidException ex) {
+        } catch (CertificateExpiredException |
+                 CertificateNotYetValidException ex) {
             LOG.securityWarn(SEC_TRUSTSTORE_CERT_INVALID, alias, ExceptionUtils.getRootCauseMessage(ex));
         }
     }
@@ -204,7 +202,7 @@ public class UITruststoreService extends BasicKeystoreService {
         X509Certificate cert;
         CertificateRO cro;
 
-        if (buff ==null || buff.length ==0){
+        if (buff == null || buff.length == 0) {
             cro = new CertificateRO();
             cro.setError(true);
             cro.setInvalid(true);
@@ -229,6 +227,7 @@ public class UITruststoreService extends BasicKeystoreService {
         }
         return cro;
     }
+
     public void validateCertificate(X509Certificate cert, CertificateRO cro) {
         validateCertificate(cert, cro, true);
     }
@@ -261,7 +260,7 @@ public class UITruststoreService extends BasicKeystoreService {
             cro.setInvalidReason(CERT_ERROR_MSG_ALREADY_IN_USE);
             // can not register it twice
             cro.setError(true);
-        }  catch (CertificateException e) {
+        } catch (CertificateException e) {
             LOG.securityError(SEC_USER_CERT_INVALID, e, cro.getCertificateId(), e.getMessage());
             if (ExceptionUtils.getRootCause(e) instanceof CertPathValidatorException) {
                 cro.setInvalidReason("Certificate is not trusted! Invalid certificate policy path!");
@@ -277,23 +276,20 @@ public class UITruststoreService extends BasicKeystoreService {
         if (x509Certificate == null) {
             throw new CertificateException("The X509Certificate is null (Is the client cert header enabled?)! Skip trust validation against the truststore!");
         }
+        Pattern subjectRegExp = configurationService.getCertificateSubjectRegularExpression();
+        List<String> allowedCertificatePolicies = configurationService.getAllowedCertificatePolicies();
         KeyStore truststore = getTrustStore();
-        if (truststore == null) {
-            LOG.warn("Truststore is not configured! Skip trust validation against the truststore!");
-            return;
-        }
 
         try {
-            if (truststore.size() == 0) {
-                LOG.warn("Truststore is empty! Skip trust validation against the truststore!");
+            if (truststore == null || truststore.size() == 0) {
+                LOG.warn("Truststore is empty! only basic validation is executed!");
+                X509CertificateUtils.basicCertificateValidation(x509Certificate, subjectRegExp, allowedCertificatePolicies);
                 return;
             }
         } catch (KeyStoreException e) {
             throw new CertificateException("Error occurred when reading the truststore!", e);
         }
 
-        Pattern subjectRegExp = configurationService.getCertificateSubjectRegularExpression();
-        List<String> allowedCertificatePolicies = configurationService.getAllowedCertificatePolicies();
         CertificateValidator certificateValidator = new CertificateValidator(
                 Collections.emptyList(), truststore,
                 subjectRegExp != null ? subjectRegExp.pattern() : null,
@@ -460,7 +456,7 @@ public class UITruststoreService extends BasicKeystoreService {
 
             String certificateAlias = truststore.getCertificateAlias(certificate);
             if (certificateAlias != null) {
-                throw new SMPRuntimeException(ErrorCode.CERTIFICATE_ERROR, "duplicate",  "The certificate you are trying to upload already exists under the [" + certificateAlias + "] entry");
+                throw new SMPRuntimeException(ErrorCode.CERTIFICATE_ERROR, "duplicate", "The certificate you are trying to upload already exists under the [" + certificateAlias + "] entry");
             }
 
             String aliasPrivate = StringUtils.isBlank(alias) ? createAliasFromCert(certificate, truststore) : alias.trim();
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
index 77887976fea0d623dc8f8763ae2043721bdb66d6..152d36a4ae58807df9f6fdcce4a84409eb053217 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java
@@ -26,7 +26,7 @@ import eu.europa.ec.edelivery.smp.data.dao.UserDao;
 import eu.europa.ec.edelivery.smp.data.enums.ApplicationRoleType;
 import eu.europa.ec.edelivery.smp.data.enums.CredentialTargetType;
 import eu.europa.ec.edelivery.smp.data.enums.CredentialType;
-import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidation;
+import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidationMapping;
 import eu.europa.ec.edelivery.smp.data.model.user.DBCertificate;
 import eu.europa.ec.edelivery.smp.data.model.user.DBCredential;
 import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
@@ -39,6 +39,7 @@ 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 eu.europa.ec.edelivery.smp.services.ConfigurationService;
+import eu.europa.ec.edelivery.smp.services.CredentialService;
 import eu.europa.ec.edelivery.smp.services.CredentialsAlertService;
 import eu.europa.ec.edelivery.smp.utils.BCryptPasswordHash;
 import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
@@ -70,6 +71,7 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
     private static final String USER_ID_REQUEST_TYPE = "UserId";
 
     private final UserDao userDao;
+    private final CredentialService credentialService;
     CredentialDao credentialDao;
     private final ConfigurationService configurationService;
     private final ConversionService conversionService;
@@ -81,13 +83,15 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
                          ConfigurationService configurationService,
                          ConversionService conversionService,
                          UITruststoreService truststoreService,
-                         CredentialsAlertService alertService) {
+                         CredentialsAlertService alertService,
+                         CredentialService credentialService) {
         this.userDao = userDao;
         this.credentialDao = credentialDao;
         this.configurationService = configurationService;
         this.conversionService = conversionService;
         this.truststoreService = truststoreService;
         this.alertService = alertService;
+        this.credentialService = credentialService;
     }
 
     @Override
@@ -242,7 +246,7 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
     protected DBUser updateUsernamePasswordForUser(Long userID, String password, boolean adminUpdate) {
         Optional<DBCredential> optCredential = credentialDao.findUsernamePasswordCredentialForUserIdAndUI(userID);
 
-        DBCredential dbCredential = optCredential.orElse(createCredentialsForUser(userID,
+        DBCredential dbCredential = optCredential.orElse(credentialService.createCredentialsForUser(userID,
                 CredentialType.USERNAME_PASSWORD,
                 CredentialTargetType.UI));
 
@@ -277,31 +281,6 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
         return dbCredential.getUser();
     }
 
-
-    /**
-     * Method creates Username/passwords credentials for the user with given userId.
-     * The method must be called inside active transactions.
-     *
-     * @param userID               to change/create username-password credentials
-     * @param credentialType       the credential type
-     * @param credentialTargetType the credential target
-     */
-    protected DBCredential createCredentialsForUser(Long userID, CredentialType credentialType, CredentialTargetType credentialTargetType) {
-
-        DBUser dbUserToUpdate = userDao.find(userID);
-        if (dbUserToUpdate == null) {
-            LOG.error("Can not update user password because user,[{}] does not exist!", userID);
-            throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, USER_ID_REQUEST_TYPE, "Can not find user id to update!");
-        }
-        DBCredential credential = new DBCredential();
-        credential.setUser(dbUserToUpdate);
-        credential.setName(dbUserToUpdate.getUsername());
-        credential.setCredentialType(credentialType);
-        credential.setCredentialTarget(credentialTargetType);
-
-        return credential;
-    }
-
     /**
      * Method updates the user password
      *
@@ -558,7 +537,7 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> {
      */
     public DeleteEntityValidation validateDeleteRequest(DeleteEntityValidation dev) {
         List<Long> idList = dev.getListIds().stream().map(SessionSecurityUtils::decryptEntityId).collect(Collectors.toList());
-        List<DBUserDeleteValidation> lstMessages = userDao.validateUsersForDelete(idList);
+        List<DBUserDeleteValidationMapping> lstMessages = userDao.validateUsersForDelete(idList);
         dev.setValidOperation(lstMessages.isEmpty());
         StringWriter sw = new StringWriter();
         sw.write("Could not delete user with ownerships! ");
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/ResourceRequest.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/ResourceRequest.java
index 0e7719dbc2c791ee4d26ab0a309e2dcf4f328c87..b21beb1db4a4e54175222500b2f92ad895b88e9d 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/ResourceRequest.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/ResourceRequest.java
@@ -20,12 +20,14 @@ package eu.europa.ec.edelivery.smp.servlet;
 
 import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.DBGroup;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.resource.ResolvedData;
 import org.apache.commons.lang3.StringUtils;
 
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
@@ -49,6 +51,7 @@ public class ResourceRequest {
     InputStream getInputStream;
 
     DBDomain authorizedDomain;
+    List<DBGroup> authorizedGroup = new ArrayList<>();
 
     ResolvedData resolvedData;
 
@@ -69,12 +72,12 @@ public class ResourceRequest {
     }
 
     public String getOwnerHttpParameter() {
-        String owner = getHeader(WebConstants.HTTP_PARAM_OWNER);
+        String owner = getHeader(WebConstants.HTTP_PARAM_ADMIN);
         if (StringUtils.isBlank(owner)) {
             LOG.debug("Try with obsolete owner parameter: 'ServiceGroup-Owner'");
-            owner = getHeader(WebConstants.HTTP_PARAM_OWNER_OBSOLETE);
+            owner = getHeader(WebConstants.HTTP_PARAM_ADMIN_OBSOLETE);
             if (StringUtils.isNotBlank(owner)) {
-                LOG.debug("Using obsolete owner parameter: 'ServiceGroup-Owner'. Move to new parameter: 'Resource-Owner'");
+                LOG.debug("Using obsolete owner parameter: 'ServiceGroup-Owner'. Move to new parameter: 'Resource-Admin'");
             }
         }
         return owner;
@@ -116,6 +119,10 @@ public class ResourceRequest {
         this.authorizedDomain = authorizedDomain;
     }
 
+    public List<DBGroup> getAuthorizedGroups() {
+        return authorizedGroup;
+    }
+
     public InputStream getInputStream() {
         return getInputStream;
     }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/WebConstants.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/WebConstants.java
index 6b7313b39deab3d30dfb7b1bb9b8e2e40c8cf4bb..4fc182cd74036a36f1819cbc1844f162dfc9fb05 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/WebConstants.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/servlet/WebConstants.java
@@ -29,8 +29,8 @@ public class WebConstants {
     public static final int HTTP_RESPONSE_CODE_UPDATED = 200;
     public static final String HTTP_PARAM_DOMAIN = "Domain";
     public static final String HTTP_PARAM_RESOURCE_TYPE = "Resource-Type";
-    public static final String HTTP_PARAM_OWNER_OBSOLETE = "ServiceGroup-Owner";
-    public static final String HTTP_PARAM_OWNER = "Resource-Owner";
+    public static final String HTTP_PARAM_ADMIN_OBSOLETE = "ServiceGroup-Owner";
+    public static final String HTTP_PARAM_ADMIN = "Resource-Admin";
     public static final String HTTP_PARAM_RESOURCE_GROUP = "Resource-Group";
     public static final String HTTP_PARAM_RESOURCE_VISIBILITY = "Resource-Visibility";
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/DateTimeUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/DateTimeUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1f61aca719abb9db484388818474a39a56dc67b
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/DateTimeUtils.java
@@ -0,0 +1,73 @@
+/*-
+ * #START_LICENSE#
+ * smp-server-library
+ * %%
+ * Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
+ * %%
+ * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
+ * versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ *
+ * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
+ * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ * #END_LICENSE#
+ */
+package eu.europa.ec.edelivery.smp.utils;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Locale;
+
+/**
+ * Utility class for date operations.
+ *
+ * @author Joze RIHTARSIC
+ * @since 5.1
+ */
+public class DateTimeUtils {
+
+
+    private DateTimeUtils() {
+        // Utility class
+    }
+
+    /**
+     * Format OffsetDateTime with locale for given ZoneId. IF ZoneId is null, system default time zone is used.
+     *
+     * @param offsetDateTime OffsetDateTime to format
+     * @param code           Locale code (e.g. "en", "de", "it", "fr", "sl"). If null/empty, "en" is used
+     * @param zoneId         ZoneId. If null, system default time zone is used
+     * @return formatted OffsetDateTime string representation
+     */
+    public static String formatOffsetDateTimeWithLocal(OffsetDateTime offsetDateTime, String code, ZoneId zoneId) {
+
+        if (offsetDateTime == null) {
+            return null;
+        }
+        //
+        Locale locale = new Locale(StringUtils.isBlank(code) ? "en" : code);
+        // Convert to ZonedDateTime using system default time zone
+        ZonedDateTime zonedDateTime = offsetDateTime.atZoneSameInstant(zoneId == null ? ZoneId.systemDefault() : zoneId);
+        // DateTimeFormatter with locale
+        DateTimeFormatter formatter = DateTimeFormatter.
+                ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.LONG)
+                .withLocale(locale);
+
+        // Format OffsetDateTime
+        return zonedDateTime.format(formatter);
+    }
+
+    public static String formatOffsetDateTimeWithLocal(OffsetDateTime offsetDateTime, String code) {
+        return formatOffsetDateTimeWithLocal(offsetDateTime, code, ZoneId.systemDefault());
+    }
+
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/EntityLoggingUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/EntityLoggingUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..034340c05b4347e4323fc8555017ee7262aeecc3
--- /dev/null
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/EntityLoggingUtils.java
@@ -0,0 +1,68 @@
+/*-
+ * #START_LICENSE#
+ * smp-server-library
+ * %%
+ * Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
+ * %%
+ * Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
+ * versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ *
+ * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
+ * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and limitations under the Licence.
+ * #END_LICENSE#
+ */
+package eu.europa.ec.edelivery.smp.utils;
+
+import eu.europa.ec.edelivery.smp.auth.SMPUserDetails;
+
+/**
+ * Utility class containing common methods for working with entities. Such as creating a string representation of an entity.
+ *
+ * @since 5.1
+ * @author Joze RIHTARSIC
+ */
+public class EntityLoggingUtils {
+    public static final String NULL_STRING = "null";
+    public static final String NULL_USER = "Anonymous";
+
+    /**
+     * Private constructor to prevent instantiation of the util class. The
+     * class contains only static methods and should not be instantiated.
+     */
+    private EntityLoggingUtils() {
+        // Utility class
+    }
+
+    public static <T> String entityToString(T entity, String defaultIfNull) {
+        return entity == null ? defaultIfNull : entity.toString();
+    }
+
+    /**
+     * Creates a string representation of an entity. If the entity is null, it returns the string "null".
+     * The method can be with logger which throws an exception if the entity is null.
+     *
+     * @param entity the entity to convert to a string
+     * @param <T>
+     * @return the string representation of the entity
+     */
+    public static <T> String entityToString(T entity) {
+        return entityToString(entity, NULL_STRING);
+    }
+
+    /**
+     * Creates a string representation of a user. If the user is null, it returns the string "UserDetails/Anonymous".
+     * @param user
+     * @return
+     */
+    public static String userDetailToString(SMPUserDetails user) {
+        if (user != null && user.getUser() == null) {
+            return "UserDetails/Anonymous";
+        }
+        return entityToString(user != null && user.getUser() != null ? user.getUser() : null, NULL_USER);
+    }
+}
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpUtils.java
index 07c2ba04ec3e7b1c0e122d816fe9127668cbef11..522f6d93d51e31a64944cbc31517f94965bd9ebe 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpUtils.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpUtils.java
@@ -23,6 +23,8 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import org.apache.commons.lang3.StringUtils;
 
 import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.AccessControlException;
 import java.util.Arrays;
 
 public class HttpUtils {
@@ -62,7 +64,7 @@ public class HttpUtils {
         String serverAddress;
         try {
             serverAddress = InetAddress.getLocalHost().getHostName();
-        } catch (Exception e) {
+        } catch (AccessControlException | UnknownHostException e) {
             LOG.error(e.getMessage(), e);
             serverAddress = StringUtils.EMPTY;
         }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java
index d8ca9d339538b3d0ceb5baae69bf5c5b965e678a..020e8ab6d9bb8a8d3d6845d9a351aeed5f6cd025 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java
@@ -27,7 +27,7 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.validator.routines.EmailValidator;
-import org.apache.commons.validator.routines.UrlValidator;
+import org.slf4j.event.Level;
 import org.springframework.scheduling.support.CronExpression;
 
 import java.io.File;
@@ -35,6 +35,7 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.Optional;
+import java.util.Properties;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import java.util.stream.Collectors;
@@ -196,8 +197,8 @@ public class PropertyUtils {
         if (propOpt.isPresent()) {
             return propOpt.get().isEncrypted() || property.toLowerCase().contains(".password.decrypted");
         }
-        LOG.warn("Database property [{}] is not recognized by the SMP!", property);
-        return false;
+        LOG.debug("Database property [{}] is not recognized by the SMP. Basic mask rule applied for masking!", property);
+        return StringUtils.contains(property.toLowerCase(), "passw");
     }
 
     /**
@@ -214,4 +215,36 @@ public class PropertyUtils {
     public static String getMaskedData(String value) {
         return isNotBlank(value) ? MASKED_VALUE : "Null/Empty/Blank";
     }
+
+    public static  void printProperties(Properties properties, Level loggingLevel) {
+        if (properties != null) {
+            LOG.debug("------ Print properties ------");
+            properties.entrySet().stream().forEach(e ->
+                    printProperty((String) e.getKey(), (String) e.getValue(), loggingLevel)
+            );
+        }
+    }
+
+    public static void printProperty(String key, String value, Level loggingLevel) {
+        String logValue = "\t[" + key + "] --> [" + getMaskedData(key, value) + "]";
+        switch (loggingLevel) {
+            case TRACE:
+                LOG.trace(logValue);
+                break;
+            case DEBUG:
+                LOG.debug(logValue);
+                break;
+            case INFO:
+                LOG.info(logValue);
+                break;
+            case WARN:
+                LOG.warn(logValue);
+                break;
+            case ERROR:
+                LOG.error(logValue);
+                break;
+            default:
+                LOG.debug(logValue);
+        }
+    }
 }
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java
index d59c253cfea1bcb878da0e58cab8a0b3f5dc1ac1..44d68211da706dea611a169c17c0c3698d90766e 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java
@@ -141,6 +141,19 @@ public class SessionSecurityUtils {
         return null;
     }
 
+    public static Long getSessionUserId() {
+        SMPUserDetails smpUserDetails = getSessionUserDetails();
+        if (smpUserDetails == null) {
+            LOG.warn("No SMPUserDetails object!");
+            return null;
+        }
+        if (smpUserDetails.getUser() == null) {
+            LOG.warn("No User object in SMPUserDetails!");
+            return null;
+        }
+        return smpUserDetails.getUser().getId();
+    }
+
     public static SecurityUtils.Secret getAuthenticationSecret() {
         SMPUserDetails smpUserDetails = getSessionUserDetails();
         if (smpUserDetails == null) {
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutor.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutor.java
index 1c87fb419787a10c83717fc54213665d28e0487c..c28ca5d2dc8c517b2a6dfbbb4944ad747a116114 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutor.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutor.java
@@ -53,7 +53,7 @@ public class StringNamedSubstitutor {
      * @param config the config to use
      * @return the resolved string
      */
-    public static String resolve(String string, Map<String, Object> config) {
+    public static String resolve(String string, Map<String, String> config) {
         String charset = Charset.defaultCharset().name();
         LOG.debug("Using default charset: [{}]", charset);
         return resolve(string, config, charset);
@@ -68,7 +68,7 @@ public class StringNamedSubstitutor {
      * @param charset the character of the input stream
      * @return the resolved string
      */
-    public static String resolve(String string, Map<String, Object> config, String charset) {
+    public static String resolve(String string, Map<String, String> config, String charset) {
         try {
             return resolve(new ByteArrayInputStream(string.getBytes()), config, charset);
         } catch (IOException e) {
@@ -86,7 +86,7 @@ public class StringNamedSubstitutor {
      * @return the resolved string
      * @throws IOException if an I/O error occurs
      */
-    public static String resolve(InputStream templateIS, Map<String, Object> config) throws IOException {
+    public static String resolve(InputStream templateIS, Map<String, String> config) throws IOException {
         String charset = Charset.defaultCharset().name();
         LOG.debug("Using default charset: [{}]", charset);
         return resolve(templateIS, config, charset);
@@ -101,7 +101,7 @@ public class StringNamedSubstitutor {
      * @param charset    the character of the input stream
      * @return the resolved string
      */
-    public static String resolve(InputStream templateIS, Map<String, Object> config, String charset) throws IOException {
+    public static String resolve(InputStream templateIS, Map<String, String> config, String charset) throws IOException {
 
         try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
             resolve(templateIS, config, byteArrayOutputStream, charset);
@@ -119,9 +119,9 @@ public class StringNamedSubstitutor {
      * @param charset      the charset to use
      * @throws IOException if an I/O error occurs
      */
-    public static void resolve(InputStream templateIS, Map<String, Object> config,
+    public static void resolve(InputStream templateIS, Map<String, String> config,
                                OutputStream outputStream, String charset) throws IOException {
-        Map<String, Object> lowerCaseMap = normalizeData(config);
+        Map<String, String> lowerCaseMap = normalizeData(config);
         try (BufferedReader template = new BufferedReader(new InputStreamReader(templateIS, charset));
              Writer writer = new OutputStreamWriter(outputStream, charset)) {
             int read;
@@ -137,11 +137,9 @@ public class StringNamedSubstitutor {
                     writer.write(START_NAME);
                 } else {
                     String key = lowerCase(name);
-                    Object objValue = lowerCaseMap.get(key);
-                    String value = objValue != null ? String.valueOf(lowerCaseMap.get(key)) : null;
-
-                    if (value != null) {
-                        writer.write(value);
+                    String objValue = lowerCaseMap.get(key);
+                    if (objValue != null) {
+                        writer.write(objValue);
                     } else {
                         writer.write(START_NAME);
                         writer.write(name);
@@ -158,8 +156,8 @@ public class StringNamedSubstitutor {
      * @param dataModel the data model
      * @return the normalized data model
      */
-    private static Map<String, Object> normalizeData(Map<String, Object> dataModel) {
-        Map<String, Object> lowerCaseMap = new HashMap<>();
+    private static Map<String, String> normalizeData(Map<String, String> dataModel) {
+        Map<String, String> lowerCaseMap = new HashMap<>();
         // Note: do not use stream with Collectors.toMap because it throws NPE if value is null
         dataModel.forEach((key, value) ->
                 lowerCaseMap.put(lowerCase(trim(key)), value));
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDaoTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDaoTest.java
index d595707da01b981542f1ddaf92342cac6f6afb1f..01871408d4b5c235fcc42e9056e8709212662976 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDaoTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentDaoTest.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -34,6 +34,9 @@ import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.*;
 
+/**
+ * The type Document dao test.
+ **/
 class DocumentDaoTest extends AbstractBaseDao {
 
     @Autowired
@@ -53,7 +56,8 @@ class DocumentDaoTest extends AbstractBaseDao {
 
         assertNotNull(document.getId());
         assertEquals(2, document.getDocumentVersions().size());
-        assertEquals(2, document.getCurrentVersion());
+        // the current version is 1
+        assertEquals(1, document.getCurrentVersion());
     }
 
 
@@ -64,7 +68,7 @@ class DocumentDaoTest extends AbstractBaseDao {
         assertTrue(result.isPresent());
         assertEquals(testUtilsDao.getDocumentD1G1RD1(), result.get());
         // the default setup  createResources  sets two versions (0 and 1 ) with current version 1
-        assertEquals(2, result.get().getCurrentVersion());
+        assertEquals(1, result.get().getCurrentVersion());
     }
 
 
@@ -82,9 +86,9 @@ class DocumentDaoTest extends AbstractBaseDao {
 
         assertTrue(result.isPresent());
         // the default setup  createResources  sets two versions (0 and 1 ) with current version 1
-        assertEquals(2, result.get().getVersion());
+        assertEquals(1, result.get().getVersion());
         // note that the versions are ordered by version desc
-        assertEquals(testUtilsDao.getDocumentD1G1RD1().getDocumentVersions().get(0), result.get());
+        assertEquals(testUtilsDao.getDocumentD1G1RD1().getDocumentVersions().get(1), result.get());
     }
 
 
@@ -102,9 +106,9 @@ class DocumentDaoTest extends AbstractBaseDao {
 
         assertTrue(result.isPresent());
         // the default setup  createResources  sets two versions (1 and 2 ) with current version 2
-        assertEquals(2, result.get().getVersion());
+        assertEquals(1, result.get().getVersion());
         // note that the versions are ordered by version desc
-        assertEquals(testUtilsDao.getDocumentD1G1RD1_S1().getDocumentVersions().get(0), result.get());
+        assertEquals(testUtilsDao.getDocumentD1G1RD1_S1().getDocumentVersions().get(1), result.get());
     }
 
     @Test
@@ -134,10 +138,10 @@ class DocumentDaoTest extends AbstractBaseDao {
                 testUtilsDao.getDomainResourceDefD1R1(), testUtilsDao.getGroupD1G1());
 
         testUtilsDao.createResourceMembership(MembershipRoleType.ADMIN, testUtilsDao.getUser1(), createResourceWithStatusReview, true);
-
-        List<DBReviewDocumentVersion> dbDocumentVersions =  testInstance.getDocumentReviewListForUser(testUtilsDao.getUser1().getId());
-        assertEquals(1, dbDocumentVersions.size());
-
+        List<DBReviewDocumentVersionMapping> result = testInstance.getDocumentReviewListForUser(testUtilsDao.getUser1().getId(), -1, -1);
+        Long resultCount = testInstance.getDocumentReviewListForUserCount(testUtilsDao.getUser1().getId());
+        assertEquals(1, result.size());
+        assertEquals(1, resultCount.intValue());
     }
 
     @ParameterizedTest
@@ -159,8 +163,41 @@ class DocumentDaoTest extends AbstractBaseDao {
 
         testUtilsDao.createResourceMembership(MembershipRoleType.ADMIN, testUtilsDao.getUser1(), resource, true);
 
-        List<DBReviewDocumentVersion> dbDocumentVersions =  testInstance.getDocumentReviewListForUser(testUtilsDao.getUser1().getId());
+        List<DBReviewDocumentVersionMapping> dbDocumentVersions = testInstance.getDocumentReviewListForUser(testUtilsDao.getUser1().getId(), -1, -1);
         assertEquals(expectedSize, dbDocumentVersions.size());
+    }
 
+    /**
+     * Test paginating the document review list for user . There are 10 document versions in the database.
+     *
+     * @param page         the page
+     * @param pageSize     the page size
+     * @param expectedSize the expected size
+     */
+    @ParameterizedTest
+    @CsvSource({
+            "'Return all', -1, -1, 20",
+            "'Page not set: Return first page', 8, -1, 8",
+            "'Return second page', 8, 1, 8",
+            "'Return reminder page', 8, 2, 4",
+            "'Page out of scope ', 8, 9, 0",
+    })
+    void testPersistUnderReviewDocumentSubresource(String desc, int pageSize, int page, int expectedSize) {
+        // given 20 document versions revisions
+        testUtilsDao.createResourceDefinitions();
+        for (int i = 0; i < 10; i++) {
+            DBResource resource = testUtilsDao.createResource("review-" + i, "1-1-1", VisibilityType.PUBLIC,
+                    DocumentVersionStatusType.UNDER_REVIEW,
+                    testUtilsDao.getDomainResourceDefD1R1(), testUtilsDao.getGroupD1G1());
+
+            DBSubresource subres = testUtilsDao.createSubresource(resource, "1-1-1" + i, "1-1-1",
+                    DocumentVersionStatusType.UNDER_REVIEW,
+                    testUtilsDao.getSubresourceDefSmpMetadata());
+            testUtilsDao.createResourceMembership(MembershipRoleType.ADMIN, testUtilsDao.getUser1(), resource, true);
+        }
+        // then
+        List<DBReviewDocumentVersionMapping> dbDocumentVersions
+                = testInstance.getDocumentReviewListForUser(testUtilsDao.getUser1().getId(), page, pageSize);
+        assertEquals(expectedSize, dbDocumentVersions.size());
     }
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentReferenceSearchTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentReferenceSearchTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0861adb14bc2d630bed28bc182fc59ab008d9b44
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DocumentReferenceSearchTest.java
@@ -0,0 +1,106 @@
+package eu.europa.ec.edelivery.smp.data.dao;
+
+import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
+import eu.europa.ec.edelivery.smp.data.model.doc.DBSearchReferenceDocumentMapping;
+import eu.europa.ec.edelivery.smp.data.model.doc.DBSubresource;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class DocumentReferenceSearchTest extends AbstractBaseDao {
+
+    @Autowired
+    DocumentDao testInstance;
+
+    @BeforeEach
+    public void prepareDatabase() {
+        // setup initial data!
+        testUtilsDao.clearData();
+        testUtilsDao.createResourcesForSearch();
+    }
+
+    @Test
+    @Transactional
+    void testGetSearchReferenceDocumentResourcesNoPublic() {
+        // given
+        DBResource dbResource = testUtilsDao.getResourceSearchPubPubPub();
+        assertNotNull(dbResource);
+
+        List<DBSearchReferenceDocumentMapping> result = testInstance.getSearchReferenceDocumentResources(dbResource, null, null, -1, -1);
+        long countResult = testInstance.getSearchReferenceDocumentResourcesCount(dbResource, null, null);
+        assertEquals(0, result.size());
+        assertEquals(0, countResult);
+    }
+
+    @Test
+    @Transactional
+    void testGetSearchReferenceDocumentSubresourcesNoPublic() {
+        // given public resource does not have any suitable public subresources for search
+        DBSubresource dbSubresource = testUtilsDao.getSubresourceSearchPubPubPub();
+        assertNotNull(dbSubresource);
+
+        List<DBSearchReferenceDocumentMapping> result = testInstance.getSearchReferenceDocumentSubresource(
+                dbSubresource, null, null, null, null, -1, -1);
+        long countResult = testInstance.getSearchReferenceDocumentSubresourceCount(dbSubresource, null, null, null, null);
+        assertEquals(0, result.size());
+        assertEquals(0, countResult);
+    }
+
+    @ParameterizedTest
+    @CsvSource({"All resources, , , 3",
+            "Filter by identifier, 'pubPubPub',, 1",
+            "Filter partial by identifier, 'pub',, 3",
+            "Filter by scheme, ,'5-5-5', 1",
+            "Filter partial by scheme, ,'5-5', 1"
+    })
+    void testGetSearchReferenceDocumentResources(String desc, String identifier, String scheme, int expectedCount) {
+        // given
+        System.out.println("desc = " + desc);
+        DBResource dbResource = testUtilsDao.getResourceSearchPrivPrivPriv();
+        assertNotNull(dbResource);
+
+        List<DBSearchReferenceDocumentMapping> result = testInstance.getSearchReferenceDocumentResources(dbResource, identifier, scheme, -1, -1);
+        long countResult = testInstance.getSearchReferenceDocumentResourcesCount(dbResource, identifier, scheme);
+
+        // the same group and one from co-group which is public
+        result.forEach(System.out::println);
+        assertEquals(expectedCount, result.size());
+        assertEquals(expectedCount, (int)countResult);
+    }
+
+    @ParameterizedTest
+    @CsvSource({"All resources,,,,,3",
+            "Filter by sidentifier,,,'pubPubPub',, 1",
+            "Filter partial by sidentifier,,, 'pub',, 3",
+            "Filter by sscheme,,,,'5-5-5', 1",
+            "Filter partial by sscheme,,,,'5-5', 1",
+            "Filter by ridentifier,'pubPubPub',,,,1",
+            "Filter partial by ridentifier, 'pub',,,,3",
+            "Filter by rscheme,,'5-5-5',,,1",
+            "Filter partial by rscheme,,'5-5',,,1",
+            "Filter partial by both identifier, 'pub',,sub,,3",
+            "Filter partial by both identifier, 'pub',,subres-priv,,2"
+    })
+    void testGetSearchReferenceDocumentSubResources(String desc,String ridentifier, String rscheme,  String sidentifier, String sscheme, int expectedCount) {
+        // given
+        System.out.println("desc = " + desc);
+        DBSubresource dbSubresource = testUtilsDao.getSubresourceSearchPrivPrivPriv();
+        assertNotNull(dbSubresource);
+
+        List<DBSearchReferenceDocumentMapping> result = testInstance.getSearchReferenceDocumentSubresource(dbSubresource, ridentifier, rscheme, sidentifier, sscheme, -1, -1);
+        long countResult = testInstance.getSearchReferenceDocumentSubresourceCount(dbSubresource, ridentifier, rscheme, sidentifier, sscheme);
+
+        // the same group and one from co-group which is public
+        result.forEach(System.out::println);
+        assertEquals(expectedCount, result.size());
+        assertEquals(expectedCount, (int)countResult);
+    }
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java
index cbab7cad2186763c8e2139f64b9c6e33b6a94ed0..8aec3d2d51cb5103b394bb75fffbfd103ee7d3af 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoSearchTest.java
@@ -19,11 +19,14 @@
 package eu.europa.ec.edelivery.smp.data.dao;
 
 
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
 import eu.europa.ec.edelivery.smp.data.model.doc.DBResourceFilter;
 import org.hamcrest.CoreMatchers;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -143,4 +146,25 @@ class ResourceDaoSearchTest extends AbstractBaseDao {
 
     }
 
+    @ParameterizedTest
+    @CsvSource({ "'Get all public  OK',0088:1234556-1234,test-test-test,,,2",
+            "'Search by identifier OK',0088:1234556-1234,test-test-test,0088:1234556-123,, 1",
+            "'Search by identifier partial OK',0088:1234556-1234,test-test-test,88:12,, 1",
+            "'Search by scheme partial OK',0088:1234556,test-test-test,,-test-, 1",
+            "'Search by chars OK',0088:#$%!@#$-1234,test-test-test,#$%!@#,, 1",
+            "'Search by '/' OK',0088/1234,test-test-test,88/12,, 1",
+            "'Search by '\\' OK',0088\\1234,test-test-test,88\\12,, 1",
+    })
+    void testGetSearchSlashCharacter(String testDec, String identifierValue, String identifierScheme, String searchValue, String searcScheme, int cnt) {
+        LOG.info(testDec);
+        // given
+        testUtilsDao.createResource(identifierValue,identifierScheme, VisibilityType.PUBLIC, testUtilsDao.getDomainResourceDefD1R1(), testUtilsDao.getGroupD1G1()  );
+        // then
+        List<ResourceDao.DBResourceWrapper> result = testInstance.getPublicResourcesSearch(-1, -1, null, searcScheme, searchValue, null, null);
+        assertEquals(cnt, result.size());
+        result.stream().forEach(val -> {
+            assertEquals(VisibilityType.PUBLIC, val.getDbResource().getVisibility());
+        });
+    }
+
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoTest.java
index 46431c41bb034a081ccd275470445bda0425ee35..ebd40eb2ed15509bf390ac52f3edd44b47ea7885 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/ResourceDaoTest.java
@@ -106,7 +106,7 @@ class ResourceDaoTest extends AbstractBaseDao {
 
         assertTrue(optResult.isPresent());
         assertNotNull(optResult.get().getDocument());
-        assertEquals(docVersion + 1, optResult.get().getDocument().getCurrentVersion());
+        assertEquals(docVersion , optResult.get().getDocument().getCurrentVersion());
         assertEquals(docCount + 1, optResult.get().getDocument().getDocumentVersions().size());
     }
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestEntitySearchBasedPermissions.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestEntitySearchBasedPermissions.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6ac4e6ac5f1d39a0ac589b4a84a6f5d8b0dda22
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestEntitySearchBasedPermissions.java
@@ -0,0 +1,112 @@
+package eu.europa.ec.edelivery.smp.data.dao;
+
+
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
+import eu.europa.ec.edelivery.smp.data.model.DBDomain;
+import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef;
+import eu.europa.ec.edelivery.smp.data.model.user.DBUser;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.List;
+
+/**
+ * Test class for testing search based permissions for entities.
+ * For validating the permissions and how entities are mapped to users, please see the following methods:
+ * testUtilsDao.createResourcesForSearch();
+ * @author Joze Rihtarsic
+ * @since 5.1
+ */
+class TestEntitySearchBasedPermissions extends AbstractBaseDao {
+
+    @Autowired
+    DomainDao domainTestInstance;
+    @Autowired
+    ResourceDefDao resourceDefTestInstance;
+
+    @BeforeEach
+    public void prepareDatabase() {
+        // setup initial data!
+        testUtilsDao.clearData();
+        testUtilsDao.createResourcesForSearch();
+    }
+
+    @Test
+    void testGetAllPublicDomains() {
+        // when
+        DBUser user = null;
+        List<DBDomain> result = testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain(user, 1);
+        Assertions.assertEquals(VisibilityType.PUBLIC, result.get(0).getVisibility());
+    }
+
+    @Test
+    void testGetAllDomainsForUsersWithResources() {
+        // when
+        DBUser user = testUtilsDao.getUser1();
+        List<DBDomain> result = testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain(user, 2);
+        Assertions.assertEquals(VisibilityType.PUBLIC, result.get(0).getVisibility());
+        Assertions.assertEquals(VisibilityType.PRIVATE, result.get(1).getVisibility());
+    }
+
+    @Test
+    void testGetAllDomainsForUsersWithPrivateDomainMembership() {
+        // when
+        DBUser user = testUtilsDao.getUser3();
+        List<DBDomain> result = testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain(user, 2);
+        Assertions.assertEquals(VisibilityType.PUBLIC, result.get(0).getVisibility());
+        Assertions.assertEquals(VisibilityType.PRIVATE, result.get(1).getVisibility());
+    }
+
+    @Test
+    void testGetAllDomainsForUsersWithGroupMembershipOnPrivateDomain() {
+        // when
+        DBUser user = testUtilsDao.getUser4();
+        List<DBDomain> result = testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain(user, 2);
+        Assertions.assertEquals(VisibilityType.PUBLIC, result.get(0).getVisibility());
+        Assertions.assertEquals(VisibilityType.PRIVATE, result.get(1).getVisibility());
+    }
+
+    @Test
+    void testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain() {
+        // when
+        DBUser user = testUtilsDao.getUser5();
+        List<DBDomain> result = testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain(user, 2);
+        Assertions.assertEquals(VisibilityType.PUBLIC, result.get(0).getVisibility());
+        Assertions.assertEquals(VisibilityType.PRIVATE, result.get(1).getVisibility());
+    }
+
+    @Test
+    void testGetAllPublicResourceDefinitions() {
+        // when
+        testGetAllDResourceDefinitionsForUsersWithResources(null, 1);
+    }
+
+    @Test
+    void testGetAllDResourceDefinitionsForUsersWithResources() {
+        // givem
+        DBUser user = testUtilsDao.getUser1();
+        // when -then
+        testGetAllDResourceDefinitionsForUsersWithResources(user, 2);
+    }
+
+    void testGetAllDResourceDefinitionsForUsersWithResources(DBUser user, long expectedCount) {
+        // when
+        List<DBResourceDef> result = resourceDefTestInstance.getAllResourceDefsForUser(user, -1, -1);
+        Long resultCount = resourceDefTestInstance.getAllResourceDefsForUserCount(user);
+
+        Assertions.assertEquals(expectedCount, result.size());
+        Assertions.assertEquals(expectedCount, resultCount);
+    }
+
+    List<DBDomain> testGetAllDomainsForUsersWithResourceMembershipOnPrivateDomain( DBUser user, long expectedCount) {
+        // when
+        List<DBDomain> result = domainTestInstance.getAllDomainsForUser(user, -1, -1);
+        Long resultCount = domainTestInstance.getAllDomainsForUserCount(user);
+
+        Assertions.assertEquals(expectedCount, result.size());
+        Assertions.assertEquals(expectedCount, resultCount);
+        return result;
+    }
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java
index e96d569a97dccfb84246ea8a1d69d3ced2f5bc85..ea8a02c12d9fe0f0dd307b84c6cc0899465ce38b 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/TestUtilsDao.java
@@ -108,7 +108,28 @@ public class TestUtilsDao {
     DBResource resourcePrivateD1G1RD1;
     DBExtension extension;
 
+
     boolean searchDataCreated = false;
+    DBResource searchPubPubPubRes = null;
+    DBResource searchPubPubPrivRes = null;
+    DBResource searchPubPrivPubRes = null;
+    DBResource searchPubPrivPrivRes = null;
+
+    DBResource searchPrivPubPubRes = null;
+    DBResource searchPrivPubPrivRes = null;
+    DBResource searchPrivPrivPubRes = null;
+    DBResource searchPrivPrivPrivRes = null;
+
+    DBSubresource searchPubPubPubSubRes = null;
+    DBSubresource searchPubPubPrivSubRes = null;
+    DBSubresource searchPubPrivPubSubRes = null;
+    DBSubresource searchPubPrivPrivSubRes = null;
+
+    DBSubresource searchPrivPubPubSubRes = null;
+    DBSubresource searchPrivPubPrivSubRes = null;
+    DBSubresource searchPrivPrivPubSubRes = null;
+    DBSubresource searchPrivPrivPrivSubRes = null;
+
 
     /**
      * Database can be cleaned by script before the next test; clean also the objects
@@ -150,6 +171,26 @@ public class TestUtilsDao {
 
         extension = null;
         searchDataCreated = false;
+        searchPubPubPubRes = null;
+        searchPubPubPrivRes = null;
+        searchPubPrivPubRes = null;
+        searchPubPrivPrivRes = null;
+
+        searchPrivPubPubRes = null;
+        searchPrivPubPrivRes = null;
+        searchPrivPrivPubRes = null;
+        searchPrivPrivPrivRes = null;
+
+        searchPubPubPubSubRes = null;
+        searchPubPubPrivSubRes = null;
+        searchPubPrivPubSubRes = null;
+        searchPubPrivPrivSubRes = null;
+
+        searchPrivPubPubSubRes = null;
+        searchPrivPubPrivSubRes = null;
+        searchPrivPrivPubSubRes = null;
+        searchPrivPrivPrivSubRes = null;
+
 
     }
 
@@ -332,50 +373,61 @@ public class TestUtilsDao {
         createUsers();
         createResourceDefinitions();
 
-        DBDomain publicDomain = createDomain("publicDomain", VisibilityType.PUBLIC);
-        DBDomain privateDomain = createDomain("privateDomain", VisibilityType.PRIVATE);
+        d1 = createDomain("publicDomain", VisibilityType.PUBLIC);
+        d2 = createDomain("privateDomain", VisibilityType.PRIVATE);
 
-        DBDomainResourceDef publicDomainResourceDef = registerDomainResourceDefinition(publicDomain, resourceDefSmp);
-        DBDomainResourceDef privateDomainResourceDef= registerDomainResourceDefinition(privateDomain, resourceDefSmp);
+
+        domainResourceDefD1R1 = registerDomainResourceDefinition(d1, resourceDefSmp);
+        domainResourceDefD2R1 = registerDomainResourceDefinition(d2, resourceDefSmp);
+        DBDomainResourceDef privateDomainResourceDef2= registerDomainResourceDefinition(d2, resourceDefCpp);
         // membership of the domain
-        createDomainMembership(MembershipRoleType.VIEWER, user3, privateDomain);
+        createDomainMembership(MembershipRoleType.VIEWER, user3, d2);
 
-        DBGroup pubPubGroup = createGroup("pubPubGroup", VisibilityType.PUBLIC, publicDomain);
-        DBGroup pubPrivGroup = createGroup("pubPrivGroup", VisibilityType.PRIVATE, publicDomain);
-        DBGroup privPubGroup = createGroup("privPubGroup", VisibilityType.PUBLIC, privateDomain);
-        DBGroup privPrivGroup = createGroup("privPrivGroup", VisibilityType.PRIVATE, privateDomain);
+        groupD1G1  = createGroup("pubPubGroup", VisibilityType.PUBLIC, d1);
+        groupD1G2 = createGroup("pubPrivGroup", VisibilityType.PRIVATE, d1);
+        groupD2G1 = createGroup("privPubGroup", VisibilityType.PUBLIC, d2);
+        DBGroup privPrivGroup = createGroup("privPrivGroup", VisibilityType.PRIVATE, d2);
 
         createGroupMembership(MembershipRoleType.VIEWER, user4, privPrivGroup);
 
-        DBResource pubPubPubRes = createResource("pubPubPub", "1-1-1", VisibilityType.PUBLIC, publicDomainResourceDef,  pubPubGroup);
-        DBResource pubPubPrivRes = createResource("pubPubPriv", "2-2-2", VisibilityType.PRIVATE, publicDomainResourceDef,  pubPubGroup);
-        DBResource pubPrivPubRes = createResource("pubPrivPub", "3-3-3", VisibilityType.PUBLIC, publicDomainResourceDef,  pubPrivGroup);
-        DBResource pubPrivPrivRes = createResource("pubPrivPriv", "4-4-4", VisibilityType.PRIVATE, publicDomainResourceDef,  pubPrivGroup);
-
-        DBResource privPubPubRes = createResource("privPubPub", "5-5-5", VisibilityType.PUBLIC, privateDomainResourceDef,  privPubGroup);
-        DBResource privPubPrivRes = createResource("privPubPriv", "6-6-6", VisibilityType.PRIVATE, privateDomainResourceDef,  privPubGroup);
-        DBResource privPrivPubRes = createResource("privPrivPub", "7-7-7", VisibilityType.PUBLIC, privateDomainResourceDef,  privPrivGroup);
-        DBResource privPrivPrivRes = createResource("privPrivPriv", "8-8-8", VisibilityType.PRIVATE, privateDomainResourceDef,  privPrivGroup);
-
-        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPubPubRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPubPubRes);
-        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPubPrivRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPubPrivRes);
-        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPrivPubRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPrivPubRes);
-        createResourceMembership(MembershipRoleType.ADMIN, user1, pubPrivPrivRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, pubPrivPrivRes);
-
-        createResourceMembership(MembershipRoleType.ADMIN, user1, privPubPubRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, privPubPubRes);
-        createResourceMembership(MembershipRoleType.ADMIN, user1, privPubPrivRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, privPubPrivRes);
-        createResourceMembership(MembershipRoleType.ADMIN, user1, privPrivPubRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, privPrivPubRes);
-        createResourceMembership(MembershipRoleType.ADMIN, user1, privPrivPrivRes);
-        createResourceMembership(MembershipRoleType.VIEWER, user2, privPrivPrivRes);
-
-        createResourceMembership(MembershipRoleType.VIEWER, user5, privPrivPrivRes);
+        searchPubPubPubRes = createResource("pubPubPub", "1-1-1", VisibilityType.PUBLIC, domainResourceDefD1R1,  groupD1G1);
+        searchPubPubPubSubRes = createSubresource(searchPubPubPubRes, "subres-pubPubPub", "s-1-1-1", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+        searchPubPubPrivRes = createResource("pubPubPriv", "2-2-2", VisibilityType.PRIVATE, domainResourceDefD1R1,  groupD1G1);
+        searchPubPubPrivSubRes = createSubresource(searchPubPubPrivRes, "subres-pubPubPriv", "s-2-2-2", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+        searchPubPrivPubRes = createResource("pubPrivPub", "3-3-3", VisibilityType.PUBLIC, domainResourceDefD1R1,  groupD1G2);
+        searchPubPrivPubSubRes = createSubresource(searchPubPrivPubRes, "subres-pubPrivPub", "s-3-3-3", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+        searchPubPrivPrivRes = createResource("pubPrivPriv", "4-4-4", VisibilityType.PRIVATE, domainResourceDefD1R1,  groupD1G2);
+        searchPubPrivPrivSubRes = createSubresource(searchPubPrivPrivRes, "subres-pubPrivPriv", "s-4-4-4", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+
+        searchPrivPubPubRes = createResource("privPubPub", "5-5-5", VisibilityType.PUBLIC, domainResourceDefD2R1,  groupD2G1);
+        searchPrivPubPubSubRes = createSubresource(searchPrivPubPubRes, "subres-privPubPub", "s-5-5-5", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+        searchPrivPubPrivRes = createResource("privPubPriv", "6-6-6", VisibilityType.PRIVATE, domainResourceDefD2R1,  groupD2G1);
+        searchPrivPubPrivSubRes = createSubresource(searchPrivPubPrivRes, "subres-privPubPriv", "s-6-6-6", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+        searchPrivPrivPubRes = createResource("privPrivPub", "7-7-7", VisibilityType.PUBLIC, domainResourceDefD2R1,  privPrivGroup);
+        searchPrivPrivPubSubRes = createSubresource(searchPrivPrivPubRes, "subres-privPrivPub", "s-7-7-7", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+        searchPrivPrivPrivRes = createResource("privPrivPriv", "8-8-8", VisibilityType.PRIVATE, domainResourceDefD2R1,  privPrivGroup);
+        searchPrivPrivPrivSubRes = createSubresource(searchPrivPrivPrivRes, "subres-privPrivPriv", "s-8-8-8", DocumentVersionStatusType.PUBLISHED, subresourceDefSmp);
+
+
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPubPubPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPubPubPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPubPubPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPubPubPrivRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPubPrivPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPubPrivPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPubPrivPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPubPrivPrivRes);
+
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPrivPubPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPrivPubPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPrivPubPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPrivPubPrivRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPrivPrivPubRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPrivPrivPubRes);
+        createResourceMembership(MembershipRoleType.ADMIN, user1, searchPrivPrivPrivRes);
+        createResourceMembership(MembershipRoleType.VIEWER, user2, searchPrivPrivPrivRes);
+
+        createResourceMembership(MembershipRoleType.VIEWER, user5, searchPrivPrivPrivRes);
 
         searchDataCreated = true;
     }
@@ -494,10 +546,10 @@ public class TestUtilsDao {
 
         dbSubresource.setSubresourceDef(subresourceDefSmp);
 
-        DBDocument doc  = createDocument(1, resourceD1G1RD1.getIdentifierValue(), resourceD1G1RD1.getIdentifierScheme(),
+        DBDocument doc  = createDocument(1, resource.getIdentifierValue(), resource.getIdentifierScheme(),
                 identifier, schema);
         doc.getDocumentVersions().get(0).setStatus(status);
-
+        doc.setSharingEnabled(Boolean.TRUE);
         dbSubresource.setDocument(doc);
         dbSubresource.setResource(resource);
 
@@ -561,8 +613,8 @@ public class TestUtilsDao {
         for (int i= 0; i< versions; i++ ) {
             assertNotNull(document.getDocumentVersions().get(i).getId());
         }
-        // current version is the last version
-        assertEquals(versions, document.getCurrentVersion());
+        // current version is first version all others are draft
+        assertEquals(1, document.getCurrentVersion());
 
         return document;
     }
@@ -850,4 +902,69 @@ public class TestUtilsDao {
     public DBGroupMember getGroupMemberU1D2G1Viewer() {
         return groupMemberU1D2G1Viewer;
     }
+
+
+    public DBResource getResourceSearchPubPubPub() {
+        return searchPubPubPubRes;
+    }
+
+    public DBResource getResourceSearchPubPubPriv() {
+        return searchPubPubPrivRes;
+    }
+
+    public DBResource getResourceSearchPubPrivPub() {
+        return searchPubPrivPubRes;
+    }
+
+    public DBResource getResourceSearchPubPrivPriv() {
+        return searchPubPrivPrivRes;
+    }
+
+    public DBResource getResourceSearchPrivPubPub() {
+        return searchPrivPubPubRes;
+    }
+
+    public DBResource getResourceSearchPrivPubPriv() {
+        return searchPrivPubPrivRes;
+    }
+
+    public DBResource getResourceSearchPrivPrivPub() {
+        return searchPrivPrivPubRes;
+    }
+
+    public DBResource getResourceSearchPrivPrivPriv() {
+        return searchPrivPrivPrivRes;
+    }
+
+    public DBSubresource getSubresourceSearchPubPubPub() {
+        return searchPubPubPubSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPubPubPriv() {
+        return searchPubPubPrivSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPubPrivPub() {
+        return searchPubPrivPubSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPubPrivPriv() {
+        return searchPubPrivPrivSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPrivPubPub() {
+        return searchPrivPubPubSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPrivPubPriv() {
+        return searchPrivPubPrivSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPrivPrivPub() {
+        return searchPrivPrivPubSubRes;
+    }
+
+    public DBSubresource getSubresourceSearchPrivPrivPriv() {
+        return searchPrivPrivPrivSubRes;
+    }
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/security/DomainGuardTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/security/DomainGroupGuardTest.java
similarity index 97%
rename from smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/security/DomainGuardTest.java
rename to smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/security/DomainGroupGuardTest.java
index 40697c84ffe409f20a07436e2711694cebd2f819..1131baa0e673f45c369293e39601ac8ab32df703 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/security/DomainGuardTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/security/DomainGroupGuardTest.java
@@ -37,10 +37,10 @@ import static org.hamcrest.Matchers.containsString;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.when;
 
-class DomainGuardTest extends AbstractJunit5BaseDao {
+class DomainGroupGuardTest extends AbstractJunit5BaseDao {
 
     @Autowired
-    DomainGuard testInstance;
+    DomainGroupGuard testInstance;
 
     ResourceRequest resourceRequest = Mockito.mock(ResourceRequest.class);
     SMPUserDetails userDetails = Mockito.mock(SMPUserDetails.class);
@@ -132,7 +132,7 @@ class DomainGuardTest extends AbstractJunit5BaseDao {
     }
 
     @Test
-    void testCanReadPrivateDomainAnonimous() {
+    void testCanReadPrivateDomainAnonymous() {
         DBDomain domain = Mockito.mock(DBDomain.class);
         when(domain.getVisibility()).thenReturn(VisibilityType.PRIVATE);
         when(userDetails.getUser()).thenReturn(null);
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialServiceTest.java
index 732c3e758e13e0bbb1536583c90f360c6e2ef1ce..ea3099c85b82211d0dd949308a280263458bfa61 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialServiceTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialServiceTest.java
@@ -294,7 +294,6 @@ class CredentialServiceTest extends AbstractJunit5BaseDao {
         MatcherAssert.assertThat(result.getMessage(), org.hamcrest.Matchers.startsWith("Login failed"));
     }
 
-
     @Test
     void testValidateCertificatePolicyLegacyMatchOk() {
         String certID = "CN=SMP Test,OU=eDelivery,O=DIGITAL,C=BE:000111";
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentServiceTest.java
index 61dfed3fc8329b36c3e57a55432ee9bddad5b1c5..d3b7083a9bf9d09814614a1e6dbf6e7ba568d149 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentServiceTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDocumentServiceTest.java
@@ -50,7 +50,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 
 @ContextConfiguration(classes = {UIDocumentService.class, ConversionTestConfig.class, ResourceHandlerService.class,
         OasisSMPResource10.class, OasisSMPResource10Handler.class, OasisSMPSubresource10.class, OasisSMPSubresource10Handler.class, Subresource10Validator.class,})
-public class UIDocumentServiceTest extends AbstractServiceIntegrationTest {
+class UIDocumentServiceTest extends AbstractServiceIntegrationTest {
 
     @Autowired
     protected UIDocumentService testInstance;
@@ -148,7 +148,7 @@ public class UIDocumentServiceTest extends AbstractServiceIntegrationTest {
         DocumentRO testDoc = testInstance.generateDocumentForResource(resource.getId());
         assertNotNull(testDoc.getPayload());
         //when
-        DocumentRO result = testInstance.saveDocumentForResource(resource.getId(), testDoc, null);
+        DocumentRO result = testInstance.saveDocumentForResource(resource.getId(), testDoc);
         // then
         assertNotNull(result);
     }
@@ -181,7 +181,7 @@ public class UIDocumentServiceTest extends AbstractServiceIntegrationTest {
         //when
         DocumentRO result = testInstance.saveSubresourceDocumentForResource(subresource.getId(), subresource.getResource().getId(), testDoc);
 
-        Map<String, Object> mapProperties = result.getProperties().stream().collect(Collectors.toMap(DocumentPropertyRO::getProperty, DocumentPropertyRO::getValue));
+        Map<String, String> mapProperties = result.getProperties().stream().collect(Collectors.toMap(DocumentPropertyRO::getProperty, DocumentPropertyRO::getValue));
         String resolved = StringNamedSubstitutor.resolve(result.getPayload(), mapProperties);
         // then
         Assertions.assertThat(resolved).doesNotContain(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_SCHEME.getPropertyPlaceholder());
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java
index f728f540d637121442c8e1d0ee24064e93ec5b06..b17d2c624f38031f12d5b2ca17faf1ac9a0e6307 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainServiceTest.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -46,7 +46,7 @@ class UIDomainServiceTest extends AbstractServiceTest {
     private UIDomainAdminService testInstance;
     @Autowired
     private DomainDao domainDao;
-//     @Autowired
+    //     @Autowired
     @SpyBean
     private SMLIntegrationService smlIntegrationService;
 
@@ -55,7 +55,6 @@ class UIDomainServiceTest extends AbstractServiceTest {
         testUtilsDao.clearData();
         testUtilsDao.createResourceDefinitionsForDomains();
 
-//        smlIntegrationService = Mockito.spy(smlIntegrationService);
         ReflectionTestUtils.setField(testInstance, "smlIntegrationService", smlIntegrationService);
     }
 
@@ -102,9 +101,9 @@ class UIDomainServiceTest extends AbstractServiceTest {
 
     @Test
     void updateSMLDomainData_domainNotFound() {
-        BadRequestException result =  assertThrows(BadRequestException.class, () ->
-                testInstance.updateDomainSmlIntegrationData(-1l, new DomainRO()));
-         assertEquals("Domain does not exist in database!", result.getMessage());
+        BadRequestException result = assertThrows(BadRequestException.class, () ->
+                testInstance.updateDomainSmlIntegrationData(-1L, new DomainRO()));
+        assertEquals("Domain does not exist in database!", result.getMessage());
     }
 
     @Test
@@ -114,9 +113,9 @@ class UIDomainServiceTest extends AbstractServiceTest {
         DomainRO domainRO = new DomainRO();
         domainRO.setSmlSmpId("utestRegistered03");
 
-        BadRequestException result =  assertThrows(BadRequestException.class, () ->
-                    testInstance.updateDomainSmlIntegrationData(domain.getId(), domainRO));
-         assertEquals("SMP-SML identifier must not change for registered domain [utestRegistered03]!", result.getMessage());
+        BadRequestException result = assertThrows(BadRequestException.class, () ->
+                testInstance.updateDomainSmlIntegrationData(domain.getId(), domainRO));
+        assertEquals("SMP-SML identifier must not change for registered domain [utestRegistered03]!", result.getMessage());
     }
 
     @Test
@@ -133,9 +132,9 @@ class UIDomainServiceTest extends AbstractServiceTest {
 
         Mockito.doReturn(false).when(smlIntegrationService).isDomainValid(domain);
 
-        BadRequestException result =  assertThrows(BadRequestException.class, () ->
+        BadRequestException result = assertThrows(BadRequestException.class, () ->
                 testInstance.updateDomainSmlIntegrationData(domain.getId(), domainRO));
-         assertEquals("The SML-SMP certificate for domain [utestRegistered03] is not valid!", result.getMessage());
+        assertEquals("The SML-SMP certificate for domain [utestRegistered03] is not valid!", result.getMessage());
     }
 
     @Test
@@ -165,7 +164,7 @@ class UIDomainServiceTest extends AbstractServiceTest {
     }
 
     @Test
-    void testGetDomainProperties(){
+    void testGetDomainProperties() {
         DBDomain domain = testUtilsDao.getD1();
         List<DomainPropertyRO> domainROList = testInstance.getDomainProperties(domain.getId());
 
@@ -175,7 +174,7 @@ class UIDomainServiceTest extends AbstractServiceTest {
     }
 
     @Test
-    void testUpdateDomainProperties(){
+    void testUpdateDomainProperties() {
         String newValue = "new value";
         DBDomain domain = testUtilsDao.getD1();
         List<DomainPropertyRO> domainROList = testInstance.getDomainProperties(domain.getId());
@@ -185,7 +184,7 @@ class UIDomainServiceTest extends AbstractServiceTest {
             domainPropertyRO.setValue(newValue);
             domainPropertyRO.setSystemDefault(!domainPropertyRO.isSystemDefault());
         }
-        List<DomainPropertyRO> domainROListUpdated =  testInstance.updateDomainProperties(domain.getId(), domainROList);
+        List<DomainPropertyRO> domainROListUpdated = testInstance.updateDomainProperties(domain.getId(), domainROList);
 
         List<DomainPropertyRO> domainROListUpdated2 = testInstance.getDomainProperties(domain.getId());
         assertEquals(SMPDomainPropertyEnum.values().length, domainROListUpdated2.size());
@@ -205,4 +204,18 @@ class UIDomainServiceTest extends AbstractServiceTest {
         assertNull(result);
     }
 
+    @Test
+    void deleteDomainMultipleGroups() {
+        DBDomain domain = testUtilsDao.getD1();
+        DBDomain test = domainDao.find(domain.getId());
+        testUtilsDao.createGroup("group1", VisibilityType.PUBLIC, test);
+        testUtilsDao.createGroup("group2", VisibilityType.PRIVATE, test);
+
+        testInstance.deleteDomain(domain.getId());
+
+        DBDomain result = domainDao.find(domain.getId());
+        assertNull(result);
+    }
+
+
 }
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
index 3267be90acd379d713e52fe8152aacd3ba2fd4e9..d44d0b042494d86e89324e856ade626a5dab6566 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java
@@ -175,6 +175,7 @@ public class TestDBUtils {
         resource.setVisibility(VisibilityType.PUBLIC);
         if (withExtension) {
             DBDocument document = createDBDocument();
+            document.setSharingEnabled(true);
             DBDocumentVersion documentVersion = createDBDocumentVersion(id, sch, statusType);
             document.addNewDocumentVersion(documentVersion);
             resource.setDocument(document);
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/DateUtilsTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/DateUtilsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..211acecbe0f9371a4de7e65203d1e5f54db49e47
--- /dev/null
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/DateUtilsTest.java
@@ -0,0 +1,28 @@
+package eu.europa.ec.edelivery.smp.utils;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class DateUtilsTest {
+
+    @ParameterizedTest
+    @CsvSource({
+            "2021-06-01T12:00:00Z, US,'2021-06-01 12:00:00 UTC'",
+            "2021-06-01T12:00:00Z, DE, '01.06.21, 12:00:00 UTC'",
+            "2021-06-01T12:00:00Z, IT, '01/06/21, 12:00:00 UTC'",
+            "2007-12-03T10:15:30+01:00, FR, '03/12/2007 09:15:30 UTC'",
+            "2021-06-01T12:00:00+02, SL, '1. 06. 21 10:00:00 UTC'",
+    })
+    void testFormatOffsetDateTimeAsLocalFormat(String offsetDateTimeStr, String locale, String expected) {
+        // given
+        OffsetDateTime offsetDateTime = OffsetDateTime.parse(offsetDateTimeStr);
+        ZoneId zoneId = ZoneId.of("UTC");
+        // Act and Assert
+        assertEquals(expected, DateTimeUtils.formatOffsetDateTimeWithLocal(offsetDateTime, locale, zoneId));
+    }
+}
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutorTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutorTest.java
index 956fb612eb8447c6fbddf4e8e84b3b3937295456..2267db16b73a3bda01fc5dc67d67800be232ed5e 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutorTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/StringNamedSubstitutorTest.java
@@ -59,7 +59,7 @@ class StringNamedSubstitutorTest {
                     "'The quick red fox jumps over the ${DOG_MODE} dog'",
     })
     void resolve(String testString, String values, String expected) {
-        Map<String, Object> mapVal = Stream.of(values.split("\\s*;\\s*"))
+        Map<String, String> mapVal = Stream.of(values.split("\\s*;\\s*"))
                 .map(s -> s.split("\\s*=\\s*"))
                 .collect(HashMap::new, (m, v) -> m.put(v[0], v[1]), Map::putAll);
 
@@ -69,7 +69,7 @@ class StringNamedSubstitutorTest {
 
     @Test
     void testTransientResolutionForResourceWithUTF8() throws UnsupportedEncodingException {
-        Map<String, Object> mapProperties = new HashMap<>();
+        Map<String, String> mapProperties = new HashMap<>();
         mapProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_VALUE.getPropertyName(), "value");
         mapProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_SCHEME.getPropertyName(), "scheme");
         String serviceGroupWithUt8 = URLDecoder.decode(SERVICE_GROUP_WITH_UTF8, "UTF-8");
@@ -87,7 +87,7 @@ class StringNamedSubstitutorTest {
 
     @Test
     void testTransientResolutionWithUTF8String() throws UnsupportedEncodingException {
-        Map<String, Object> mapProperties = new HashMap<>();
+        Map<String, String> mapProperties = new HashMap<>();
         mapProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_VALUE.getPropertyName(), "value");
         mapProperties.put(TransientDocumentPropertyType.RESOURCE_IDENTIFIER_SCHEME.getPropertyName(), "scheme");
         String serviceGroupWithUt8 = URLDecoder.decode(TEST_UTF8_STRING, "UTF-8");
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java
index ef65571b9dad35753b0143a427647eb613da80a7..6aa5f34a0c633d7a90319602ae9f8cb2a1c012e5 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthenticationService.java
@@ -114,7 +114,6 @@ public class SMPAuthenticationService {
             credentialService.delayResponse(CredentialType.USERNAME_PASSWORD, startTime);
             throw e;
         }
-        credentialService.validatePasswordResetToken(resetToken);
     }
 
     public void logout(HttpServletRequest request, HttpServletResponse response) {
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/cas/SMPCasUserService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/cas/SMPCasUserService.java
index 5b22b2f9f0cd53ba74410237b17c9e224c397b38..f8e04881a4153e3a7aa11facf5916a6641c04b35 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/cas/SMPCasUserService.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/cas/SMPCasUserService.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -39,6 +39,7 @@ import org.springframework.stereotype.Component;
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 
 /**
@@ -50,82 +51,91 @@ import java.util.Map;
  */
 @Component
 public class SMPCasUserService implements AuthenticationUserDetailsService<CasAssertionAuthenticationToken> {
-	enum MappingData {
-		EMAIL("${email}"),
-		FULL_NAME("${firstName} ${lastName}");
-
-		private final String defaultValue;
-
-		MappingData(String defaultValue) {
-			this.defaultValue = defaultValue;
-		}
-
-		public String getDefaultValue() {
-			return defaultValue;
-		}
-	}
-
-	private static final Logger LOG = LoggerFactory.getLogger(SMPCasUserService.class);
-
-	private final UIUserService uiUserService;
-	private final ConfigurationService configurationService;
-
-	@Autowired
-	public SMPCasUserService(UIUserService uiUserService,
-							 ConfigurationService configurationService) {
-		this.uiUserService = uiUserService;
-		this.configurationService = configurationService;
-	}
-
-	/**
-	 * @param token The pre-authenticated authentication token from the cas SMPCas20ServiceTicketValidator
-	 * @return UserDetails for the given authentication token, never null.
-	 * @throws UsernameNotFoundException if no user details can be found for the given authentication token
-	 */
-	@Override
-	public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
-		
-		AttributePrincipal principal = token.getAssertion().getPrincipal();
-		// the cas id must match with username
-
-		String username = principal.getName();
-		LOG.info("Got CAS user with principal name: [{}]", username);
+    enum MappingData {
+        EMAIL("${email}"),
+        FULL_NAME("${firstName} ${lastName}");
+
+        private final String defaultValue;
+
+        MappingData(String defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
+        public String getDefaultValue() {
+            return defaultValue;
+        }
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(SMPCasUserService.class);
+
+    private final UIUserService uiUserService;
+    private final ConfigurationService configurationService;
+
+    @Autowired
+    public SMPCasUserService(UIUserService uiUserService,
+                             ConfigurationService configurationService) {
+        this.uiUserService = uiUserService;
+        this.configurationService = configurationService;
+    }
+
+    /**
+     * @param token The pre-authenticated authentication token from the cas SMPCas20ServiceTicketValidator
+     * @return UserDetails for the given authentication token, never null.
+     * @throws UsernameNotFoundException if no user details can be found for the given authentication token
+     */
+    @Override
+    public UserDetails loadUserDetails(CasAssertionAuthenticationToken token) throws UsernameNotFoundException {
+
+        AttributePrincipal principal = token.getAssertion().getPrincipal();
+        // the cas id must match with username
+
+        String username = principal.getName();
+        LOG.info("Got CAS user with principal name: [{}]", username);
         DBUser dbuser;
-		try {
-			dbuser = uiUserService.findUserByUsername(username);
-		} catch (SMPRuntimeException ex) {
-			if (configurationService.isCasAutomaticRegistrationEnabledForUserAuthentication()) {
-				dbuser = registerNewCasUser(principal);
-			}else {
-				throw new UsernameNotFoundException("User with the username ["+username+"] is not registered in SMP", ex);
-			}
-		}
-
-		SMPAuthority authority = SMPAuthority.getAuthorityByApplicationRole(dbuser.getApplicationRole());
-		// generate secret for the session
-		SMPUserDetails smpUserDetails = new SMPUserDetails(dbuser, SecurityUtils.generatePrivateSymmetricKey(true), Collections.singletonList(authority));
-		smpUserDetails.setCasAuthenticated(true);
-		LOG.info("Return authenticated user details for username: [{}]", username);
-		return smpUserDetails;
-	}
-
-	public DBUser registerNewCasUser(AttributePrincipal principal){
-		Map<String, Object> attributes = principal.getAttributes();
-		Map<String, String> attributesMap = configurationService.getCasAutomaticRegistrationDataMapping();
-
-		DBUser dbUser = new DBUser();
-		// update user data by admin
-		dbUser.setUsername(principal.getName());
-		dbUser.setApplicationRole(ApplicationRoleType.USER);
-		dbUser.setActive(!configurationService.isCasAutomaticRegistrationConfirmation());
-		dbUser.setEmailAddress(getValueFromCasPrincipal(MappingData.EMAIL, attributes, attributesMap));
-		dbUser.setFullName(getValueFromCasPrincipal(MappingData.FULL_NAME, attributes, attributesMap));
-		uiUserService.createDBUser(dbUser);
-		return dbUser;
-	}
-
-	protected String getValueFromCasPrincipal(MappingData data, Map<String, Object> attributes, Map<String,String> mapping){
-		String template = mapping.getOrDefault(data.name(), data.getDefaultValue());
-		return StringNamedSubstitutor.resolve(template, attributes);
-	}
+        try {
+            dbuser = uiUserService.findUserByUsername(username);
+        } catch (SMPRuntimeException ex) {
+            if (configurationService.isCasAutomaticRegistrationEnabledForUserAuthentication()) {
+                dbuser = registerNewCasUser(principal);
+            } else {
+                throw new UsernameNotFoundException("User with the username [" + username + "] is not registered in SMP", ex);
+            }
+        }
+
+        SMPAuthority authority = SMPAuthority.getAuthorityByApplicationRole(dbuser.getApplicationRole());
+        // generate secret for the session
+        SMPUserDetails smpUserDetails = new SMPUserDetails(dbuser, SecurityUtils.generatePrivateSymmetricKey(true), Collections.singletonList(authority));
+        smpUserDetails.setCasAuthenticated(true);
+        LOG.info("Return authenticated user details for username: [{}]", username);
+        return smpUserDetails;
+    }
+
+    public DBUser registerNewCasUser(AttributePrincipal principal) {
+        // convert user attributes to map of string
+        Map<String, Object> princAttr = principal.getAttributes();
+        Map<String, String> attributes = princAttr == null ? Collections.emptyMap() :
+                princAttr.entrySet()
+                        .stream()
+                        .collect(Collectors.toMap(
+                                Map.Entry::getKey,
+                                entry -> String.valueOf(entry.getValue())
+                        ));
+
+        Map<String, String> attributesMap = configurationService.getCasAutomaticRegistrationDataMapping();
+
+        DBUser dbUser = new DBUser();
+        // update user data by admin
+        dbUser.setUsername(principal.getName());
+        dbUser.setApplicationRole(ApplicationRoleType.USER);
+        dbUser.setActive(!configurationService.isCasAutomaticRegistrationConfirmation());
+        dbUser.setEmailAddress(getValueFromCasPrincipal(MappingData.EMAIL, attributes, attributesMap));
+        dbUser.setFullName(getValueFromCasPrincipal(MappingData.FULL_NAME, attributes, attributesMap));
+        uiUserService.createDBUser(dbUser);
+        return dbUser;
+    }
+
+    protected String getValueFromCasPrincipal(MappingData data, Map<String, String> attributes, Map<String, String> mapping) {
+        String template = mapping.getOrDefault(data.name(), data.getDefaultValue());
+        return StringNamedSubstitutor.resolve(template, attributes);
+    }
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ResourceController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ResourceController.java
index 32fe3f8599dab21c68836e5b4cb6aae2b5809902..361d753c7393406a7e2e032d7c968b5a57a64779 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ResourceController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/controllers/ResourceController.java
@@ -22,7 +22,7 @@ import eu.europa.ec.edelivery.smp.auth.SMPUserDetails;
 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 eu.europa.ec.edelivery.smp.security.DomainGuard;
+import eu.europa.ec.edelivery.smp.security.DomainGroupGuard;
 import eu.europa.ec.edelivery.smp.services.resource.ResourceService;
 import eu.europa.ec.edelivery.smp.servlet.ResourceAction;
 import eu.europa.ec.edelivery.smp.servlet.ResourceRequest;
@@ -68,16 +68,16 @@ public class ResourceController {
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ResourceController.class);
     // set them to lower case for fast comparing with the  http headers
     private static final List<String> SUPPORTED_HEADERS = Arrays.asList(lowerCase(HTTP_PARAM_DOMAIN),
-            lowerCase(HTTP_PARAM_OWNER),
-            lowerCase(HTTP_PARAM_OWNER_OBSOLETE),
+            lowerCase(HTTP_PARAM_ADMIN),
+            lowerCase(HTTP_PARAM_ADMIN_OBSOLETE),
             lowerCase(HTTP_PARAM_RESOURCE_GROUP),
             lowerCase(HTTP_PARAM_RESOURCE_VISIBILITY),
             lowerCase(HTTP_PARAM_RESOURCE_TYPE));
     final ResourceService resourceService;
-    final DomainGuard domainGuard;
+    final DomainGroupGuard domainGuard;
 
 
-    public ResourceController(ResourceService resourceLocatorService, DomainGuard domainGuard) {
+    public ResourceController(ResourceService resourceLocatorService, DomainGroupGuard domainGuard) {
         this.resourceService = resourceLocatorService;
         this.domainGuard = domainGuard;
     }
@@ -131,6 +131,7 @@ public class ResourceController {
         ResourceRequest resourceRequest = fromServletRequest(httpReq, pathParameters);
         LOG.debug("Got resource request [{}]", resourceRequest);
         SMPUserDetails user = authorizeForDomain(resourceRequest);
+
         ResourceResponse resourceResponse = fromServletResponse(httpRes);
         // handle the request
         resourceService.handleRequest(user, resourceRequest, resourceResponse);
@@ -152,6 +153,8 @@ public class ResourceController {
         }
         // resolve domain and test authorization for the domain.
         domainGuard.resolveAndAuthorizeForDomain(resourceRequest, user);
+        // resolve group and test authorization for the group.
+        domainGuard.resolveAndAuthorizeForGroup(resourceRequest, user);
         return user;
     }
 
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
index 7f114ab42bfa7cbaf1a38325eff69d7ed7001d4f..7cf2c175b66421ddc4f6213175949058a3ad4bcc 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/AbstractErrorControllerAdvice.java
@@ -21,9 +21,9 @@ package eu.europa.ec.edelivery.smp.error;
 
 import eu.europa.ec.dynamicdiscovery.exception.MalformedIdentifierException;
 import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
-import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
 import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -43,10 +43,7 @@ abstract class AbstractErrorControllerAdvice {
         ResponseEntity response;
         if (runtimeException instanceof SMPRuntimeException) {
             SMPRuntimeException ex = (SMPRuntimeException)runtimeException;
-            response = buildAndLog(HttpStatus.resolve(ex.getErrorCode().getHttpCode()), ex.getErrorCode().getErrorBusinessCode(), ex.getMessage(), ex);
-        } else if (runtimeException instanceof SMPResponseStatusException ){
-            SMPResponseStatusException ex = (SMPResponseStatusException)runtimeException;
-            response = buildAndLog(ex.getStatus(), ex.getErrorBusinessCode(), ex.getMessage(), ex);
+            response = buildAndLog(HttpStatus.resolve(ex.getErrorCode().getHttpCode()), ex.getErrorCode(), ex.getMessage(), ex);
         } else if (runtimeException instanceof AuthenticationException ){
             AuthenticationException ex = (AuthenticationException)runtimeException;
             response = buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage(), ex);
@@ -66,7 +63,7 @@ abstract class AbstractErrorControllerAdvice {
         }
 
 
-        String errorCodeId = response.getBody() instanceof  ErrorResponseRO?
+        String errorCodeId = response.getBody()!=null && response.getBody() instanceof  ErrorResponseRO?
                 ((ErrorResponseRO) response.getBody()).getErrorUniqueId(): null;
 
 
@@ -74,5 +71,16 @@ abstract class AbstractErrorControllerAdvice {
         return response;
     }
 
-    abstract ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception);
+
+    ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
+        return buildAndLog(status, ErrorCode.INTERNAL_ERROR_GENERIC, businessCode, msg, exception);
+    }
+
+    ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode, String msg, Exception exception) {
+        return buildAndLog(status, errorCode, errorCode.getErrorBusinessCode(), msg, exception);
+    }
+
+    abstract ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode,
+                                        ErrorBusinessCode businessCode,
+                                        String msg, Exception exception);
 }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java
index 820d148b70cde0eac99e26a7243b063f19dc0a3e..90378a504d97db1bc630a20618697b97db31a985 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ErrorResponseBuilder.java
@@ -24,6 +24,7 @@ package eu.europa.ec.edelivery.smp.error;
 import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
 import eu.europa.ec.edelivery.smp.error.xml.ErrorResponse;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.HttpStatus;
@@ -42,11 +43,10 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
  */
 public class ErrorResponseBuilder {
 
-    private static final Logger LOG = LoggerFactory.getLogger(ErrorResponseBuilder.class);
-
     public static final MediaType CONTENT_TYPE_TEXT_XML_UTF8 = MediaType.valueOf("text/xml; charset=UTF-8");
     private HttpStatus status = INTERNAL_SERVER_ERROR;
     private ErrorBusinessCode errorBusinessCode = TECHNICAL;
+    private ErrorCode errorCode = ErrorCode.INTERNAL_ERROR_GENERIC;
     private String strErrorDescription = "Unexpected technical error occurred.";
 
     private static String getErrorUniqueId() {
@@ -78,6 +78,7 @@ public class ErrorResponseBuilder {
     public ErrorResponseRO buildJSonBody() {
         ErrorResponseRO err = new ErrorResponseRO();
         err.setBusinessCode(errorBusinessCode.name());
+        err.setErrorCode(errorCode.getErrorCode());
         err.setErrorDescription(strErrorDescription);
         err.setErrorUniqueId(getErrorUniqueId());
         return err;
@@ -88,6 +89,11 @@ public class ErrorResponseBuilder {
         return this;
     }
 
+    public ErrorResponseBuilder errorCode(ErrorCode errorCode) {
+        this.errorCode = errorCode;
+        return this;
+    }
+
     public ErrorResponseBuilder errorDescription(String newErrorDescription) {
         this.strErrorDescription = newErrorDescription;
         return this;
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java
index 06df983531493c86f598aff784fd63ec943dead8..9c1161e710a6ddcb20b69dfb918a30a4ee97e955 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/ServiceErrorControllerAdvice.java
@@ -19,10 +19,10 @@
 
 package eu.europa.ec.edelivery.smp.error;
 
-import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
 import eu.europa.ec.edelivery.smp.error.xml.ErrorResponse;
 import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -44,7 +44,7 @@ import static org.springframework.http.HttpStatus.UNAUTHORIZED;
 public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice {
 
     @Override
-    @ExceptionHandler({RuntimeException.class, SMPRuntimeException.class, SMPResponseStatusException.class, AuthenticationException.class,})
+    @ExceptionHandler({RuntimeException.class, SMPRuntimeException.class,  AuthenticationException.class,})
     public ResponseEntity handleRuntimeException(RuntimeException ex) {
         return super.handleRuntimeException(ex);
     }
@@ -64,16 +64,16 @@ public class ServiceErrorControllerAdvice extends AbstractErrorControllerAdvice
         return buildAndLog(UNAUTHORIZED, ErrorBusinessCode.UNAUTHORIZED, ex.getMessage() + " - Only SMP Admin or owner of given ServiceGroup is allowed to perform this action", ex);
     }
 
-    ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
+    ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode, ErrorBusinessCode businessCode, String msg, Exception exception) {
 
         ResponseEntity response = ErrorResponseBuilder.status(status)
                 .businessCode(businessCode)
+                .errorCode(errorCode)
                 .errorDescription(msg)
                 .build();
 
         String errorUniqueId = ((ErrorResponse) response.getBody()).getErrorUniqueId();
         String logMsg = errorUniqueId == null ? "Null Error ID" : format("UI Error unique ID: %s", errorUniqueId);
-
         LOG.warn(logMsg, exception);
         return response;
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
index f35922153ba46c95a2c9d333b6cbd37edbbb8174..936294fc8f8a73aa85228435deb60831c6b100ce 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/error/UIErrorControllerAdvice.java
@@ -19,9 +19,9 @@
 package eu.europa.ec.edelivery.smp.error;
 
 import eu.europa.ec.edelivery.smp.data.ui.exceptions.ErrorResponseRO;
-import eu.europa.ec.edelivery.smp.error.exceptions.SMPResponseStatusException;
 import eu.europa.ec.edelivery.smp.exceptions.BadRequestException;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorBusinessCode;
+import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
@@ -47,17 +47,17 @@ public class UIErrorControllerAdvice extends AbstractErrorControllerAdvice {
     @ExceptionHandler({BadCredentialsException.class,
             RuntimeException.class,
             SMPRuntimeException.class,
-            SMPResponseStatusException.class,
             AuthenticationException.class,
             BadRequestException.class})
     public ResponseEntity handleRuntimeException(RuntimeException ex) {
         return super.handleRuntimeException(ex);
     }
 
-    ResponseEntity buildAndLog(HttpStatus status, ErrorBusinessCode businessCode, String msg, Exception exception) {
+    protected ResponseEntity buildAndLog(HttpStatus status, ErrorCode errorCode, ErrorBusinessCode businessCode, String msg, Exception exception) {
 
         ResponseEntity response = ErrorResponseBuilder.status(status)
                 .businessCode(businessCode)
+                .errorCode(errorCode)
                 .errorDescription(msg)
                 .buildJSon();
 
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 77f20f6dfc426355588b189bb94ab6c578e008cc..6e55c53b8caccced2cd58a6eb1e6361ee4ed0523 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
@@ -47,6 +47,7 @@ public class ResourceConstants {
     public static final String PATH_RESOURCE_TYPE_DOCUMENT = "document";
     public static final String PATH_RESOURCE_TYPE_PROPERTY = "property";
     public static final String PATH_RESOURCE_TYPE_REVIEW = "review-task";
+    public static final String PATH_RESOURCE_TYPE_REFERENCE_DOCUMENTS = "reference-documents";
 
     public static final String PATH_RESOURCE_TYPE_RESOURCE_DEFINITION = "res-def";
     /**
@@ -147,6 +148,7 @@ public class ResourceConstants {
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE_REVIEW =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_REVIEW_REQUEST;
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE_APPROVE =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_REVIEW_APPROVE;
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE_REJECT =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_REVIEW_REJECT;
+    public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE_SEARCH_REFERENCES =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE +  URL_PATH_SEPARATOR + PATH_RESOURCE_TYPE_REFERENCE_DOCUMENTS;
 
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE = PATH_RESOURCE_TYPE_SUBRESOURCE +  URL_PATH_SEPARATOR +  "{" + PATH_PARAM_ENC_SUBRESOURCE_ID + "}" +  URL_PATH_SEPARATOR + PATH_RESOURCE_TYPE_DOCUMENT;
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_VALIDATE =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_VALIDATE;
@@ -155,6 +157,7 @@ public class ResourceConstants {
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_REVIEW =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_REVIEW_REQUEST;
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_APPROVE =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_REVIEW_APPROVE;
     public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_REJECT =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE +  URL_PATH_SEPARATOR + PATH_ACTION_REVIEW_REJECT;
+    public static final String SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_SEARCH_REFERENCES =  SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE +  URL_PATH_SEPARATOR + PATH_RESOURCE_TYPE_REFERENCE_DOCUMENTS;
 
     public static final String CONTEXT_PATH_EDIT_REVIEW =  CONTEXT_PATH_EDIT +  URL_PATH_SEPARATOR + PATH_RESOURCE_TYPE_REVIEW;
     // public
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DocumentEditController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DocumentEditController.java
index 6a8cbce1ea2f253fbd7e984e4588e288fece9e8e..2be21d69245cf8092c3200624bb483d8acbe2b80 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DocumentEditController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DocumentEditController.java
@@ -22,12 +22,13 @@ package eu.europa.ec.edelivery.smp.ui.edit;
 import eu.europa.ec.edelivery.smp.auth.SMPAuthorizationService;
 import eu.europa.ec.edelivery.smp.data.enums.DocumentVersionEventType;
 import eu.europa.ec.edelivery.smp.data.ui.DocumentRO;
+import eu.europa.ec.edelivery.smp.data.ui.SearchReferenceDocumentRO;
+import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UIDocumentService;
 import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.*;
@@ -260,7 +261,6 @@ public class DocumentEditController {
                 document.getActionMessage());
     }
 
-
     @PutMapping(path = SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE,
             consumes = MimeTypeUtils.APPLICATION_JSON_VALUE,
             produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
@@ -271,12 +271,7 @@ public class DocumentEditController {
                                               @RequestBody DocumentRO document) {
         logAdminAccess("saveResourceDocument");
         Long resourceId = SessionSecurityUtils.decryptEntityId(resourceEncId);
-        Long referenceDocumentId = null;
-        String referenceDocumentEncId = document.getMetadata()!=null? document.getMetadata().getReferenceDocumentId():null;
-        if (StringUtils.isNotBlank(referenceDocumentEncId)) {
-            referenceDocumentId = SessionSecurityUtils.decryptEntityId(referenceDocumentEncId);
-        }
-        return uiDocumentService.saveDocumentForResource(resourceId, document, referenceDocumentId);
+        return uiDocumentService.saveDocumentForResource(resourceId, document);
     }
 
     @PutMapping(path = SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE,
@@ -294,6 +289,43 @@ public class DocumentEditController {
         return uiDocumentService.saveSubresourceDocumentForResource(subresourceId, resourceId, document);
     }
 
+    @PostMapping(path = SUB_CONTEXT_PATH_EDIT_DOCUMENT_RESOURCE_SEARCH_REFERENCES, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and" +
+            "@smpAuthorizationService.isResourceAdministrator(#resourceEncId)")
+    public ServiceResult<SearchReferenceDocumentRO> getDocumentReferenceList(@PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId,
+                                                                             @PathVariable(PATH_PARAM_ENC_RESOURCE_ID) String resourceEncId,
+                                                                             @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
+                                                                             @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
+                                                                             @RequestBody(required = false) SearchReferenceDocumentRO filter) {
+
+        LOG.info("Search for document reference for resource with paging: [{}/{}], user: {}", page, pageSize, userEncId);
+        Long resourceId = SessionSecurityUtils.decryptEntityId(resourceEncId);
+        String identifier = filter != null ? filter.getResourceValue() : null;
+        String scheme = filter != null ? filter.getResourceScheme() : null;
+        return uiDocumentService.getSearchReferenceDocumentListForResource(resourceId, page, pageSize, identifier, scheme);
+    }
+
+    @PostMapping(path = SUB_CONTEXT_PATH_EDIT_DOCUMENT_SUBRESOURCE_SEARCH_REFERENCES, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and" +
+            "@smpAuthorizationService.isResourceAdministrator(#resourceEncId)")
+    public ServiceResult<SearchReferenceDocumentRO> getDocumentReferenceListForSubresource(@PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId,
+                                                                                           @PathVariable(PATH_PARAM_ENC_RESOURCE_ID) String resourceEncId,
+                                                                                           @PathVariable(PATH_PARAM_ENC_SUBRESOURCE_ID) String subresourceEncId,
+                                                                                           @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
+                                                                                           @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
+                                                                                           @RequestBody(required = false) SearchReferenceDocumentRO filter) {
+
+        LOG.info("Search for document reference for subresource with paging: [{}/{}], user: {}", page, pageSize, userEncId);
+        Long resourceId = SessionSecurityUtils.decryptEntityId(resourceEncId);
+        Long subresourceId = SessionSecurityUtils.decryptEntityId(subresourceEncId);
+        String resourceValue = filter != null ? filter.getResourceValue() : null;
+        String resourceScheme = filter != null ? filter.getResourceScheme() : null;
+        String subresourceValue = filter != null ? filter.getSubresourceValue() : null;
+        String subresourceScheme = filter != null ? filter.getSubresourceScheme() : null;
+        return uiDocumentService.getSearchReferenceDocumentListForSubresource(subresourceId, resourceId, page, pageSize, resourceValue, resourceScheme, subresourceValue, subresourceScheme);
+    }
+
+
     protected void logAdminAccess(String action) {
         LOG.info(SMPLogger.SECURITY_MARKER, "Admin Domain action [{}] by user [{}], ", action, SessionSecurityUtils.getSessionUserDetails());
     }
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java
index 3b3cf2e7cccc476bd90218ae4e9238051ef7d026..86f45bba29edb1a2b324d57e89ca3ce42fa83303 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java
@@ -19,7 +19,6 @@
 package eu.europa.ec.edelivery.smp.ui.edit;
 
 
-import eu.europa.ec.edelivery.smp.config.enums.SMPDomainPropertyEnum;
 import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
 import eu.europa.ec.edelivery.smp.data.ui.*;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
@@ -86,7 +85,8 @@ public class DomainEditController {
 
 
     @GetMapping(path = SUB_CONTEXT_PATH_EDIT_DOMAIN_MEMBER, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and (@smpAuthorizationService.systemAdministrator or @smpAuthorizationService.isDomainAdministrator(#domainEncId))")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and " +
+            "(@smpAuthorizationService.systemAdministrator or @smpAuthorizationService.isDomainAdministrator(#domainEncId))")
     public ServiceResult<MemberRO> getDomainMemberList(
             @PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId,
             @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId,
@@ -100,7 +100,8 @@ public class DomainEditController {
     }
 
     @PutMapping(path = SUB_CONTEXT_PATH_EDIT_DOMAIN_MEMBER_PUT, produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and (@smpAuthorizationService.systemAdministrator or @smpAuthorizationService.isDomainAdministrator(#domainEncId))")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) " +
+            "and (@smpAuthorizationService.systemAdministrator or @smpAuthorizationService.isDomainAdministrator(#domainEncId))")
     public MemberRO putDomainMember(
             @PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId,
             @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId,
@@ -118,7 +119,8 @@ public class DomainEditController {
     }
 
     @DeleteMapping(value = SUB_CONTEXT_PATH_EDIT_DOMAIN_MEMBER_DELETE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and (@smpAuthorizationService.systemAdministrator or @smpAuthorizationService.isDomainAdministrator(#domainEncId))")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) " +
+            "and (@smpAuthorizationService.systemAdministrator or @smpAuthorizationService.isDomainAdministrator(#domainEncId))")
     public MemberRO deleteDomainMember(
             @PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId,
             @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId,
@@ -151,14 +153,17 @@ public class DomainEditController {
 
 
     /**
-     * Method returns domain properties with access rights for domain administrators.
+     * Method returns domain properties with access rights for domain administrators
+     * and group administrators to be able to configure new resources according to the domain settings.
      *
      * @param userEncId   encrypted user identifier
      * @param domainEncId the  encrypted domain identifier
      * @return list of domain properties
      */
     @GetMapping(path = SUB_CONTEXT_PATH_EDIT_DOMAIN_PROPERTIES, produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
-    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isDomainAdministrator(#domainEncId)")
+    @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and " +
+            "(@smpAuthorizationService.isDomainAdministrator(#domainEncId) " +
+            " or @smpAuthorizationService.isAnyDomainGroupAdministrator(#domainEncId))")
     public List<DomainPropertyRO> getEditDomainPropertyList(@PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId,
                                                             @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId) {
         logAdminAccess("getDomainPropertyList:" + domainEncId);
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ReviewEditController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ReviewEditController.java
index 79b5b30e342b009b37587f0f2cfc91e69d168a5a..6c15ef44b9d24405ab873bd19e986be5b1a9ce59 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ReviewEditController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ReviewEditController.java
@@ -23,7 +23,7 @@ import eu.europa.ec.edelivery.smp.data.ui.ReviewDocumentVersionRO;
 import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
-import eu.europa.ec.edelivery.smp.services.ui.UIDocumentService;
+import eu.europa.ec.edelivery.smp.services.ui.UIReviewService;
 import eu.europa.ec.edelivery.smp.ui.ResourceConstants;
 import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -45,10 +45,10 @@ import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*;
 public class ReviewEditController {
 
     private static final SMPLogger LOG = SMPLoggerFactory.getLogger(ReviewEditController.class);
-    private final UIDocumentService uiDocumentService;
+    private final UIReviewService reviewService;
 
-    public ReviewEditController(UIDocumentService uiDocumentService) {
-        this.uiDocumentService = uiDocumentService;
+    public ReviewEditController(UIReviewService reviewService) {
+        this.reviewService = reviewService;
     }
 
     /**
@@ -75,7 +75,7 @@ public class ReviewEditController {
         LOG.info("Search for page: {}, page size: {}", page, pageSize);
         Long userId = SessionSecurityUtils.decryptEntityId(encUserId);
         // set filter to current user
-        return uiDocumentService.getDocumentReviewListForUser(userId, page, pageSize, orderBy, orderType, filter);
+        return reviewService.getDocumentReviewListForUser(userId, page, pageSize, orderBy, orderType, filter);
     }
 }
 
diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainController.java
index 1d8a428fccb6446f3874741ac2c15612cebd388b..6572bfce540ac7a8f03629584cb0f863380441c7 100644
--- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainController.java
+++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/DomainController.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -24,7 +24,6 @@ import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.services.ui.UIDomainEditService;
-import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
 import org.springframework.util.MimeTypeUtils;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -34,7 +33,7 @@ import org.springframework.web.bind.annotation.RestController;
 import static eu.europa.ec.edelivery.smp.ui.ResourceConstants.*;
 
 /**
- * Purpose of the DomainResource is to provide public methoda to retrieve configured domains in SMP.
+ * Purpose of the DomainResource is to provide public method to retrieve configured domains in SMP.
  *
  * @author Joze Rihtarsic
  * @since 4.1
@@ -57,15 +56,8 @@ public class DomainController {
     public ServiceResult<DomainPublicRO> getDomainList(
             @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page,
             @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize,
-            @RequestParam(value = PARAM_PAGINATION_ORDER_BY, required = false) String orderBy,
-            @RequestParam(value = PARAM_PAGINATION_ORDER_TYPE, defaultValue = "asc", required = false) String orderType,
             @RequestParam(value = PARAM_QUERY_USER, required = false) String user) {
-
         LOG.info("Search for page: {}, page size: {}, user: {}", page, pageSize, user);
-        return uiDomainService.getTableList(page, pageSize, orderBy, orderType, null);
-    }
-
-    protected void logAdminAccess(String action) {
-        LOG.info(SMPLogger.SECURITY_MARKER, "Admin Domain action [{}] by user [{}], ", action, SessionSecurityUtils.getSessionUserDetails());
+        return uiDomainService.getUserPermittedDomains(page, pageSize);
     }
 }
diff --git a/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl b/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl
index ca073b2a7e19e543667c036b4c3f0f93372c540a..711c1f2e40bdba1c28a336ef09038ee5f861ff58 100644
--- a/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl
+++ b/smp-webapp/src/main/smp-setup/database-scripts/mysql5innodb.ddl
@@ -164,6 +164,7 @@
         CURRENT_VERSION integer not null,
         MIME_TYPE varchar(128)  CHARACTER SET utf8 COLLATE utf8_bin,
         NAME varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin,
+        REF_DOCUMENT_URL varchar(1024)  CHARACTER SET utf8 COLLATE utf8_bin,
         SHARING_ENABLED bit,
         FK_REF_DOCUMENT_ID bigint,
         primary key (ID)
@@ -178,6 +179,7 @@
         CURRENT_VERSION integer,
         MIME_TYPE varchar(128)  CHARACTER SET utf8 COLLATE utf8_bin,
         NAME varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin,
+        REF_DOCUMENT_URL varchar(1024)  CHARACTER SET utf8 COLLATE utf8_bin,
         SHARING_ENABLED bit,
         FK_REF_DOCUMENT_ID bigint,
         primary key (ID, REV)
@@ -241,6 +243,7 @@
         EVENT_ON datetime comment 'Date time of the event',
         EVENT_SOURCE varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin not null comment 'Event source UI, API',
         EVENT_TYPE varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin not null comment 'Document version event type',
+        EVENT_STATUS varchar(255)  CHARACTER SET utf8 COLLATE utf8_bin not null comment 'Document version event type',
         EVENT_BY_USERNAME varchar(64)  CHARACTER SET utf8 COLLATE utf8_bin comment 'username identifier of the user who triggered the event',
         FK_DOCUMENT_VERSION_ID bigint,
         primary key (ID)
@@ -610,9 +613,6 @@
     alter table SMP_CREDENTIAL 
        add constraint SMP_CRD_USER_NAME_TYPE_IDX unique (CREDENTIAL_NAME, CREDENTIAL_TYPE, CREDENTIAL_TARGET);
 
-    alter table SMP_CREDENTIAL 
-       add constraint SMP_CRD_USER_NAME_RESET_IDX unique (RESET_TOKEN, CREDENTIAL_TYPE, CREDENTIAL_TARGET);
-
     alter table SMP_DOCUMENT_PROPERTY 
        add constraint SMP_DOC_PROP_IDX unique (FK_DOCUMENT_ID, PROPERTY_NAME);
 create index SMP_DOCVER_DOCUMENT_IDX on SMP_DOCUMENT_VERSION (FK_DOCUMENT_ID);
diff --git a/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl b/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl
index f7156c6dfdcc4c29dd03ee72ced09f7e3f62506f..0db20288a7c6524f1f34f6637a5918c10b96c9a4 100644
--- a/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl
+++ b/smp-webapp/src/main/smp-setup/database-scripts/oracle10g.ddl
@@ -284,6 +284,7 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
         CURRENT_VERSION number(10,0) not null,
         MIME_TYPE varchar2(128 char),
         NAME varchar2(255 char),
+        REF_DOCUMENT_URL varchar2(1024 char),
         SHARING_ENABLED number(1,0),
         FK_REF_DOCUMENT_ID number(19,0),
         primary key (ID)
@@ -304,6 +305,7 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
         CURRENT_VERSION number(10,0),
         MIME_TYPE varchar2(128 char),
         NAME varchar2(255 char),
+        REF_DOCUMENT_URL varchar2(1024 char),
         SHARING_ENABLED number(1,0),
         FK_REF_DOCUMENT_ID number(19,0),
         primary key (ID, REV)
@@ -385,6 +387,7 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
         EVENT_ON timestamp,
         EVENT_SOURCE varchar2(255 char) not null,
         EVENT_TYPE varchar2(255 char) not null,
+        EVENT_STATUS varchar2(255 char) not null,
         EVENT_BY_USERNAME varchar2(64 char),
         FK_DOCUMENT_VERSION_ID number(19,0),
         primary key (ID)
@@ -408,6 +411,9 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
     comment on column SMP_DOCUMENT_VERSION_EVENT.EVENT_TYPE is
         'Document version event type';
 
+    comment on column SMP_DOCUMENT_VERSION_EVENT.EVENT_STATUS is
+        'Document version event type';
+
     comment on column SMP_DOCUMENT_VERSION_EVENT.EVENT_BY_USERNAME is
         'username identifier of the user who triggered the event';
 
@@ -910,9 +916,6 @@ create sequence SMP_USER_SEQ start with 1 increment by  1;
     alter table SMP_CREDENTIAL 
        add constraint SMP_CRD_USER_NAME_TYPE_IDX unique (CREDENTIAL_NAME, CREDENTIAL_TYPE, CREDENTIAL_TARGET);
 
-    alter table SMP_CREDENTIAL 
-       add constraint SMP_CRD_USER_NAME_RESET_IDX unique (RESET_TOKEN, CREDENTIAL_TYPE, CREDENTIAL_TARGET);
-
     alter table SMP_DOCUMENT_PROPERTY 
        add constraint SMP_DOC_PROP_IDX unique (FK_DOCUMENT_ID, PROPERTY_NAME);
 create index SMP_DOCVER_DOCUMENT_IDX on SMP_DOCUMENT_VERSION (FK_DOCUMENT_ID);
diff --git a/smp-webapp/src/main/smp-setup/smp.config.properties b/smp-webapp/src/main/smp-setup/smp.config.properties
index 356e5937b71838ac4a746d69c28785c21616aca7..29e87fa26a2875b9dfa74efd8f4efbfb9c2be2df 100644
--- a/smp-webapp/src/main/smp-setup/smp.config.properties
+++ b/smp-webapp/src/main/smp-setup/smp.config.properties
@@ -62,8 +62,11 @@ smp.jdbc.password=secret123
 # Extension folder
 # *********************************
 # path where SMP extensions are located. The Folder is loaded by the SMP classloader at startup.
-# smp.libraries.folder=/cef/test/smp/apache-tomcat-8.5.73/smp/ext-lib
-
-
+# smp.libraries.folder=/data/smp/ext-lib
 
 
+# *********************************
+# Locale folder
+# *********************************
+# The locale folder contains the translations for the SMP web application.
+# smp.libraries.folder=/data/smp/locales
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSingleDomainTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSingleDomainTest.java
index d4ac2abef468cf625cf719752ed64b788b1fe55b..99fa8bc75544a3ae054c4df2d482d26eaf77de1b 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSingleDomainTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSingleDomainTest.java
@@ -53,7 +53,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
 
     private static final String SERVICE_GROUP_INPUT_BODY = getSampleServiceGroupBodyWithScheme(IDENTIFIER_SCHEME);
     private static final String HTTP_HEADER_KEY_DOMAIN = "Domain";
-    private static final String HTTP_HEADER_KEY_SERVICE_GROUP_OWNER = "ServiceGroup-Owner";
+    private static final String HTTP_HEADER_KEY_SERVICE_GROUP_OWNER = "Resource-Admin";
     private static final String HTTP_HEADER_KEY_RESOURCE_GROUP = "Resource-Group";
     private static final String HTTP_HEADER_KEY_RESOURCE_VISIBILITY = "Resource-Visibility";
     private static final String OTHER_OWNER_NAME = "CN=EHEALTH_SMP_TEST_BRAZIL,O=European Commission,C=BE:48b681ee8e0dcc08";
@@ -64,7 +64,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
     }
 
     @Test
-    void adminCanCreateServiceGroupNoDomain() throws Exception {
+    void adminCanCreateResourceNoDomain() throws Exception {
         mvc.perform(put(URL_PATH)
                         .with(ADMIN_CREDENTIALS)
                         .contentType(APPLICATION_XML_VALUE)
@@ -85,7 +85,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
             "'Set owner username: OK', 200, test_pat_hashed_pass, 123456,'test_user_hashed_pass'",
             "'Set owner user, but admin updates: Fail', 401, test_pat_hashed_pass, 123456,'pat_smp_admin'",
     })
-    void groupAdminCanUpdateServiceGroupNoDomain(String desc, int expectedStatus,
+    void groupAdminCanUpdateResourceNoDomain(String desc, int expectedStatus,
                                                  String resourceAdminATId, String groupResourceATSecret,
                                                  String resourceOwnerId) throws Exception {
         LOG.info(desc);
@@ -110,7 +110,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
     }
 
     @Test
-    void addServiceGroupWithUTF8() throws Exception {
+    void addResourceWithUTF8() throws Exception {
         String resourceLocation = "/input/ServiceGroupWithUTF8.xml";
         LOG.info(resourceLocation);
 
@@ -128,7 +128,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
     }
 
     @Test
-    void anonymousUserCannotCreateServiceGroup() throws Exception {
+    void anonymousUserCannotCreateResource() throws Exception {
         mvc.perform(put(URL_PATH)
                         .contentType(APPLICATION_XML_VALUE)
                         .content(SERVICE_GROUP_INPUT_BODY))
@@ -161,7 +161,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
     }
 
     @Test
-    void creatingServiceGroupUnderBadFormattedDomainReturnsBadRequestNoDomain() throws Exception {
+    void creatingResourceUnderBadFormattedDomainReturnsBadRequestNoDomain() throws Exception {
         mvc.perform(put(URL_PATH)
                         .with(ADMIN_CREDENTIALS)
                         .contentType(APPLICATION_XML_VALUE)
@@ -172,7 +172,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
     }
 
     @Test
-    void creatingServiceGroupUnderNotExistingDomainReturnsBadRequestNoDomain() throws Exception {
+    void creatingResourceUnderNotExistingDomainReturnsBadRequestNoDomain() throws Exception {
         mvc.perform(put(URL_PATH)
                         .with(ADMIN_CREDENTIALS)
                         .contentType(APPLICATION_XML_VALUE)
@@ -183,7 +183,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
     }
 
     @Test
-    void adminCanAssignNewServiceGroupToOtherOwnerNoDomain() throws Exception {
+    void adminCanAssignNewResourceToOtherOwnerNoDomain() throws Exception {
         mvc.perform(put(URL_PATH)
                         .with(ADMIN_CREDENTIALS)
                         .contentType(APPLICATION_XML_VALUE)
@@ -198,7 +198,7 @@ public class ResourceControllerSingleDomainTest extends AbstractControllerTest {
             "Existing group:,'domain group',201",
             "Existing group 2:,'Third group',201",
             "Not authorized for domain:,'Second group',401",
-            "Not authorized for non existing domain:,'Not exists group',401"})
+            "Not authorized for non existing domain:,'Not exists group',404"})
     void createResourceForGroup(String testDesc, String groupName, int httpCode) throws Exception {
 
         LOG.info(testDesc);
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSubResourceTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSubResourceTest.java
index 5c881147a7863b585914d785a88be9db2cd2b141..0146b1298d08caf08e8eff1a2ca90f70240c06db 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSubResourceTest.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/controllers/ResourceControllerSubResourceTest.java
@@ -8,9 +8,9 @@
  * versions of the EUPL (the "Licence");
  * You may not use this work except in compliance with the Licence.
  * You may obtain a copy of the Licence at:
- * 
+ *
  * [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software distributed under the Licence is
  * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the Licence for the specific language governing permissions and limitations under the Licence.
@@ -18,6 +18,7 @@
  */
 package eu.europa.ec.edelivery.smp.controllers;
 
+import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
 import eu.europa.ec.edelivery.smp.servlet.WebConstants;
 import eu.europa.ec.edelivery.smp.ui.AbstractControllerTest;
 import org.junit.jupiter.api.BeforeEach;
@@ -34,6 +35,8 @@ import java.io.IOException;
 
 import static eu.europa.ec.edelivery.smp.ServiceGroupBodyUtil.generateServiceMetadata;
 import static eu.europa.ec.edelivery.smp.ServiceGroupBodyUtil.getSampleServiceGroupBody;
+import static eu.europa.ec.edelivery.smp.server.security.SecurityConfigurationTest.PASSWORD;
+import static eu.europa.ec.edelivery.smp.server.security.SecurityConfigurationTest.TEST_USERNAME_DB_HASHED_PASS;
 import static org.springframework.http.MediaType.APPLICATION_XML_VALUE;
 import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
@@ -46,13 +49,65 @@ public class ResourceControllerSubResourceTest extends AbstractControllerTest {
 
     private static final String IDENTIFIER_SCHEME = "ehealth-participantid-qns";
     private static final String DOCUMENT_SCHEME = "doctype";
+    public static final String GROUP_01 = "domain group";
+    public static final String GROUP_02 = "Second group";
+    public static final String GROUP_03 = "Third group";
 
 
     @BeforeEach
-    public void setup() throws IOException {
+    public void setupController() throws IOException {
+        // for database setup check the webapp_integration_test_data.sql
         super.setup();
     }
 
+
+    /**
+     * Test get permissions for resource with different creation parameters. The user data match
+     * the data in the database: webapp_integration_test_data.sql
+     */
+    @ParameterizedTest
+    @CsvSource({"'Get with same user as resource admin: OK', 200, pat_smp_admin, 123456, pat_smp_admin, 123456, ''",
+            "'Non resource memeber is trying to get it ', 401, pat_smp_admin, 123456, test_pat_hashed_pass, 123456,''",
+            "'Resource member with bad password, bad credentials: Fail', 401, pat_smp_admin, 123456, pat_smp_admin, 000000,''",
+            "'Set same Owner as admin user: OK', 200, pat_smp_admin, 123456, pat_smp_admin, 123456,'pat_smp_admin'",
+            "'Set resource owner user: OK', 200, test_pat_hashed_pass, 123456, test_pat_hashed_pass, 123456,'test_user_hashed_pass'",
+            "'Legacy: Set owner user, but default admin owner deletes: OK', 200, test_pat_hashed_pass, 123456, pat_smp_admin, 123456, 'test_pat_hashed_pass'",
+    })
+    void getPrivateSubResourcePermissions(String desc, int expectedStatus,
+                                          String resourceAdminCreateATId, String resourceCreateATSecret,
+                                          String getUserATId, String getUserPassword,
+                                          String resourceOwnerId) throws Exception {
+        LOG.info(desc);
+
+        String xmlSG = getSampleServiceGroupBody(IDENTIFIER_SCHEME, PARTICIPANT_ID);
+        String xmlMD = generateServiceMetadata(PARTICIPANT_ID, IDENTIFIER_SCHEME, DOCUMENT_ID, DOCUMENT_SCHEME, "test");
+        // owner headers
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add(WebConstants.HTTP_PARAM_RESOURCE_VISIBILITY, VisibilityType.PRIVATE.name());
+        if (StringUtils.isNotBlank(resourceOwnerId)) {
+            httpHeaders.add(WebConstants.HTTP_PARAM_ADMIN, resourceOwnerId);
+        }
+        // crate service group
+        mvc.perform(put(URL_PATH)
+                        .with(ADMIN_CREDENTIALS)
+                        .headers(httpHeaders)
+                        .contentType(APPLICATION_XML_VALUE)
+                        .content(xmlSG))
+                .andExpect(status().isCreated());
+        // add subresource/service-metadata with appropriate owner
+        mvc.perform(put(URL_DOC_PATH)
+                        .with(httpBasic(resourceAdminCreateATId, resourceCreateATSecret))
+                        .contentType(APPLICATION_XML_VALUE)
+                        .content(xmlMD))
+                .andExpect(status().isCreated());
+
+        // get subresource/service-metadata with test owner
+        mvc.perform(get(URL_DOC_PATH)
+                        .with(httpBasic(getUserATId, getUserPassword)))
+                .andExpect(status().is(expectedStatus));
+    }
+
+
     /**
      * Test update permissions for resource with different creation parameters. The user data match
      * the data in the database: webapp_integration_test_data.sql
@@ -76,7 +131,7 @@ public class ResourceControllerSubResourceTest extends AbstractControllerTest {
         // owner headers
         HttpHeaders httpHeaders = new HttpHeaders();
         if (StringUtils.isNotBlank(resourceOwnerId)) {
-            httpHeaders.add(WebConstants.HTTP_PARAM_OWNER, resourceOwnerId);
+            httpHeaders.add(WebConstants.HTTP_PARAM_ADMIN, resourceOwnerId);
         }
         // crate service group
         mvc.perform(put(URL_PATH)
@@ -117,7 +172,7 @@ public class ResourceControllerSubResourceTest extends AbstractControllerTest {
         // owner headers
         HttpHeaders httpHeaders = new HttpHeaders();
         if (StringUtils.isNotBlank(resourceOwnerId)) {
-            httpHeaders.add(WebConstants.HTTP_PARAM_OWNER, resourceOwnerId);
+            httpHeaders.add(WebConstants.HTTP_PARAM_ADMIN, resourceOwnerId);
         }
         // crate service group
         mvc.perform(put(URL_PATH)
@@ -139,6 +194,92 @@ public class ResourceControllerSubResourceTest extends AbstractControllerTest {
                 .andExpect(status().is(expectedStatus));
     }
 
+    /**
+     * Test update permissions for resource with different creation parameters. The user data match
+     * the data in the database: webapp_integration_test_data.sql
+     */
+    @ParameterizedTest
+    @CsvSource({"'The right group: OK', 201, 'Third group'",
+            "'Wrong group', 401, 'domain group'",
+            "'Group not exists', 404, 'NotExits'",
+            "'If group is not given it figures it out the right group', 201, ''",
+    })
+    void createSubResourceForGroupPermissions(String desc, int expectedStatus,
+                                              String targetGroup) throws Exception {
+        LOG.info(desc);
+
+        String xmlSG = getSampleServiceGroupBody(IDENTIFIER_SCHEME, PARTICIPANT_ID);
+        String xmlMD = generateServiceMetadata(PARTICIPANT_ID, IDENTIFIER_SCHEME, DOCUMENT_ID, DOCUMENT_SCHEME, "test");
+        // owner headers and group
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add(WebConstants.HTTP_PARAM_ADMIN, TEST_USERNAME_DB_HASHED_PASS);
+        httpHeaders.add(WebConstants.HTTP_PARAM_RESOURCE_GROUP, GROUP_03);
+
+        // crate service group
+        mvc.perform(put(URL_PATH)
+                        .with(ADMIN_CREDENTIALS)
+                        .headers(httpHeaders)
+                        .contentType(APPLICATION_XML_VALUE)
+                        .content(xmlSG))
+                .andExpect(status().isCreated());
+        // add subresource/service-metadata with owner user
+        HttpHeaders httpHeadersTest = new HttpHeaders();
+        httpHeadersTest.add(WebConstants.HTTP_PARAM_RESOURCE_GROUP, targetGroup);
+        mvc.perform(put(URL_DOC_PATH)
+                        .with(httpBasic(TEST_USERNAME_DB_HASHED_PASS, PASSWORD))
+                        .headers(httpHeadersTest)
+                        .contentType(APPLICATION_XML_VALUE)
+                        .content(xmlMD))
+                .andExpect(status().is(expectedStatus));
+    }
+
+    /**
+     * Test update permissions for resource with different creation parameters. The user data match
+     * the data in the database: webapp_integration_test_data.sql
+     */
+    @ParameterizedTest
+    @CsvSource({"'The right group: OK', 200, 'Third group'",
+            "'Wrong group not allowed', 401, 'domain group'",
+            "'Group not exists', 404, 'NotExits'",
+            "'If group is not given it figures it out the right group', 200, ''",
+    })
+    void deleteSubResourceForGroupPermissions(String desc, int expectedStatus,
+                                              String targetGroup) throws Exception {
+        LOG.info(desc);
+
+        String xmlSG = getSampleServiceGroupBody(IDENTIFIER_SCHEME, PARTICIPANT_ID);
+        String xmlMD = generateServiceMetadata(PARTICIPANT_ID, IDENTIFIER_SCHEME, DOCUMENT_ID, DOCUMENT_SCHEME, "test");
+        // owner headers
+        HttpHeaders httpHeaders = new HttpHeaders();
+        httpHeaders.add(WebConstants.HTTP_PARAM_ADMIN, TEST_USERNAME_DB_HASHED_PASS);
+        httpHeaders.add(WebConstants.HTTP_PARAM_RESOURCE_GROUP, GROUP_03);
+        // crate service group
+        mvc.perform(put(URL_PATH)
+                        .with(ADMIN_CREDENTIALS)
+                        .headers(httpHeaders)
+                        .contentType(APPLICATION_XML_VALUE)
+                        .content(xmlSG))
+                .andExpect(status().isCreated());
+        // add subresource/service-metadata with appropriate owner and group
+        HttpHeaders httpHeadersTestCreateSubR = new HttpHeaders();
+        httpHeadersTestCreateSubR.add(WebConstants.HTTP_PARAM_RESOURCE_GROUP, GROUP_03);
+        mvc.perform(put(URL_DOC_PATH)
+                        .with(httpBasic(TEST_USERNAME_DB_HASHED_PASS, PASSWORD))
+                        .headers(httpHeadersTestCreateSubR)
+                        .contentType(APPLICATION_XML_VALUE)
+                        .content(xmlMD))
+                .andExpect(status().isCreated());
+
+        // delete subresource/service-metadata with test owner
+        // add subresource/service-metadata with owner user
+        HttpHeaders httpHeadersTest = new HttpHeaders();
+        httpHeadersTest.add(WebConstants.HTTP_PARAM_RESOURCE_GROUP, targetGroup);
+        mvc.perform(delete(URL_DOC_PATH)
+                        .with(httpBasic(TEST_USERNAME_DB_HASHED_PASS, PASSWORD))
+                        .headers(httpHeadersTest))
+                .andExpect(status().is(expectedStatus));
+    }
+
     @Test
     void existingSubResourceCanBeRetrievedByEverybodyNoDomain() throws Exception {
 
diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIT.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIT.java
index c71840dd602d781962c536b8c8ca88183b97924e..c527707146c8d1266a91fbdbc4d879842a4e37ce 100644
--- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIT.java
+++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/ui/external/DomainResourceIT.java
@@ -90,7 +90,9 @@ class DomainResourceIT {
 
 
         assertNotNull(res);
-        assertEquals(2, res.getServiceEntities().size());
+        // there are two  public domains in the database but only one has resources
+        // see EDELIVERY-13793
+        assertEquals(1, res.getServiceEntities().size());
         res.getServiceEntities().forEach(sgMap -> {
             DomainRO sgro = mapper.convertValue(sgMap, DomainRO.class);
             assertNotNull(sgro.getDomainCode());