From da5d5406683ff81c9c78c4538ab7a8821d12ce51 Mon Sep 17 00:00:00 2001 From: Pratik Rajkotiya Date: Wed, 27 Apr 2022 19:10:44 +0530 Subject: [PATCH 1/7] [CST-5738] add special group with mock & test cases. --- src/app/core/auth/models/auth-status.model.ts | 11 ++++ .../profile-page/profile-page.component.html | 11 ++++ .../profile-page.component.spec.ts | 22 ++++++- .../profile-page/profile-page.component.ts | 8 +++ .../testing/auth-request-service.stub.ts | 6 ++ src/app/shared/testing/special-group.mock.ts | 64 +++++++++++++++++++ src/assets/i18n/en.json5 | 2 + 7 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/app/shared/testing/special-group.mock.ts diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index 197c025407..2500c5b0a9 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -6,6 +6,8 @@ import { CacheableObject } from '../../cache/object-cache.reducer'; import { RemoteData } from '../../data/remote-data'; import { EPerson } from '../../eperson/models/eperson.model'; import { EPERSON } from '../../eperson/models/eperson.resource-type'; +import { Group } from '../../eperson/models/group.model'; +import { GROUP } from '../../eperson/models/group.resource-type'; import { HALLink } from '../../shared/hal-link.model'; import { ResourceType } from '../../shared/resource-type'; import { excludeFromEquals } from '../../utilities/equals.decorators'; @@ -14,6 +16,7 @@ import { AUTH_STATUS } from './auth-status.resource-type'; import { AuthTokenInfo } from './auth-token-info.model'; import { AuthMethod } from './auth.method'; + /** * Object that represents the authenticated status of a user */ @@ -61,6 +64,7 @@ export class AuthStatus implements CacheableObject { _links: { self: HALLink; eperson: HALLink; + specialGroups: HALLink; }; /** @@ -70,6 +74,13 @@ export class AuthStatus implements CacheableObject { @link(EPERSON) eperson?: Observable>; + /** + * The SpecialGroup of this auth status + * Will be undefined unless the SpecialGroup {@link HALLink} has been resolved. + */ + @link(GROUP) + specialGroups?: Observable>; + /** * True if the token is valid, false if there was no token or the token wasn't valid */ diff --git a/src/app/profile-page/profile-page.component.html b/src/app/profile-page/profile-page.component.html index ccfae0bba1..ffdf802a94 100644 --- a/src/app/profile-page/profile-page.component.html +++ b/src/app/profile-page/profile-page.component.html @@ -29,5 +29,16 @@ + + +
+
+

{{'profile.special.groups.head' | translate}}

+
    +
  • {{specialGroup.name}}
  • +
+
+
+
diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index f48b894d8d..5ba1deedcf 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -13,13 +13,17 @@ import { NotificationsService } from '../shared/notifications/notifications.serv import { authReducer } from '../core/auth/auth.reducer'; import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { createPaginatedList } from '../shared/testing/utils.test'; -import { BehaviorSubject, of as observableOf } from 'rxjs'; +import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; import { AuthService } from '../core/auth/auth.service'; import { RestResponse } from '../core/cache/response.models'; import { provideMockStore } from '@ngrx/store/testing'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { getTestScheduler } from 'jasmine-marbles'; import { By } from '@angular/platform-browser'; +import { RemoteData } from '../core/data/remote-data'; +import { PaginatedList } from '../core/data/paginated-list.model'; +import { Group } from '../core/eperson/models/group.model'; +import { SpecialGroupData } from '../shared/testing/special-group.mock'; describe('ProfilePageComponent', () => { let component: ProfilePageComponent; @@ -235,4 +239,20 @@ describe('ProfilePageComponent', () => { }); }); }); + + describe('check for specialGroups', () => { + it('should contains specialGroups list', () => { + component.specialGroupsRD$ = SpecialGroupData; + fixture.detectChanges(); + const specialGroupsEle = fixture.debugElement.query(By.css('#specialGroups')); + expect(specialGroupsEle).toBeTruthy(); + }); + + it('should not contains specialGroups list', () => { + component.specialGroupsRD$ = null; + fixture.detectChanges(); + const specialGroupsEle = fixture.debugElement.query(By.css('#specialGroups')); + expect(specialGroupsEle).toBeFalsy(); + }); + }); }); diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index fece166a59..574f8c17a4 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -20,6 +20,8 @@ import { AuthService } from '../core/auth/auth.service'; import { Operation } from 'fast-json-patch'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../core/data/feature-authorization/feature-id'; +import { SpecialGroupData } from '../shared/testing/special-group.mock'; + @Component({ selector: 'ds-profile-page', @@ -45,6 +47,11 @@ export class ProfilePageComponent implements OnInit { */ groupsRD$: Observable>>; + /** + * The special groups the user belongs to + */ + specialGroupsRD$: Observable>>; + /** * Prefix for the notification messages of this component */ @@ -88,6 +95,7 @@ export class ProfilePageComponent implements OnInit { ); this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups)); this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href))); + this.specialGroupsRD$ = SpecialGroupData; } /** diff --git a/src/app/shared/testing/auth-request-service.stub.ts b/src/app/shared/testing/auth-request-service.stub.ts index 0dc57427dd..0094324518 100644 --- a/src/app/shared/testing/auth-request-service.stub.ts +++ b/src/app/shared/testing/auth-request-service.stub.ts @@ -34,6 +34,9 @@ export class AuthRequestServiceStub { }, eperson: { href: this.mockUser._links.self.href + }, + specialGroups: { + href: this.mockUser._links.self.href } }; } else { @@ -62,6 +65,9 @@ export class AuthRequestServiceStub { }, eperson: { href: this.mockUser._links.self.href + }, + specialGroups: { + href: this.mockUser._links.self.href } }; } else { diff --git a/src/app/shared/testing/special-group.mock.ts b/src/app/shared/testing/special-group.mock.ts new file mode 100644 index 0000000000..76d5bf60ea --- /dev/null +++ b/src/app/shared/testing/special-group.mock.ts @@ -0,0 +1,64 @@ +import { EPersonMock } from './eperson.mock'; +import { of } from 'rxjs'; +import { RemoteData } from '../../core/data/remote-data'; +import { environment } from '../../../environments/environment'; +import { RequestEntryState } from '../../core/data/request.reducer'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { buildPaginatedList } from '../../core/data/paginated-list.model'; +import { Group } from '../../core/eperson/models/group.model'; + + +export const SpecialGroupMock2: Group = Object.assign(new Group(), { + handle: null, + subgroups: [], + epersons: [], + permanent: true, + selfRegistered: false, + _links: { + self: { + href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid2', + }, + subgroups: { href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid2/subgroups' }, + object: { href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid2/object' }, + epersons: { href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid2/epersons' } + }, + _name: 'testgroupname2', + id: 'testgroupid2', + uuid: 'testgroupid2', + type: 'specialGroups', + // object: createSuccessfulRemoteDataObject$({ name: 'testspecialGroupsid2objectName'}) +}); + +export const SpecialGroupMock: Group = Object.assign(new Group(), { + handle: null, + subgroups: [SpecialGroupMock2], + epersons: [EPersonMock], + selfRegistered: false, + permanent: false, + _links: { + self: { + href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid', + }, + subgroups: { href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid/subgroups' }, + object: { href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid2/object' }, + epersons: { href: 'https://rest.api/server/api/eperson/specialGroups/testgroupid/epersons' } + }, + _name: 'testgroupname', + id: 'testgroupid', + uuid: 'testgroupid', + type: 'specialGroups', +}); + +export const SpecialGroupData = of(new RemoteData( + new Date().getTime(), + environment.cache.msToLive.default, + new Date().getTime(), + RequestEntryState.Success, + undefined, + buildPaginatedList(new PageInfo(), [SpecialGroupMock2,SpecialGroupMock]), + 200 + )); + + + + diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index c3c68a6882..25c69d372a 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -2861,6 +2861,8 @@ "profile.groups.head": "Authorization groups you belong to", + "profile.special.groups.head": "Authorization special groups you belong to", + "profile.head": "Update Profile", "profile.metadata.form.error.firstname.required": "First Name is required", From a34e7428c3ad7fb1d441ae9d3f532a44522fcce2 Mon Sep 17 00:00:00 2001 From: Pratik Rajkotiya Date: Wed, 27 Apr 2022 19:11:49 +0530 Subject: [PATCH 2/7] [CST-5738] remove unused variable. --- config/config.yml | 4 ++-- src/app/profile-page/profile-page.component.spec.ts | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/config/config.yml b/config/config.yml index b5eecd112f..3866797f5d 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,5 +1,5 @@ rest: - ssl: true - host: api7.dspace.org + ssl: false + host: localhost:8080 port: 443 nameSpace: /server diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 5ba1deedcf..6fad24eb34 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -20,9 +20,6 @@ import { provideMockStore } from '@ngrx/store/testing'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { getTestScheduler } from 'jasmine-marbles'; import { By } from '@angular/platform-browser'; -import { RemoteData } from '../core/data/remote-data'; -import { PaginatedList } from '../core/data/paginated-list.model'; -import { Group } from '../core/eperson/models/group.model'; import { SpecialGroupData } from '../shared/testing/special-group.mock'; describe('ProfilePageComponent', () => { From 0f80b6533b89e98f4161a3dc4d164ddda9f10f0f Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 29 Apr 2022 12:49:07 +0200 Subject: [PATCH 3/7] [CST-5738] Add method to retrieve embedded special groups --- src/app/core/auth/auth-request.service.ts | 12 +++++--- src/app/core/auth/auth.service.spec.ts | 22 ++++++++++++++ src/app/core/auth/auth.service.ts | 22 +++++++++++++- src/app/core/auth/models/auth-status.model.ts | 6 ++-- .../profile-page.component.spec.ts | 9 +++--- .../profile-page/profile-page.component.ts | 10 ++----- src/app/shared/testing/special-group.mock.ts | 29 +++++++------------ 7 files changed, 70 insertions(+), 40 deletions(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index da38d730a5..516502ca6e 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -18,7 +18,6 @@ import { RestRequest } from '../data/rest-request.model'; */ export abstract class AuthRequestService { protected linkName = 'authn'; - protected browseEndpoint = ''; protected shortlivedtokensEndpoint = 'shortlivedtokens'; constructor(protected halService: HALEndpointService, @@ -33,8 +32,13 @@ export abstract class AuthRequestService { ); } - protected getEndpointByMethod(endpoint: string, method: string): string { - return isNotEmpty(method) ? `${endpoint}/${method}` : `${endpoint}`; + protected getEndpointByMethod(endpoint: string, method: string, embed = false): string { + let url = isNotEmpty(method) ? `${endpoint}/${method}` : `${endpoint}`; + if (embed) { + url += '?embed=specialGroups'; + } + + return url; } public postToEndpoint(method: string, body?: any, options?: HttpOptions): Observable> { @@ -48,7 +52,7 @@ export abstract class AuthRequestService { distinctUntilChanged()); } - public getRequest(method: string, options?: HttpOptions): Observable> { + public getRequest(method: string, options?: HttpOptions, embed = false): Observable> { return this.halService.getEndpoint(this.linkName).pipe( filter((href: string) => isNotEmpty(href)), map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index ced8bb94c8..d63e300ce0 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -32,6 +32,8 @@ import { TranslateService } from '@ngx-translate/core'; import { getMockTranslateService } from '../../shared/mocks/translate.service.mock'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { SetUserAsIdleAction, UnsetUserAsIdleAction } from './auth.actions'; +import { SpecialGroupDataMock, SpecialGroupDataMock$ } from '../../shared/testing/special-group.mock'; +import { cold } from 'jasmine-marbles'; describe('AuthService test', () => { @@ -56,6 +58,13 @@ describe('AuthService test', () => { let linkService; let hardRedirectService; + const AuthStatusWithSpecialGroups = Object.assign(new AuthStatus(), { + uuid: 'test', + authenticated: true, + okay: true, + specialGroups: SpecialGroupDataMock$ + }); + function init() { mockStore = jasmine.createSpyObj('store', { dispatch: {}, @@ -511,6 +520,19 @@ describe('AuthService test', () => { expect((authService as any).navigateToRedirectUrl).toHaveBeenCalled(); }); }); + + describe('getSpecialGroupsFromAuthStatus', () => { + beforeEach(() => { + spyOn(authRequest, 'getRequest').and.returnValue(createSuccessfulRemoteDataObject$(AuthStatusWithSpecialGroups)); + }); + + it('should call navigateToRedirectUrl with no url', () => { + const expectRes = cold('(a|)', { + a: SpecialGroupDataMock + }); + expect(authService.getSpecialGroupsFromAuthStatus()).toBeObservable(expectRes); + }); + }); }); describe('when user is not logged in', () => { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index f89fa21681..2d2c61490c 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -44,13 +44,17 @@ import { import { NativeWindowRef, NativeWindowService } from '../services/window.service'; import { RouteService } from '../services/route.service'; import { EPersonDataService } from '../eperson/eperson-data.service'; -import { getAllSucceededRemoteDataPayload } from '../shared/operators'; +import { getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData } from '../shared/operators'; import { AuthMethod } from './models/auth.method'; import { HardRedirectService } from '../services/hard-redirect.service'; import { RemoteData } from '../data/remote-data'; import { environment } from '../../../environments/environment'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { TranslateService } from '@ngx-translate/core'; +import { buildPaginatedList, PaginatedList } from '../data/paginated-list.model'; +import { Group } from '../eperson/models/group.model'; +import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; +import { PageInfo } from '../shared/page-info.model'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -211,6 +215,22 @@ export class AuthService { this.store.dispatch(new CheckAuthenticationTokenAction()); } + /** + * Return the special groups list embedded in the AuthStatus model + */ + public getSpecialGroupsFromAuthStatus(): Observable>> { + return this.authRequestService.getRequest('status', null, true).pipe( + getFirstCompletedRemoteData(), + switchMap((status: RemoteData) => { + if (status.hasSucceeded) { + return status.payload.specialGroups; + } else { + return createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(),[])); + } + }) + ); + } + /** * Checks if token is present into storage and is not expired */ diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index 2634182a55..d18b1ccf9a 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -15,7 +15,7 @@ import { AUTH_STATUS } from './auth-status.resource-type'; import { AuthTokenInfo } from './auth-token-info.model'; import { AuthMethod } from './auth.method'; import { CacheableObject } from '../../cache/cacheable-object.model'; - +import { PaginatedList } from '../../data/paginated-list.model'; /** * Object that represents the authenticated status of a user @@ -78,8 +78,8 @@ export class AuthStatus implements CacheableObject { * The SpecialGroup of this auth status * Will be undefined unless the SpecialGroup {@link HALLink} has been resolved. */ - @link(GROUP) - specialGroups?: Observable>; + @link(GROUP, true) + specialGroups?: Observable>>; /** * True if the token is valid, false if there was no token or the token wasn't valid diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 6fad24eb34..1bc9a78ad5 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -13,14 +13,14 @@ import { NotificationsService } from '../shared/notifications/notifications.serv import { authReducer } from '../core/auth/auth.reducer'; import { createSuccessfulRemoteDataObject$ } from '../shared/remote-data.utils'; import { createPaginatedList } from '../shared/testing/utils.test'; -import { BehaviorSubject, Observable, of as observableOf } from 'rxjs'; +import { BehaviorSubject, of as observableOf } from 'rxjs'; import { AuthService } from '../core/auth/auth.service'; import { RestResponse } from '../core/cache/response.models'; import { provideMockStore } from '@ngrx/store/testing'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { getTestScheduler } from 'jasmine-marbles'; import { By } from '@angular/platform-browser'; -import { SpecialGroupData } from '../shared/testing/special-group.mock'; +import { SpecialGroupDataMock$ } from '../shared/testing/special-group.mock'; describe('ProfilePageComponent', () => { let component: ProfilePageComponent; @@ -55,7 +55,8 @@ describe('ProfilePageComponent', () => { }; authService = jasmine.createSpyObj('authService', { - getAuthenticatedUserFromStore: observableOf(user) + getAuthenticatedUserFromStore: observableOf(user), + getSpecialGroupsFromAuthStatus: SpecialGroupDataMock$ }); epersonService = jasmine.createSpyObj('epersonService', { findById: createSuccessfulRemoteDataObject$(user), @@ -239,8 +240,6 @@ describe('ProfilePageComponent', () => { describe('check for specialGroups', () => { it('should contains specialGroups list', () => { - component.specialGroupsRD$ = SpecialGroupData; - fixture.detectChanges(); const specialGroupsEle = fixture.debugElement.query(By.css('#specialGroups')); expect(specialGroupsEle).toBeTruthy(); }); diff --git a/src/app/profile-page/profile-page.component.ts b/src/app/profile-page/profile-page.component.ts index 574f8c17a4..7623e9e6ea 100644 --- a/src/app/profile-page/profile-page.component.ts +++ b/src/app/profile-page/profile-page.component.ts @@ -9,19 +9,13 @@ import { RemoteData } from '../core/data/remote-data'; import { PaginatedList } from '../core/data/paginated-list.model'; import { filter, switchMap, tap } from 'rxjs/operators'; import { EPersonDataService } from '../core/eperson/eperson-data.service'; -import { - getAllSucceededRemoteData, - getRemoteDataPayload, - getFirstCompletedRemoteData -} from '../core/shared/operators'; +import { getAllSucceededRemoteData, getFirstCompletedRemoteData, getRemoteDataPayload } from '../core/shared/operators'; import { hasValue, isNotEmpty } from '../shared/empty.util'; import { followLink } from '../shared/utils/follow-link-config.model'; import { AuthService } from '../core/auth/auth.service'; import { Operation } from 'fast-json-patch'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { FeatureID } from '../core/data/feature-authorization/feature-id'; -import { SpecialGroupData } from '../shared/testing/special-group.mock'; - @Component({ selector: 'ds-profile-page', @@ -95,7 +89,7 @@ export class ProfilePageComponent implements OnInit { ); this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups)); this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href))); - this.specialGroupsRD$ = SpecialGroupData; + this.specialGroupsRD$ = this.authService.getSpecialGroupsFromAuthStatus(); } /** diff --git a/src/app/shared/testing/special-group.mock.ts b/src/app/shared/testing/special-group.mock.ts index 76d5bf60ea..d8ec8a83cc 100644 --- a/src/app/shared/testing/special-group.mock.ts +++ b/src/app/shared/testing/special-group.mock.ts @@ -1,12 +1,11 @@ -import { EPersonMock } from './eperson.mock'; -import { of } from 'rxjs'; -import { RemoteData } from '../../core/data/remote-data'; -import { environment } from '../../../environments/environment'; -import { RequestEntryState } from '../../core/data/request.reducer'; -import { PageInfo } from '../../core/shared/page-info.model'; -import { buildPaginatedList } from '../../core/data/paginated-list.model'; -import { Group } from '../../core/eperson/models/group.model'; +import { Observable } from 'rxjs'; +import { EPersonMock } from './eperson.mock'; +import { PageInfo } from '../../core/shared/page-info.model'; +import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model'; +import { Group } from '../../core/eperson/models/group.model'; +import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../remote-data.utils'; +import { RemoteData } from '../../core/data/remote-data'; export const SpecialGroupMock2: Group = Object.assign(new Group(), { handle: null, @@ -49,16 +48,8 @@ export const SpecialGroupMock: Group = Object.assign(new Group(), { type: 'specialGroups', }); -export const SpecialGroupData = of(new RemoteData( - new Date().getTime(), - environment.cache.msToLive.default, - new Date().getTime(), - RequestEntryState.Success, - undefined, - buildPaginatedList(new PageInfo(), [SpecialGroupMock2,SpecialGroupMock]), - 200 - )); - - +export const SpecialGroupDataMock: RemoteData> = createSuccessfulRemoteDataObject(buildPaginatedList(new PageInfo(), [SpecialGroupMock2,SpecialGroupMock])); +export const SpecialGroupDataMock$: Observable>> = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [SpecialGroupMock2,SpecialGroupMock])); + From aa7ceec15aaa331335a67e6d595c075d14918c25 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Fri, 29 Apr 2022 19:15:40 +0200 Subject: [PATCH 4/7] [CST-5738] Fix retrieving of embed from auth status model --- src/app/core/auth/auth-request.service.ts | 19 +++++++++++-------- src/app/core/auth/auth.service.ts | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index 516502ca6e..d0fec5fa71 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -12,6 +12,7 @@ import { AuthStatus } from './models/auth-status.model'; import { ShortLivedToken } from './models/short-lived-token.model'; import { URLCombiner } from '../url-combiner/url-combiner'; import { RestRequest } from '../data/rest-request.model'; +import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; /** * Abstract service to send authentication requests @@ -26,16 +27,18 @@ export abstract class AuthRequestService { ) { } - protected fetchRequest(request: RestRequest): Observable> { - return this.rdbService.buildFromRequestUUID(request.uuid).pipe( + protected fetchRequest(request: RestRequest, ...linksToFollow: FollowLinkConfig[]): Observable> { + return this.rdbService.buildFromRequestUUID(request.uuid, ...linksToFollow).pipe( getFirstCompletedRemoteData(), ); } - protected getEndpointByMethod(endpoint: string, method: string, embed = false): string { + protected getEndpointByMethod(endpoint: string, method: string, ...linksToFollow: FollowLinkConfig[]): string { let url = isNotEmpty(method) ? `${endpoint}/${method}` : `${endpoint}`; - if (embed) { - url += '?embed=specialGroups'; + if (linksToFollow && linksToFollow.length > 0) { + linksToFollow.forEach((link: FollowLinkConfig, index: number) => { + url += ((index === 0) ? '?' : '&') + `embed=${link.name}`; + }); } return url; @@ -52,14 +55,14 @@ export abstract class AuthRequestService { distinctUntilChanged()); } - public getRequest(method: string, options?: HttpOptions, embed = false): Observable> { + public getRequest(method: string, options?: HttpOptions, ...linksToFollow: FollowLinkConfig[]): Observable> { return this.halService.getEndpoint(this.linkName).pipe( filter((href: string) => isNotEmpty(href)), - map((endpointURL) => this.getEndpointByMethod(endpointURL, method)), + map((endpointURL) => this.getEndpointByMethod(endpointURL, method, ...linksToFollow)), distinctUntilChanged(), map((endpointURL: string) => new GetRequest(this.requestService.generateRequestId(), endpointURL, undefined, options)), tap((request: GetRequest) => this.requestService.send(request)), - mergeMap((request: GetRequest) => this.fetchRequest(request)), + mergeMap((request: GetRequest) => this.fetchRequest(request, ...linksToFollow)), distinctUntilChanged()); } diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 2d2c61490c..7796094e39 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -55,6 +55,7 @@ import { buildPaginatedList, PaginatedList } from '../data/paginated-list.model' import { Group } from '../eperson/models/group.model'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { PageInfo } from '../shared/page-info.model'; +import { followLink } from '../../shared/utils/follow-link-config.model'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -219,7 +220,7 @@ export class AuthService { * Return the special groups list embedded in the AuthStatus model */ public getSpecialGroupsFromAuthStatus(): Observable>> { - return this.authRequestService.getRequest('status', null, true).pipe( + return this.authRequestService.getRequest('status', null, followLink('specialGroups')).pipe( getFirstCompletedRemoteData(), switchMap((status: RemoteData) => { if (status.hasSucceeded) { From 724fc3c6f045e8ff839cc0c080492139279e81c6 Mon Sep 17 00:00:00 2001 From: Michael Spalti Date: Mon, 9 May 2022 09:24:17 +0200 Subject: [PATCH 5/7] [CST-5738] Revert unintentional change on config.yml --- config/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/config.yml b/config/config.yml index 3866797f5d..b5eecd112f 100644 --- a/config/config.yml +++ b/config/config.yml @@ -1,5 +1,5 @@ rest: - ssl: false - host: localhost:8080 + ssl: true + host: api7.dspace.org port: 443 nameSpace: /server From 50184c87848f6d9e69180b5a377346ab91caafbb Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 18 May 2022 19:27:23 +0200 Subject: [PATCH 6/7] [CST-5738] fix LGTM alert --- src/app/core/auth/auth-request.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/core/auth/auth-request.service.ts b/src/app/core/auth/auth-request.service.ts index d0fec5fa71..4db4cba612 100644 --- a/src/app/core/auth/auth-request.service.ts +++ b/src/app/core/auth/auth-request.service.ts @@ -35,7 +35,7 @@ export abstract class AuthRequestService { protected getEndpointByMethod(endpoint: string, method: string, ...linksToFollow: FollowLinkConfig[]): string { let url = isNotEmpty(method) ? `${endpoint}/${method}` : `${endpoint}`; - if (linksToFollow && linksToFollow.length > 0) { + if (linksToFollow?.length > 0) { linksToFollow.forEach((link: FollowLinkConfig, index: number) => { url += ((index === 0) ? '?' : '&') + `embed=${link.name}`; }); From 305203dba7fb2212171ed19df4d39895b235493b Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Thu, 19 May 2022 19:08:08 +0200 Subject: [PATCH 7/7] [CST-5738] hide special group heading when are not present --- src/app/profile-page/profile-page.component.html | 14 ++++++-------- .../profile-page/profile-page.component.spec.ts | 13 ++++++++++--- src/app/shared/testing/special-group.mock.ts | 1 + 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/app/profile-page/profile-page.component.html b/src/app/profile-page/profile-page.component.html index ffdf802a94..da31018cad 100644 --- a/src/app/profile-page/profile-page.component.html +++ b/src/app/profile-page/profile-page.component.html @@ -22,7 +22,7 @@ -
+

{{'profile.groups.head' | translate}}

  • {{group.name}}
  • @@ -31,13 +31,11 @@ -
    -
    -

    {{'profile.special.groups.head' | translate}}

    -
      -
    • {{specialGroup.name}}
    • -
    -
    +
    +

    {{'profile.special.groups.head' | translate}}

    +
      +
    • {{specialGroup.name}}
    • +
    diff --git a/src/app/profile-page/profile-page.component.spec.ts b/src/app/profile-page/profile-page.component.spec.ts index 1bc9a78ad5..46f83c964b 100644 --- a/src/app/profile-page/profile-page.component.spec.ts +++ b/src/app/profile-page/profile-page.component.spec.ts @@ -20,7 +20,7 @@ import { provideMockStore } from '@ngrx/store/testing'; import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service'; import { getTestScheduler } from 'jasmine-marbles'; import { By } from '@angular/platform-browser'; -import { SpecialGroupDataMock$ } from '../shared/testing/special-group.mock'; +import { EmptySpecialGroupDataMock$, SpecialGroupDataMock$ } from '../shared/testing/special-group.mock'; describe('ProfilePageComponent', () => { let component: ProfilePageComponent; @@ -240,14 +240,21 @@ describe('ProfilePageComponent', () => { describe('check for specialGroups', () => { it('should contains specialGroups list', () => { - const specialGroupsEle = fixture.debugElement.query(By.css('#specialGroups')); + const specialGroupsEle = fixture.debugElement.query(By.css('[data-test="specialGroups"]')); expect(specialGroupsEle).toBeTruthy(); }); it('should not contains specialGroups list', () => { component.specialGroupsRD$ = null; fixture.detectChanges(); - const specialGroupsEle = fixture.debugElement.query(By.css('#specialGroups')); + const specialGroupsEle = fixture.debugElement.query(By.css('[data-test="specialGroups"]')); + expect(specialGroupsEle).toBeFalsy(); + }); + + it('should not contains specialGroups list', () => { + component.specialGroupsRD$ = EmptySpecialGroupDataMock$; + fixture.detectChanges(); + const specialGroupsEle = fixture.debugElement.query(By.css('[data-test="specialGroups"]')); expect(specialGroupsEle).toBeFalsy(); }); }); diff --git a/src/app/shared/testing/special-group.mock.ts b/src/app/shared/testing/special-group.mock.ts index d8ec8a83cc..f1102e0584 100644 --- a/src/app/shared/testing/special-group.mock.ts +++ b/src/app/shared/testing/special-group.mock.ts @@ -50,6 +50,7 @@ export const SpecialGroupMock: Group = Object.assign(new Group(), { export const SpecialGroupDataMock: RemoteData> = createSuccessfulRemoteDataObject(buildPaginatedList(new PageInfo(), [SpecialGroupMock2,SpecialGroupMock])); export const SpecialGroupDataMock$: Observable>> = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [SpecialGroupMock2,SpecialGroupMock])); +export const EmptySpecialGroupDataMock$: Observable>> = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), []));