diff --git a/domismp-tests/domismp-tests-api/groovy/mysql-4.1_integration_test_data.sql b/domismp-tests/domismp-tests-api/groovy/mysql-4.1_integration_test_data.sql index 43e74e7ab56aa77a1a9188be0bed4efdbc767654..5670eba3f947efcd9fa9cb76baf13401c072fd1e 100644 --- a/domismp-tests/domismp-tests-api/groovy/mysql-4.1_integration_test_data.sql +++ b/domismp-tests/domismp-tests-api/groovy/mysql-4.1_integration_test_data.sql @@ -49,7 +49,7 @@ insert into SMP_EXTENSION ( ID, IDENTIFIER, IMPLEMENTATION_NAME, NAME, VERSION, insert into SMP_RESOURCE_DEF ( ID, FK_EXTENSION_ID, URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values (1, 1, 'smp-1', 'edelivery-oasis-smp-1.0-servicegroup', 'Oasis SMP 1.0 ServiceGroup', 'text/xml','Oasis SMP 1.0 ServiceGroup', NOW(), NOW()), -(2, 1, 'oasis-bdxr-smp-2', 'edelivery-oasis-smp-2.0-servicegroup', 'Oasis SMP 2.0 ServiceGroup', 'text/xml','Oasis SMP 2.0 ServiceGroup', NOW(), NOW()); +(2, 1, 'bdxr-smp-2', 'edelivery-oasis-smp-2.0-servicegroup', 'Oasis SMP 2.0 ServiceGroup', 'text/xml','Oasis SMP 2.0 ServiceGroup', NOW(), NOW()); insert into SMP_SUBRESOURCE_DEF (ID,FK_RESOURCE_DEF_ID,URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values (1,1, 'services', 'edelivery-oasis-smp-1.0-servicemetadata', 'Oasis SMP 1.0 ServiceMetadata', 'text/xml','Oasis SMP 1.0 ServiceMetadata', NOW(), NOW()), diff --git a/domismp-tests/domismp-tests-api/groovy/oracle-4.1_integration_test_data.sql b/domismp-tests/domismp-tests-api/groovy/oracle-4.1_integration_test_data.sql index 4d59b98edc60254beeebf2f6214bb68cbef86501..f628771f4b2a47647856c8e37d1ff49e4222c338 100644 --- a/domismp-tests/domismp-tests-api/groovy/oracle-4.1_integration_test_data.sql +++ b/domismp-tests/domismp-tests-api/groovy/oracle-4.1_integration_test_data.sql @@ -120,7 +120,7 @@ insert into SMP_EXTENSION ( ID, IDENTIFIER, IMPLEMENTATION_NAME, NAME, VERSION, insert into SMP_RESOURCE_DEF ( ID, FK_EXTENSION_ID, URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values (1, 1, 'smp-1', 'edelivery-oasis-smp-1.0-servicegroup', 'Service group', 'text/xml','Oasis SMP ServiceGroup', sysdate, sysdate); insert into SMP_RESOURCE_DEF ( ID, FK_EXTENSION_ID, URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values -(2, 1, 'oasis-bdxr-smp-2', 'edelivery-oasis-smp-2.0-servicegroup', 'Oasis SMP 2.0 ServiceGroup', 'text/xml','Oasis SMP 2.0 ServiceGroup', sysdate, sysdate); +(2, 1, 'bdxr-smp-2', 'edelivery-oasis-smp-2.0-servicegroup', 'Oasis SMP 2.0 ServiceGroup', 'text/xml','Oasis SMP 2.0 ServiceGroup', sysdate, sysdate); insert into SMP_SUBRESOURCE_DEF (ID,FK_RESOURCE_DEF_ID,URL_SEGMENT, IDENTIFIER, DESCRIPTION, MIME_TYPE, NAME, CREATED_ON, LAST_UPDATED_ON) values (1,1, 'services', 'edelivery-oasis-smp-1.0-servicemetadata', 'ServiceMetadata', 'text/xml','Oasis SMP ServiceMetadata', sysdate, sysdate); diff --git a/smp-angular/src/app/app.component.ts b/smp-angular/src/app/app.component.ts index dd6f64b5d557c7ad908de5dd8308b486728b7af5..fd3eb7802e2c9d5da2501a3be2d32e7bdd6739ed 100644 --- a/smp-angular/src/app/app.component.ts +++ b/smp-angular/src/app/app.component.ts @@ -1,8 +1,10 @@ -import {Component, ViewChild} from '@angular/core'; +import {Component, HostListener, ViewChild} from '@angular/core'; import {SecurityService} from './security/security.service'; import {Router} from '@angular/router'; import {Authority} from "./security/authority.model"; -import {AlertMessageService} from "./common/alert-message/alert-message.service"; +import { + AlertMessageService +} from "./common/alert-message/alert-message.service"; import {MatDialog} from "@angular/material/dialog"; import {GlobalLookups} from "./common/global-lookups"; import {HttpClient} from "@angular/common/http"; @@ -92,7 +94,7 @@ export class AppComponent { this.alertService.clearAlert(); } - onDrawerContentScroll(scrollEvent: any){ + onDrawerContentScroll(scrollEvent: any) { let scrollTop = scrollEvent.srcElement.scrollTop; this.alertService.setKeepAfterNavigationChange(scrollTop > 0) } @@ -100,4 +102,34 @@ export class AppComponent { get showSpinner(): boolean { return this.windowSpinnerService.showSpinner } + +// Listeners for activity monitoring +// Every time one of these events are triggered, all the "watches" are reseted + @HostListener('window:mousemove') + mouseMove() { + this.refreshUserState(); + } + + @HostListener('keydown') + keyboardClick() { + this.refreshUserState(); + } + + @HostListener('touchstart') + screenTouched() { + this.refreshUserState(); + } + + @HostListener('touchmove') + screenDragged() { + this.refreshUserState(); + } + + refreshUserState() { + // if user is not logged in, do nothing + if (!this.securityService.isAuthenticated(false)) { + return; + } + this.securityService.uiUserActivityDetected() + } } diff --git a/smp-angular/src/app/common/global-lookups.ts b/smp-angular/src/app/common/global-lookups.ts index d5a29a494fec7cd39dab49a97e28110afebfd027..05e02efc2fbc89b4b94a7d2543a4e62d9573fd5a 100644 --- a/smp-angular/src/app/common/global-lookups.ts +++ b/smp-angular/src/app/common/global-lookups.ts @@ -115,7 +115,6 @@ export class GlobalLookups { console.log("getSmpInfo:" + err); } }); - } public refreshApplicationConfiguration() { diff --git a/smp-angular/src/app/common/search-table/search-table-entity.model.ts b/smp-angular/src/app/common/search-table/search-table-entity.model.ts index 92b09f28fa73142c74541133385c46fc7718c0c2..bea9b54e20c392681e37b83b38cad118fa1c3b9e 100644 --- a/smp-angular/src/app/common/search-table/search-table-entity.model.ts +++ b/smp-angular/src/app/common/search-table/search-table-entity.model.ts @@ -1,10 +1,11 @@ import {EntityStatus} from '../enums/entity-status.enum'; +import {VisibilityEnum} from "../enums/visibility.enum"; export interface SearchTableEntity { id?: number; index?: number; status?: EntityStatus; deleted?: boolean; - + visibility?: VisibilityEnum; actionMessage?: string; } diff --git a/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts b/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts index ee27b6546e67e6177a7447e3aa964ba524dace66..660c3f7387de4fb7e12783f1146aa9f4f1ca30b0 100644 --- a/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts +++ b/smp-angular/src/app/edit/edit-domain/domain-group-panel/domain-group.component.ts @@ -29,6 +29,9 @@ import {lastValueFrom} from "rxjs"; import { SmpTableColDef } from "../../../common/components/smp-table/smp-table-coldef.model"; +import { + EditResourceController +} from "../../edit-resources/edit-resource.controller"; @Component({ selector: 'domain-group-panel', @@ -52,6 +55,7 @@ export class DomainGroupComponent implements OnInit, BeforeLeaveGuard { selectedGroup: GroupRo; constructor(private editDomainService: EditDomainService, + private editResourceController: EditResourceController, private alertService: AlertMessageService, private dialog: MatDialog, private formBuilder: FormBuilder, @@ -216,6 +220,7 @@ export class DomainGroupComponent implements OnInit, BeforeLeaveGuard { if (result) { this.alertService.success(await lastValueFrom(this.translateService.get("domain.group.success.delete", {groupName: result.groupName}))); this.onGroupSelected(null); + this.editResourceController.dataChanged = true; this.refresh() } }, (error) => { 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 6f24f1b9b81c12356f7607c3f3227dce511b99c8..4368213e44e4ed1d6d25d4dafa06af930bc352a8 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 @@ -6,6 +6,9 @@ import {AlertMessageService} from "../../../../common/alert-message/alert-messag import {VisibilityEnum} from "../../../../common/enums/visibility.enum"; import {GroupRo} from "../../../../common/model/group-ro.model"; import {EditDomainService} from "../../edit-domain.service"; +import { + EditResourceController +} from "../../../edit-resources/edit-resource.controller"; @Component({ @@ -29,6 +32,7 @@ export class GroupDialogComponent { constructor(@Inject(MAT_DIALOG_DATA) public data: any, private editDomainService: EditDomainService, + private editResourceController: EditResourceController, public dialogRef: MatDialogRef<GroupDialogComponent>, private alertService: AlertMessageService, private formBuilder: FormBuilder @@ -112,6 +116,7 @@ export class GroupDialogComponent { this.editDomainService.createDomainGroupObservable(this._currentDomain.domainId, group).subscribe((group: GroupRo) => { if (!!group) { + this.editResourceController.dataChanged = true; this.closeDialog(); } }, (error) => { @@ -126,6 +131,7 @@ export class GroupDialogComponent { public saveGroup(group: GroupRo) { this.editDomainService.saveDomainGroupObservable(this._currentDomain.domainId, group).subscribe((group: GroupRo) => { if (!!group) { + this.editResourceController.dataChanged = true; this.closeDialog(); } }, (error) => { 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 326d15ef158a4c232a8bbd0c7243a810f50123f6..1901c0cdb5641392992bcc39c4d3b505ae16fe7f 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 @@ -34,6 +34,9 @@ import {MatTableDataSource} from "@angular/material/table"; import { SmpTableColDef } from "../../../common/components/smp-table/smp-table-coldef.model"; +import { + EditResourceController +} from "../../edit-resources/edit-resource.controller"; @Component({ selector: 'group-resource-panel', @@ -58,6 +61,7 @@ export class GroupResourcePanelComponent implements BeforeLeaveGuard { columns: SmpTableColDef[]; constructor(private editGroupService: EditGroupService, + private editResourceController: EditResourceController, private alertService: AlertMessageService, private dialog: MatDialog, private translateService: TranslateService) { @@ -220,6 +224,7 @@ export class GroupResourcePanelComponent implements BeforeLeaveGuard { this.editGroupService.deleteResourceFromGroup(resource, this._group, this.domain) .pipe( finalize(() => { + this.editResourceController.dataChanged = true; this.refresh(); this.isLoadingResults = false; })) 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 b2595a6a3cefd8b5e3affed7e8275d8e6e5cd04d..44f48e5c40c6c5cf051e2624a0303327a352075e 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 @@ -31,6 +31,9 @@ import { DomainPropertyRo } from "../../../../common/model/domain-property-ro.model"; import {Subscription} from "rxjs"; +import { + EditResourceController +} from "../../../edit-resources/edit-resource.controller"; @Component({ @@ -67,6 +70,7 @@ export class ResourceDialogComponent implements OnInit { public dialogRef: MatDialogRef<ResourceDialogComponent>, private editGroupService: EditGroupService, private editResourceService: EditResourceService, + private editResourceController: EditResourceController, private alertService: AlertMessageService, private httpErrorHandlerService: HttpErrorHandlerService, private editDomainService: EditDomainService, @@ -224,6 +228,8 @@ export class ResourceDialogComponent implements OnInit { this.editGroupService.createResourceForGroup(this.resource, this.group, this.domain).subscribe({ next: (result: ResourceRo) => { if (!!result) { + // refresh the domains/groups/resources for user to see the changes + this.editResourceController.dataChanged = true; this.closeDialog(); } this.submitInProgress = false; @@ -239,6 +245,8 @@ export class ResourceDialogComponent implements OnInit { this.editResourceService.updateResourceForGroup(resource, this.group, this.domain).subscribe({ next: (result: ResourceRo): void => { if (!!result) { + // refresh the domains/groups/resources for user to see the changes + this.editResourceController.dataChanged = true; this.closeDialog(); } 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 2271a143d0148308fa26d61f1ba3964d7c391225..0577e4e00d47c05726d482ffec255f618c48778d 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 @@ -47,6 +47,8 @@ export class EditResourceComponent implements OnInit, BeforeLeaveGuard { ngOnInit() { console.log("EditResourceComponent: ngOnInit " + this.columns.length); + this.editResourceController.refreshDataOnDataChange(); + if (!this.selectedResource) { this.editResourceController.refreshDomains(); } else { 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 899324fca1adca87f78252926bf3047cdebfdaa6..6f9d9581948bcbf3bfe6104c6c998879694351fa 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 @@ -28,13 +28,16 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { domainList: DomainRo[] = []; groupList: GroupRo[] = []; + // data changed indicates the cached data may be outdated and need to be refreshed + _dataChanged: boolean = false; + _isLoadingResults:boolean = false; + _selectedDomain: DomainRo; _selectedGroup: GroupRo; _selectedResource: ResourceRo; _selectedDomainResourceDefs: ResourceDefinitionRo[]; resourcesFilter: any = {}; - isLoadingResults = false; dataLength:number = 0; pageIndex:number = 0; @@ -58,6 +61,29 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { }); } + // this flag is used to trigger data refresh when data is needed. + //The data can be changed for the user when adding/creating new resource in the edit group + @Input() set dataChanged(value: boolean) { + this._dataChanged = value; + } + + get dataChanged(): boolean { + return this._dataChanged; + } + + // this flag is used to trigger data refresh when data is needed. + //The data can be changed for the user when adding/creating new resource in the edit group + @Input() set isLoadingResults(value: boolean) { + if (!value) { + // data was loaded, and we can reset the flag for data changed + this._dataChanged = value + } + this._isLoadingResults = value; + } + + get isLoadingResults(): boolean { + return this._isLoadingResults; + } private clearSelectedData() { this.domainList = []; @@ -77,7 +103,7 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { @Input() set selectedDomain(domain: DomainRo) { this._selectedDomain = domain; - if (!!this.selectedDomain) { + if (!!this.selectedDomain || this.dataChanged) { this.refreshGroups(); this.refreshDomainsResourceDefinitions(); } else { @@ -93,7 +119,7 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { @Input() set selectedGroup(resource: GroupRo) { this._selectedGroup = resource; - if (!!this._selectedGroup) { + if (!!this._selectedGroup || this.dataChanged ) { this.refreshResources(); } else { this.isLoadingResults = false; @@ -123,6 +149,15 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { this._selectedResource = resource; }; + /** + * Method refreshes data when data changed + */ + refreshDataOnDataChange() { + if (this.dataChanged) { + this.refreshDomains(); + } + } + refreshDomains() { this.isLoadingResults = true; @@ -140,6 +175,7 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { refreshGroups() { if (!this.selectedDomain) { this.updateGroupList([]); + this.isLoadingResults = false; return; } @@ -191,6 +227,7 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { if (!!this.domainList && this.domainList.length > 0) { this.selectedDomain = this.domainList[0]; } else { + this._dataChanged = false; this.isLoadingResults = false; } } @@ -200,6 +237,7 @@ export class EditResourceController extends MatTableDataSource<ResourceRo> { if (!!this.groupList && this.groupList.length > 0) { this.selectedGroup = this.groupList[0]; } else { + this._dataChanged = false; this.isLoadingResults = false; } } diff --git a/smp-angular/src/app/http/http-session-interceptor.ts b/smp-angular/src/app/http/http-session-interceptor.ts index 2e6a7f1cde465472910665a655097406c53b34fa..9494440b0b4118f96a06a5fd855dec810ccec651 100644 --- a/smp-angular/src/app/http/http-session-interceptor.ts +++ b/smp-angular/src/app/http/http-session-interceptor.ts @@ -20,9 +20,6 @@ import {TranslateService} from "@ngx-translate/core"; }) export class HttpSessionInterceptor implements HttpInterceptor { - private readonly TIME_BEFORE_EXPIRATION_IN_SECONDS = 60; - private readonly MAXIMUM_TIMEOUT_VALUE = 2147483647; - private timerId: number; private timerToLogoutId: number; @@ -36,23 +33,28 @@ export class HttpSessionInterceptor implements HttpInterceptor { clearTimeout(this.timerId); clearTimeout(this.timerToLogoutId); let user = this.securityService.getCurrentUser(); - 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); + // set the last UI session call + this.securityService.uiUserSessionCallDetected() + if (user?.sessionMaxIntervalTimeoutInSeconds && user.sessionMaxIntervalTimeoutInSeconds > SecurityService.TIME_BEFORE_EXPIRATION_IN_SECONDS) { + let timeout = Math.min((user.sessionMaxIntervalTimeoutInSeconds - SecurityService.TIME_BEFORE_EXPIRATION_IN_SECONDS) * 1000, SecurityService.MAXIMUM_TIMEOUT_VALUE); this.timerId = setTimeout(() => this.sessionExpiringSoon(user.sessionMaxIntervalTimeoutInSeconds), timeout); } return next.handle(req); } private sessionExpiringSoon(timeout) { + // 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); - + }, SecurityService.TIME_BEFORE_EXPIRATION_IN_SECONDS * 1000); + // disable the automatic UI session extension, + // because the user has dialog to extend the session + this.securityService.uiUserSessionExtensionDisable(); this.dialog.open(SessionExpirationDialogComponent, { data: { - timeLeft: this.TIME_BEFORE_EXPIRATION_IN_SECONDS, + timeLeft: SecurityService.TIME_BEFORE_EXPIRATION_IN_SECONDS, timeout } }); 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 c8a85b61666de30b0e01c4f64e36196d79ff1da6..79a04f9a7651f9c7f51f3277e2ab3d8355fd4c83 100644 --- a/smp-angular/src/app/resource-search/resource-search.component.ts +++ b/smp-angular/src/app/resource-search/resource-search.component.ts @@ -39,7 +39,6 @@ import {SecurityEventService} from "../security/security-event.service"; export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterViewChecked { @ViewChild('rowSMPUrlLinkAction', {static: true}) rowSMPUrlLinkAction: TemplateRef<any> - @ViewChild('rowActions', {static: true}) rowActions: TemplateRef<any>; @ViewChild('searchTable', {static: true}) searchTable: SearchTableComponent; columnPicker: ColumnPicker = new ColumnPicker(); @@ -91,6 +90,14 @@ export class ResourceSearchComponent implements OnInit, AfterViewInit, AfterView resizable: 'false', showInitially: true, }, + { + name: await lastValueFrom(this.translateService.get("resource.search.label.column.visibility")), + prop: 'visibility', + width: 100, + maxWidth: 100, + resizable: 'false', + showInitially: true, + }, { name: await lastValueFrom(this.translateService.get("resource.search.label.column.domain")), prop: 'domainCode', diff --git a/smp-angular/src/app/security/security.service.ts b/smp-angular/src/app/security/security.service.ts index 9c456fb71e0d0007bd389329bfc94803f1d6bc3c..ed6ee70d24dea981d489bf581a9dfd66cb876ac1 100644 --- a/smp-angular/src/app/security/security.service.ts +++ b/smp-angular/src/app/security/security.service.ts @@ -17,11 +17,19 @@ import {TranslateService} from "@ngx-translate/core"; import {WindowSpinnerService} from "../common/services/window-spinner.service"; import {SmpErrorCode} from "../common/enums/smp-error-code.enum"; import {LocalStorageService} from "../common/services/local-storage.service"; +import {SmpInfo} from "../app-info/smp-info.model"; @Injectable() export class SecurityService { + public static readonly TIME_BEFORE_EXPIRATION_IN_SECONDS: number = 60; + public static readonly DELAY_BEFORE_UI_SESSION_EXTENSION_IN_MS: number = 3000; + public static readonly MAXIMUM_TIMEOUT_VALUE: number = 2147483647; + readonly LOCAL_STORAGE_KEY_CURRENT_USER = 'currentUser'; + + lastUIActivity: Date = new Date(); + lastUISessionCall: Date = new Date(); constructor( private http: HttpClient, @@ -275,4 +283,51 @@ export class SecurityService { public clearLocalStorage(): void { this.localStorageService.clearLocalStorage(); } + + /** + * + */ + uiUserActivityDetected() { + console.log("User activity detected"); + let user = this.getCurrentUser(); + if (!this.isAuthenticated(false) + || !user + || !this.lastUISessionCall) { + return; + } + this.lastUIActivity = new Date(); + // to prevent multiple calls to the backend, we check if the last call + // was more than DELAY_BEFORE_UI_SESSION_EXTENSION_IN_MS + if (this.lastUIActivity.getTime() - this.lastUISessionCall.getTime() > SecurityService.DELAY_BEFORE_UI_SESSION_EXTENSION_IN_MS) { + // make a call to the backend to extend the session + this.refreshApplicationInfo(); + } + } + + /** + * This method is called when a UI session call to server is detected. + */ + uiUserSessionCallDetected() { + if (!this.isAuthenticated(false)) { + return; + } + this.lastUISessionCall = new Date(); + } + + uiUserSessionExtensionDisable() { + this.lastUISessionCall = null; + } + + public refreshApplicationInfo() { + + this.http.get<SmpInfo>(SmpConstants.REST_PUBLIC_APPLICATION_INFO) + .subscribe({ + next: (res: SmpInfo): void => { + + }, + error: (err: any): void => { + console.log("getSmpInfo:" + err); + } + }); + } } diff --git a/smp-angular/src/assets/i18n/en.json b/smp-angular/src/assets/i18n/en.json index 6beaf4bdd7c6bd8d6776b23e758c985bb412e18b..3a9d41d6594ed09139ef37da42cba7a9eee2bbbd 100644 --- a/smp-angular/src/assets/i18n/en.json +++ b/smp-angular/src/assets/i18n/en.json @@ -547,7 +547,7 @@ "edit.resource.placeholder.filter": "Resource filter", "edit.resource.placeholder.selected.domain": "Select domain", "edit.resource.placeholder.selected.group": "Select group", - "edit.resource.text": "Edit resource administration panel is a tool for resource administrators to administer the resource", + "edit.resource.text": "Edit resource administration panel is a tool for resource administrators to administer the resource.<br /><b>Note:</b>Only domains and groups where the user is a resource administrator are shown.", "edit.resource.title": "Edit Resource", "edit.resource.tooltip.selected.domain": "Select domain.", "edit.resource.tooltip.selected.group": "Select group.", @@ -588,6 +588,7 @@ "resource.search.label.column.resource.scheme": "Resource scheme", "resource.search.label.column.resource.url": "Resource URL", "resource.search.label.column.subresource.count": "Sr. Cnt.", + "resource.search.label.column.subresource.visibility": "Visibility", "resource.search.label.subresource.id": "Subresource identifier", "resource.search.label.subresource.id.scheme": "Subresource identifier scheme", "resource.search.placeholder.document.type": "Document type", @@ -945,5 +946,4 @@ "navigation.tooltip.search.resources": "Search registered resources", "navigation.tooltip.search.tools": "Search tools", "navigation.tooltip.search.dns.tools": "DNS lookup tools" - } diff --git a/smp-resource-extensions/oasis-smp-spi/src/main/java/eu/europa/ec/smp/spi/def/OasisSMPResource20.java b/smp-resource-extensions/oasis-smp-spi/src/main/java/eu/europa/ec/smp/spi/def/OasisSMPResource20.java index d1cc8b4038ca883f9537ff556a6bf3fc3d5813d0..867f8669c43fb9cf73081a0e9007bbf8a0393b16 100644 --- a/smp-resource-extensions/oasis-smp-spi/src/main/java/eu/europa/ec/smp/spi/def/OasisSMPResource20.java +++ b/smp-resource-extensions/oasis-smp-spi/src/main/java/eu/europa/ec/smp/spi/def/OasisSMPResource20.java @@ -53,7 +53,7 @@ public class OasisSMPResource20 implements ResourceDefinitionSpi { @Override public String defaultUrlSegment() { - return "oasis-bdxr-smp-2"; + return "bdxr-smp-2"; } @Override diff --git a/smp-resource-extensions/oasis-smp-spi/src/test/java/eu/europa/ec/smp/spi/def/OasisSMPResource20Test.java b/smp-resource-extensions/oasis-smp-spi/src/test/java/eu/europa/ec/smp/spi/def/OasisSMPResource20Test.java index 74941484bbbb411ba676e7997c0f9214f8b75410..64a7949b63c9f147ec525fb92c686ce74207a4d2 100644 --- a/smp-resource-extensions/oasis-smp-spi/src/test/java/eu/europa/ec/smp/spi/def/OasisSMPResource20Test.java +++ b/smp-resource-extensions/oasis-smp-spi/src/test/java/eu/europa/ec/smp/spi/def/OasisSMPResource20Test.java @@ -48,7 +48,7 @@ class OasisSMPResource20Test { void defaultUrlSegment() { String result = testInstance.defaultUrlSegment(); - assertEquals("oasis-bdxr-smp-2", result); + assertEquals("bdxr-smp-2", result); } @Test diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceSearchRO.java similarity index 89% rename from smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java rename to smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceSearchRO.java index cf080ac997fa8bccabf073e016f4fe716357050c..b3613fcf126124b80e0193c4195dd5f6031e77c9 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceGroupSearchRO.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ResourceSearchRO.java @@ -19,6 +19,8 @@ package eu.europa.ec.edelivery.smp.data.ui; +import eu.europa.ec.edelivery.smp.data.enums.VisibilityType; + import java.util.ArrayList; import java.util.List; @@ -29,7 +31,7 @@ import java.util.List; * @since 4.1 */ -public class ServiceGroupSearchRO extends BaseRO { +public class ResourceSearchRO extends BaseRO { private static final long serialVersionUID = 9008583888835630016L; @@ -40,6 +42,7 @@ public class ServiceGroupSearchRO extends BaseRO { private String resourceDefUrlSegment; private String participantIdentifier; private String participantScheme; + private VisibilityType visibility; private final List<ServiceMetadataRO> lstServiceMetadata = new ArrayList<>(); @@ -94,4 +97,12 @@ public class ServiceGroupSearchRO extends BaseRO { public void setDocumentType(String documentType) { this.documentType = documentType; } + + public VisibilityType getVisibility() { + return visibility; + } + + public void setVisibility(VisibilityType visibility) { + this.visibility = visibility; + } } 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 b38234ae00ef00821d750c31137cd99403214705..f85a6a4137b98eb66f40e60e907989df78cbecf6 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 @@ -28,7 +28,7 @@ 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; import eu.europa.ec.edelivery.smp.data.ui.ResourceFilterOptionsResult; -import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupSearchRO; +import eu.europa.ec.edelivery.smp.data.ui.ResourceSearchRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceMetadataRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; import eu.europa.ec.edelivery.smp.logging.SMPLogger; @@ -43,7 +43,7 @@ import java.util.List; import java.util.stream.Collectors; @Service -public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGroupSearchRO> { +public class UIResourceSearchService extends UIServiceBase<DBResource, ResourceSearchRO> { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIResourceSearchService.class); private final DomainDao domainDao; @@ -75,9 +75,9 @@ 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<ResourceSearchRO> 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<>(); + ServiceResult<ResourceSearchRO> sg = new ServiceResult<>(); sg.setPage(page < 0 ? 0 : page); sg.setPageSize(pageSize); DBUser user = SessionSecurityUtils.getSessionUserDetails() != null ? @@ -95,9 +95,9 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr iStartIndex = pageSize < 0 ? -1 : page * pageSize; } List<ResourceDao.DBResourceWrapper> lst = resourceDao.getPublicResourcesSearch(page, pageSize, user, filter.getIdentifierSchemeLike(), filter.getIdentifierValueLike(), filter.getDomainCode(), filter.getDocumentType()); - List<ServiceGroupSearchRO> lstRo = new ArrayList<>(); + List<ResourceSearchRO> lstRo = new ArrayList<>(); for (ResourceDao.DBResourceWrapper resource : lst) { - ServiceGroupSearchRO serviceGroupRo = convert(resource); + ResourceSearchRO serviceGroupRo = convert(resource); serviceGroupRo.setIndex(iStartIndex++); lstRo.add(serviceGroupRo); } @@ -112,8 +112,8 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr * @param resource - database entity wrapper * @return ServiceGroupRO */ - private ServiceGroupSearchRO convert(ResourceDao.DBResourceWrapper resource) { - ServiceGroupSearchRO serviceGroupRo = new ServiceGroupSearchRO(); + private ResourceSearchRO convert(ResourceDao.DBResourceWrapper resource) { + ResourceSearchRO serviceGroupRo = new ResourceSearchRO(); serviceGroupRo.setId(resource.getDbResource().getId()); serviceGroupRo.setDomainCode(resource.getDomainCode()); @@ -121,6 +121,7 @@ public class UIResourceSearchService extends UIServiceBase<DBResource, ServiceGr serviceGroupRo.setResourceDefUrlSegment(resource.getUrlSegment()); serviceGroupRo.setParticipantIdentifier(resource.getDbResource().getIdentifierValue()); serviceGroupRo.setParticipantScheme(resource.getDbResource().getIdentifierScheme()); + serviceGroupRo.setVisibility(resource.getDbResource().getVisibility()); resource.getDbResource().getSubresources().forEach(subresource -> { ServiceMetadataRO smdro = new ServiceMetadataRO(); diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchServiceTest.java index 1418b3dff71269f6cabe70a781681954104ddc30..ec40ca73442cb21b00247fbaaa604293682d424c 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchServiceTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceSearchServiceTest.java @@ -19,7 +19,7 @@ package eu.europa.ec.edelivery.smp.services.ui; import eu.europa.ec.edelivery.smp.data.dao.AbstractJunit5BaseDao; -import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupSearchRO; +import eu.europa.ec.edelivery.smp.data.ui.ResourceSearchRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; import eu.europa.ec.edelivery.smp.services.ui.filters.ResourceFilter; import org.junit.jupiter.api.BeforeEach; @@ -46,7 +46,7 @@ class UIResourceSearchServiceTest extends AbstractJunit5BaseDao { @Test void testGetTableList() { ResourceFilter filter = new ResourceFilter(); - ServiceResult<ServiceGroupSearchRO> result = testInstance.getTableList(-1, -1, null, null, filter); + ServiceResult<ResourceSearchRO> result = testInstance.getTableList(-1, -1, null, null, filter); assertNotNull(result); assertEquals(2, result.getCount().intValue()); } @@ -56,7 +56,7 @@ class UIResourceSearchServiceTest extends AbstractJunit5BaseDao { ResourceFilter filter = new ResourceFilter(); filter.setIdentifierValueLike(testUtilsDao.getResourceD1G1RD1().getIdentifierValue()); - ServiceResult<ServiceGroupSearchRO> result = testInstance.getTableList(-1, -1, null, null, filter); + ServiceResult<ResourceSearchRO> result = testInstance.getTableList(-1, -1, null, null, filter); assertNotNull(result); assertEquals(1, result.getCount().intValue()); } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java index 6d514e10f224943306563b3aeb995bc2acc7bf59..181cf82eec66ff266d6904f9450698196f4fcc42 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/external/SearchResource.java @@ -20,7 +20,7 @@ package eu.europa.ec.edelivery.smp.ui.external; import eu.europa.ec.edelivery.smp.data.dao.DomainDao; import eu.europa.ec.edelivery.smp.data.ui.ResourceFilterOptionsResult; -import eu.europa.ec.edelivery.smp.data.ui.ServiceGroupSearchRO; +import eu.europa.ec.edelivery.smp.data.ui.ResourceSearchRO; 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; @@ -59,7 +59,7 @@ public class SearchResource { } @GetMapping(path = CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT) - public ServiceResult<ServiceGroupSearchRO> getServiceGroupList( + public ServiceResult<ResourceSearchRO> getServiceGroupList( @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,