diff --git a/package.json b/package.json index b058730545..874f4a6019 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "cerialize": "0.1.18", "compression": "1.7.1", "cookie-parser": "1.4.3", - "core-js": "2.5.3", + "core-js": "^2.5.7", "express": "4.16.2", "express-session": "1.15.6", "font-awesome": "4.7.0", diff --git a/src/app/+search-page/search-filters/search-filters.component.ts b/src/app/+search-page/search-filters/search-filters.component.ts index f4b63c332f..1da4e5860d 100644 --- a/src/app/+search-page/search-filters/search-filters.component.ts +++ b/src/app/+search-page/search-filters/search-filters.component.ts @@ -56,7 +56,6 @@ export class SearchFiltersComponent { * @returns {Observable} Emits true whenever a given filter config should be shown */ isActive(filter: SearchFilterConfig): Observable { - // console.log(filter.name); return this.filterService.getSelectedValuesForFilter(filter) .flatMap((isActive) => { if (isNotEmpty(isActive)) { diff --git a/src/app/core/auth/auth-object-factory.ts b/src/app/core/auth/auth-object-factory.ts index c3e70eaaac..b6df1fac34 100644 --- a/src/app/core/auth/auth-object-factory.ts +++ b/src/app/core/auth/auth-object-factory.ts @@ -1,14 +1,15 @@ import { AuthType } from './auth-type'; import { GenericConstructor } from '../shared/generic-constructor'; import { NormalizedAuthStatus } from './models/normalized-auth-status.model'; -import { NormalizedDSpaceObject } from '../cache/models/normalized-dspace-object.model'; -import { NormalizedEpersonModel } from '../eperson/models/NormalizedEperson.model'; +import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model'; +import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { EPerson } from '../eperson/models/eperson.model'; export class AuthObjectFactory { - public static getConstructor(type): GenericConstructor { + public static getConstructor(type): GenericConstructor { switch (type) { - case AuthType.Eperson: { - return NormalizedEpersonModel + case AuthType.EPerson: { + return NormalizedEPerson } case AuthType.Status: { diff --git a/src/app/core/auth/auth-response-parsing.service.spec.ts b/src/app/core/auth/auth-response-parsing.service.spec.ts index f7d899a9bc..f6dd87e99a 100644 --- a/src/app/core/auth/auth-response-parsing.service.spec.ts +++ b/src/app/core/auth/auth-response-parsing.service.spec.ts @@ -8,12 +8,13 @@ import { CoreState } from '../core.reducers'; import { AuthStatus } from './models/auth-status.model'; import { AuthResponseParsingService } from './auth-response-parsing.service'; import { AuthGetRequest, AuthPostRequest } from '../data/request.models'; +import { getMockStore } from '../../shared/mocks/mock-store'; -describe('ConfigResponseParsingService', () => { +describe('AuthResponseParsingService', () => { let service: AuthResponseParsingService; - const EnvConfig = {} as GlobalConfig; - const store = {} as Store; + const EnvConfig = {cache: {msToLive: 1000}} as GlobalConfig; + const store = getMockStore() as Store; const objectCacheService = new ObjectCacheService(store); beforeEach(() => { @@ -86,13 +87,19 @@ describe('ConfigResponseParsingService', () => { type: 'eperson', uuid: '4dc70ab5-cd73-492f-b007-3179d2d9296b', _links: { - self: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b' + self: { + href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b' + } } } }, _links: { - eperson: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b', - self: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/authn/status' + eperson: { + href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/eperson/epersons/4dc70ab5-cd73-492f-b007-3179d2d9296b' + }, + self: { + href: 'https://hasselt-dspace.dev01.4science.it/dspace-spring-rest/api/authn/status' + } } }, statusCode: '200' diff --git a/src/app/core/auth/auth-response-parsing.service.ts b/src/app/core/auth/auth-response-parsing.service.ts index 80c1b2eeca..8efa36f9e2 100644 --- a/src/app/core/auth/auth-response-parsing.service.ts +++ b/src/app/core/auth/auth-response-parsing.service.ts @@ -12,22 +12,23 @@ import { ResponseParsingService } from '../data/parsing.service'; import { RestRequest } from '../data/request.models'; import { AuthType } from './auth-type'; import { AuthStatus } from './models/auth-status.model'; +import { NormalizedAuthStatus } from './models/normalized-auth-status.model'; @Injectable() export class AuthResponseParsingService extends BaseResponseParsingService implements ResponseParsingService { protected objectFactory = AuthObjectFactory; - protected toCache = false; + protected toCache = true; constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig, - protected objectCache: ObjectCacheService,) { + protected objectCache: ObjectCacheService) { super(); } parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse { if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === '200' || data.statusCode === 'OK')) { - const response = this.process(data.payload, request.href); - return new AuthStatusResponse(response[Object.keys(response)[0]][0], data.statusCode); + const response = this.process(data.payload, request.href); + return new AuthStatusResponse(response, data.statusCode); } else { return new AuthStatusResponse(data.payload as AuthStatus, data.statusCode); } diff --git a/src/app/core/auth/auth-type.ts b/src/app/core/auth/auth-type.ts index b8879ae445..9a248da91f 100644 --- a/src/app/core/auth/auth-type.ts +++ b/src/app/core/auth/auth-type.ts @@ -1,4 +1,4 @@ export enum AuthType { - Eperson = 'eperson', + EPerson = 'eperson', Status = 'status' } diff --git a/src/app/core/auth/auth.actions.ts b/src/app/core/auth/auth.actions.ts index 207e8fae70..d0969d38d4 100644 --- a/src/app/core/auth/auth.actions.ts +++ b/src/app/core/auth/auth.actions.ts @@ -5,7 +5,7 @@ import { Action } from '@ngrx/store'; import { type } from '../../shared/ngrx/type'; // import models -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; export const AuthActionTypes = { @@ -76,10 +76,10 @@ export class AuthenticatedSuccessAction implements Action { payload: { authenticated: boolean; authToken: AuthTokenInfo; - user: Eperson + user: EPerson }; - constructor(authenticated: boolean, authToken: AuthTokenInfo, user: Eperson) { + constructor(authenticated: boolean, authToken: AuthTokenInfo, user: EPerson) { this.payload = { authenticated, authToken, user }; } } @@ -250,9 +250,9 @@ export class RefreshTokenErrorAction implements Action { */ export class RegistrationAction implements Action { public type: string = AuthActionTypes.REGISTRATION; - payload: Eperson; + payload: EPerson; - constructor(user: Eperson) { + constructor(user: EPerson) { this.payload = user; } } @@ -278,9 +278,9 @@ export class RegistrationErrorAction implements Action { */ export class RegistrationSuccessAction implements Action { public type: string = AuthActionTypes.REGISTRATION_SUCCESS; - payload: Eperson; + payload: EPerson; - constructor(user: Eperson) { + constructor(user: EPerson) { this.payload = user; } } diff --git a/src/app/core/auth/auth.effects.spec.ts b/src/app/core/auth/auth.effects.spec.ts index 3b569e523f..d75b407516 100644 --- a/src/app/core/auth/auth.effects.spec.ts +++ b/src/app/core/auth/auth.effects.spec.ts @@ -25,12 +25,11 @@ import { AuthServiceStub } from '../../shared/testing/auth-service-stub'; import { AuthService } from './auth.service'; import { TruncatablesState } from '../../shared/truncatable/truncatable.reducer'; -import { EpersonMock } from '../../shared/testing/eperson-mock'; +import { EPersonMock } from '../../shared/testing/eperson-mock'; describe('AuthEffects', () => { let authEffects: AuthEffects; let actions: Observable; - const authServiceStub = new AuthServiceStub(); const store: Store = jasmine.createSpyObj('store', { /* tslint:disable:no-empty */ @@ -105,7 +104,7 @@ describe('AuthEffects', () => { it('should return a AUTHENTICATED_SUCCESS action in response to a AUTHENTICATED action', () => { actions = hot('--a-', {a: {type: AuthActionTypes.AUTHENTICATED, payload: token}}); - const expected = cold('--b-', {b: new AuthenticatedSuccessAction(true, token, EpersonMock)}); + const expected = cold('--b-', {b: new AuthenticatedSuccessAction(true, token, EPersonMock)}); expect(authEffects.authenticated$).toBeObservable(expected); }); diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index e2d6c80b5e..82def702eb 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -28,7 +28,7 @@ import { RegistrationErrorAction, RegistrationSuccessAction } from './auth.actions'; -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; import { AppState } from '../../app.reducer'; @@ -63,7 +63,7 @@ export class AuthEffects { .ofType(AuthActionTypes.AUTHENTICATED) .switchMap((action: AuthenticatedAction) => { return this.authService.authenticatedUser(action.payload) - .map((user: Eperson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)) + .map((user: EPerson) => new AuthenticatedSuccessAction((user !== null), action.payload, user)) .catch((error) => Observable.of(new AuthenticatedErrorAction(error))); }); @@ -88,7 +88,7 @@ export class AuthEffects { .debounceTime(500) // to remove when functionality is implemented .switchMap((action: RegistrationAction) => { return this.authService.create(action.payload) - .map((user: Eperson) => new RegistrationSuccessAction(user)) + .map((user: EPerson) => new RegistrationSuccessAction(user)) .catch((error) => Observable.of(new RegistrationErrorAction(error))); }); diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index 651e2fd096..f38abb90bc 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -35,7 +35,7 @@ export class AuthInterceptor implements HttpInterceptor { } private isSuccess(response: HttpResponseBase): boolean { - return response.status === 200; + return (response.status === 200 || response.status === 204); } private isAuthRequest(http: HttpRequest | HttpResponseBase): boolean { diff --git a/src/app/core/auth/auth.reducer.spec.ts b/src/app/core/auth/auth.reducer.spec.ts index f148f3ac8d..ca2ba00036 100644 --- a/src/app/core/auth/auth.reducer.spec.ts +++ b/src/app/core/auth/auth.reducer.spec.ts @@ -21,7 +21,7 @@ import { SetRedirectUrlAction } from './auth.actions'; import { AuthTokenInfo } from './models/auth-token-info.model'; -import { EpersonMock } from '../../shared/testing/eperson-mock'; +import { EPersonMock } from '../../shared/testing/eperson-mock'; describe('authReducer', () => { @@ -107,7 +107,7 @@ describe('authReducer', () => { loading: true, info: undefined }; - const action = new AuthenticatedSuccessAction(true, mockTokenInfo, EpersonMock); + const action = new AuthenticatedSuccessAction(true, mockTokenInfo, EPersonMock); const newState = authReducer(initialState, action); state = { authenticated: true, @@ -116,7 +116,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; expect(newState).toEqual(state); }); @@ -182,7 +182,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const action = new LogOutAction(); @@ -199,7 +199,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const action = new LogOutSuccessAction(); @@ -225,7 +225,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const action = new LogOutErrorAction(mockError); @@ -237,7 +237,7 @@ describe('authReducer', () => { error: 'Test error message', loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; expect(newState).toEqual(state); }); @@ -250,7 +250,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; const newTokenInfo = new AuthTokenInfo('Refreshed token'); const action = new RefreshTokenAction(newTokenInfo); @@ -262,7 +262,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: true }; expect(newState).toEqual(state); @@ -276,7 +276,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: true }; const newTokenInfo = new AuthTokenInfo('Refreshed token'); @@ -289,7 +289,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: false }; expect(newState).toEqual(state); @@ -303,7 +303,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock, + user: EPersonMock, refreshing: true }; const action = new RefreshTokenErrorAction(); @@ -329,7 +329,7 @@ describe('authReducer', () => { error: undefined, loading: false, info: undefined, - user: EpersonMock + user: EPersonMock }; state = { diff --git a/src/app/core/auth/auth.reducer.ts b/src/app/core/auth/auth.reducer.ts index 0c5e36ce91..98827d842e 100644 --- a/src/app/core/auth/auth.reducer.ts +++ b/src/app/core/auth/auth.reducer.ts @@ -12,7 +12,7 @@ import { SetRedirectUrlAction } from './auth.actions'; // import models -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; /** @@ -46,7 +46,7 @@ export interface AuthState { refreshing?: boolean; // the authenticated user - user?: Eperson; + user?: EPerson; } /** diff --git a/src/app/core/auth/auth.service.spec.ts b/src/app/core/auth/auth.service.spec.ts index b54f65078e..c943a815e7 100644 --- a/src/app/core/auth/auth.service.spec.ts +++ b/src/app/core/auth/auth.service.spec.ts @@ -18,10 +18,12 @@ import { AuthRequestServiceStub } from '../../shared/testing/auth-request-servic import { AuthRequestService } from './auth-request.service'; import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo } from './models/auth-token-info.model'; -import { Eperson } from '../eperson/models/eperson.model'; -import { EpersonMock } from '../../shared/testing/eperson-mock'; +import { EPerson } from '../eperson/models/eperson.model'; +import { EPersonMock } from '../../shared/testing/eperson-mock'; import { AppState } from '../../app.reducer'; import { ClientCookieService } from '../../shared/services/client-cookie.service'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service'; describe('AuthService test', () => { @@ -42,9 +44,9 @@ describe('AuthService test', () => { loaded: true, loading: false, authToken: token, - user: EpersonMock + user: EPersonMock }; - + const rdbService = getMockRemoteDataBuildService(); describe('', () => { beforeEach(() => { @@ -61,6 +63,7 @@ describe('AuthService test', () => { {provide: Router, useValue: routerStub}, {provide: ActivatedRoute, useValue: routeStub}, {provide: Store, useValue: mockStore}, + {provide: RemoteDataBuildService, useValue: rdbService}, CookieService, AuthService ], @@ -79,7 +82,7 @@ describe('AuthService test', () => { }); it('should return the authenticated user object when user token is valid', () => { - authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((user: Eperson) => { + authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((user: EPerson) => { expect(user).toBeDefined(); }); }); @@ -121,6 +124,7 @@ describe('AuthService test', () => { {provide: AuthRequestService, useValue: authRequest}, {provide: REQUEST, useValue: {}}, {provide: Router, useValue: routerStub}, + {provide: RemoteDataBuildService, useValue: rdbService}, CookieService ] }).compileComponents(); @@ -132,7 +136,7 @@ describe('AuthService test', () => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, authReqService, router, cookieService, store); + authService = new AuthService({}, window, authReqService, router, cookieService, store, rdbService); })); it('should return true when user is logged in', () => { @@ -184,14 +188,14 @@ describe('AuthService test', () => { loaded: true, loading: false, authToken: expiredToken, - user: EpersonMock + user: EPersonMock }; store .subscribe((state) => { (state as any).core = Object.create({}); (state as any).core.auth = authenticatedState; }); - authService = new AuthService({}, window, authReqService, router, cookieService, store); + authService = new AuthService({}, window, authReqService, router, cookieService, store, rdbService); storage = (authService as any).storage; spyOn(storage, 'get'); spyOn(storage, 'remove'); diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 2848b54b50..5f113b0262 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -7,9 +7,9 @@ import { RouterReducerState } from '@ngrx/router-store'; import { Store } from '@ngrx/store'; import { CookieAttributes } from 'js-cookie'; import { Observable } from 'rxjs/Observable'; -import { map, withLatestFrom } from 'rxjs/operators'; +import { map, switchMap, withLatestFrom } from 'rxjs/operators'; -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; import { AuthRequestService } from './auth-request.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; @@ -17,11 +17,18 @@ import { AuthStatus } from './models/auth-status.model'; import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model'; import { isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util'; import { CookieService } from '../../shared/services/cookie.service'; -import { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors'; +import { + getAuthenticationToken, + getRedirectUrl, + isAuthenticated, + isTokenRefreshing +} from './selectors'; import { AppState, routerStateSelector } from '../../app.reducer'; import { ResetAuthenticationMessagesAction, SetRedirectUrlAction } from './auth.actions'; import { NativeWindowRef, NativeWindowService } from '../../shared/services/window.service'; import { Base64EncodeUrl } from '../../shared/utils/encode-decode.util'; +import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; +import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model'; export const LOGIN_ROUTE = '/login'; export const LOGOUT_ROUTE = '/logout'; @@ -45,7 +52,9 @@ export class AuthService { protected authRequestService: AuthRequestService, protected router: Router, protected storage: CookieService, - protected store: Store) { + protected store: Store, + protected rdbService: RemoteDataBuildService + ) { this.store.select(isAuthenticated) .startWith(false) .subscribe((authenticated: boolean) => this._authenticated = authenticated); @@ -116,21 +125,26 @@ export class AuthService { * Returns the authenticated user * @returns {User} */ - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { // Determine if the user has an existing auth session on the server const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); headers = headers.append('Accept', 'application/json'); headers = headers.append('Authorization', `Bearer ${token.accessToken}`); options.headers = headers; - return this.authRequestService.getRequest('status', options) - .map((status: AuthStatus) => { + return this.authRequestService.getRequest('status', options).pipe( + switchMap((status: AuthStatus) => { + if (status.authenticated) { - return status.eperson[0]; + // TODO this should be cleaned up, AuthStatus could be parsed by the RemoteDataService as a whole... + // Review when https://jira.duraspace.org/browse/DS-4006 is fixed + // See https://github.com/DSpace/dspace-angular/issues/292 + const person$ = this.rdbService.buildSingle(status.eperson.toString()); + return person$.pipe(map((eperson) => eperson.payload)); } else { throw(new Error('Not authenticated')); } - }); + })) } /** @@ -188,7 +202,7 @@ export class AuthService { * Create a new user * @returns {User} */ - public create(user: Eperson): Observable { + public create(user: EPerson): Observable { // Normally you would do an HTTP request to POST the user // details and then return the new user object // but, let's just return the new user for this example. @@ -204,7 +218,7 @@ export class AuthService { // Send a request that sign end the session let headers = new HttpHeaders(); headers = headers.append('Content-Type', 'application/x-www-form-urlencoded'); - const options: HttpOptions = Object.create({headers, responseType: 'text'}); + const options: HttpOptions = Object.create({ headers, responseType: 'text' }); return this.authRequestService.getRequest('logout', options) .map((status: AuthStatus) => { if (!status.authenticated) { @@ -213,7 +227,6 @@ export class AuthService { throw(new Error('auth.errors.invalid-user')); } }) - } /** @@ -279,7 +292,7 @@ export class AuthService { // Set the cookie expire date const expires = new Date(expireDate); - const options: CookieAttributes = {expires: expires}; + const options: CookieAttributes = { expires: expires }; // Save cookie with the token return this.storage.set(TOKENITEM, token, options); @@ -337,8 +350,12 @@ export class AuthService { this.router.navigated = false; const url = decodeURIComponent(redirectUrl); this.router.navigateByUrl(url); + /* TODO Reenable hard redirect when REST API can handle x-forwarded-for, see https://github.com/DSpace/DSpace/pull/2207 */ + // this._window.nativeWindow.location.href = url; } else { this.router.navigate(['/']); + /* TODO Reenable hard redirect when REST API can handle x-forwarded-for, see https://github.com/DSpace/DSpace/pull/2207 */ + // this._window.nativeWindow.location.href = '/'; } }) @@ -374,7 +391,7 @@ export class AuthService { // Set the cookie expire date const expires = new Date(expireDate); - const options: CookieAttributes = {expires: expires}; + const options: CookieAttributes = { expires: expires }; this.storage.set(REDIRECT_COOKIE, url, options); this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(url) ? url : '')); } diff --git a/src/app/core/auth/models/auth-status.model.ts b/src/app/core/auth/models/auth-status.model.ts index 22c9d14718..b8ccf9ed6d 100644 --- a/src/app/core/auth/models/auth-status.model.ts +++ b/src/app/core/auth/models/auth-status.model.ts @@ -1,7 +1,8 @@ import { AuthError } from './auth-error.model'; import { AuthTokenInfo } from './auth-token-info.model'; -import { DSpaceObject } from '../../shared/dspace-object.model'; -import { Eperson } from '../../eperson/models/eperson.model'; +import { EPerson } from '../../eperson/models/eperson.model'; +import { RemoteData } from '../../data/remote-data'; +import { Observable } from 'rxjs/Observable'; export class AuthStatus { @@ -13,7 +14,7 @@ export class AuthStatus { error?: AuthError; - eperson: Eperson[]; + eperson: Observable>; token?: AuthTokenInfo; diff --git a/src/app/core/auth/models/normalized-auth-status.model.ts b/src/app/core/auth/models/normalized-auth-status.model.ts index 19952f7c70..b8dd2aa23e 100644 --- a/src/app/core/auth/models/normalized-auth-status.model.ts +++ b/src/app/core/auth/models/normalized-auth-status.model.ts @@ -1,12 +1,18 @@ import { AuthStatus } from './auth-status.model'; import { autoserialize, autoserializeAs, inheritSerialization } from 'cerialize'; -import { mapsTo } from '../../cache/builders/build-decorators'; -import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Eperson } from '../../eperson/models/eperson.model'; +import { mapsTo, relationship } from '../../cache/builders/build-decorators'; +import { ResourceType } from '../../shared/resource-type'; +import { NormalizedObject } from '../../cache/models/normalized-object.model'; +import { IDToUUIDSerializer } from '../../cache/id-to-uuid-serializer'; @mapsTo(AuthStatus) -@inheritSerialization(NormalizedDSpaceObject) -export class NormalizedAuthStatus extends NormalizedDSpaceObject { +@inheritSerialization(NormalizedObject) +export class NormalizedAuthStatus extends NormalizedObject { + @autoserialize + id: string; + + @autoserializeAs(new IDToUUIDSerializer('auth-status'), 'id') + uuid: string; /** * True if REST API is up and running, should never return false @@ -20,7 +26,7 @@ export class NormalizedAuthStatus extends NormalizedDSpaceObject { @autoserialize authenticated: boolean; - @autoserializeAs(Eperson) - eperson: Eperson[]; - + @relationship(ResourceType.EPerson, false) + @autoserialize + eperson: string; } diff --git a/src/app/core/auth/server-auth.service.ts b/src/app/core/auth/server-auth.service.ts index 96ee2e355a..9030443a1e 100644 --- a/src/app/core/auth/server-auth.service.ts +++ b/src/app/core/auth/server-auth.service.ts @@ -1,3 +1,4 @@ +import { first, map, switchMap } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; @@ -8,7 +9,8 @@ import { isNotEmpty } from '../../shared/empty.util'; import { AuthService } from './auth.service'; import { AuthTokenInfo } from './models/auth-token-info.model'; import { CheckAuthenticationTokenAction } from './auth.actions'; -import { Eperson } from '../eperson/models/eperson.model'; +import { EPerson } from '../eperson/models/eperson.model'; +import { NormalizedEPerson } from '../eperson/models/normalized-eperson.model'; /** * The auth service. @@ -20,7 +22,7 @@ export class ServerAuthService extends AuthService { * Returns the authenticated user * @returns {User} */ - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { // Determine if the user has an existing auth session on the server const options: HttpOptions = Object.create({}); let headers = new HttpHeaders(); @@ -32,14 +34,19 @@ export class ServerAuthService extends AuthService { headers = headers.append('X-Forwarded-For', clientIp); options.headers = headers; - return this.authRequestService.getRequest('status', options) - .map((status: AuthStatus) => { + return this.authRequestService.getRequest('status', options).pipe( + switchMap((status: AuthStatus) => { + if (status.authenticated) { - return status.eperson[0]; + + // TODO this should be cleaned up, AuthStatus could be parsed by the RemoteDataService as a whole... + const person$ = this.rdbService.buildSingle(status.eperson.toString()); + // person$.subscribe(() => console.log('test')); + return person$.pipe(map((eperson) => eperson.payload)); } else { throw(new Error('Not authenticated')); } - }); + })) } /** @@ -53,8 +60,8 @@ export class ServerAuthService extends AuthService { * Redirect to the route navigated before the login */ public redirectToPreviousUrl() { - this.getRedirectUrl() - .first() + this.getRedirectUrl().pipe( + first()) .subscribe((redirectUrl) => { if (isNotEmpty(redirectUrl)) { // override the route reuse strategy diff --git a/src/app/core/cache/models/normalized-object-factory.ts b/src/app/core/cache/models/normalized-object-factory.ts index df67a1f2ce..5c5ebf50aa 100644 --- a/src/app/core/cache/models/normalized-object-factory.ts +++ b/src/app/core/cache/models/normalized-object-factory.ts @@ -8,6 +8,8 @@ import { ResourceType } from '../../shared/resource-type'; import { NormalizedObject } from './normalized-object.model'; import { NormalizedBitstreamFormat } from './normalized-bitstream-format.model'; import { NormalizedResourcePolicy } from './normalized-resource-policy.model'; +import { NormalizedEPerson } from '../../eperson/models/normalized-eperson.model'; +import { NormalizedGroup } from '../../eperson/models/normalized-group.model'; export class NormalizedObjectFactory { public static getConstructor(type: ResourceType): GenericConstructor { @@ -33,6 +35,12 @@ export class NormalizedObjectFactory { case ResourceType.ResourcePolicy: { return NormalizedResourcePolicy } + case ResourceType.EPerson: { + return NormalizedEPerson + } + case ResourceType.Group: { + return NormalizedGroup + } default: { return undefined; } diff --git a/src/app/core/data/base-response-parsing.service.ts b/src/app/core/data/base-response-parsing.service.ts index 050b3c2da5..fdf5b4eb97 100644 --- a/src/app/core/data/base-response-parsing.service.ts +++ b/src/app/core/data/base-response-parsing.service.ts @@ -7,6 +7,8 @@ import { GlobalConfig } from '../../../config/global-config.interface'; import { GenericConstructor } from '../shared/generic-constructor'; import { PaginatedList } from './paginated-list'; import { NormalizedObject } from '../cache/models/normalized-object.model'; +import { ResourceType } from '../shared/resource-type'; +import { RESTURLCombiner } from '../url-combiner/rest-url-combiner'; function isObjectLevel(halObj: any) { return isNotEmpty(halObj._links) && hasValue(halObj._links.self); @@ -34,6 +36,7 @@ export abstract class BaseResponseParsingService { } else if (Array.isArray(data)) { return this.processArray(data, requestHref); } else if (isObjectLevel(data)) { + data = this.fixBadEPersonRestResponse(data); const object = this.deserialize(data); if (isNotEmpty(data._embedded)) { Object @@ -53,6 +56,7 @@ export abstract class BaseResponseParsingService { } }); } + this.cache(object, requestHref); return object; } @@ -145,4 +149,23 @@ export abstract class BaseResponseParsingService { } return obj[keys[0]]; } + + // TODO Remove when https://jira.duraspace.org/browse/DS-4006 is fixed + // See https://github.com/DSpace/dspace-angular/issues/292 + private fixBadEPersonRestResponse(obj: any): any { + if (obj.type === ResourceType.EPerson) { + const groups = obj.groups; + const normGroups = []; + if (isNotEmpty(groups)) { + groups.forEach((group) => { + const parts = ['eperson', 'groups', group.uuid]; + const href = new RESTURLCombiner(this.EnvConfig, ...parts).toString(); + normGroups.push(href); + } + ) + } + return Object.assign({}, obj, { groups: normGroups }); + } + return obj; + } } diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 413de9bb9b..3948c3672f 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -1,3 +1,4 @@ +import { filter, take } from 'rxjs/operators'; import { Store } from '@ngrx/store'; import { Observable } from 'rxjs/Observable'; import { hasValue, isNotEmpty } from '../../shared/empty.util'; @@ -55,9 +56,9 @@ export abstract class DataService findAll(options: FindAllOptions = {}): Observable>> { const hrefObs = this.getFindAllHref(options); - hrefObs - .filter((href: string) => hasValue(href)) - .take(1) + hrefObs.pipe( + filter((href: string) => hasValue(href)), + take(1)) .subscribe((href: string) => { const request = new FindAllRequest(this.requestService.generateRequestId(), href, options); this.requestService.configure(request); diff --git a/src/app/core/eperson/models/eperson.model.ts b/src/app/core/eperson/models/eperson.model.ts index 373fb42792..45d26761b0 100644 --- a/src/app/core/eperson/models/eperson.model.ts +++ b/src/app/core/eperson/models/eperson.model.ts @@ -1,7 +1,7 @@ import { DSpaceObject } from '../../shared/dspace-object.model'; import { Group } from './group.model'; -export class Eperson extends DSpaceObject { +export class EPerson extends DSpaceObject { public handle: string; diff --git a/src/app/core/eperson/models/NormalizedEperson.model.ts b/src/app/core/eperson/models/normalized-eperson.model.ts similarity index 84% rename from src/app/core/eperson/models/NormalizedEperson.model.ts rename to src/app/core/eperson/models/normalized-eperson.model.ts index 0c0b2490d6..9d0fa428e9 100644 --- a/src/app/core/eperson/models/NormalizedEperson.model.ts +++ b/src/app/core/eperson/models/normalized-eperson.model.ts @@ -2,13 +2,13 @@ import { autoserialize, inheritSerialization } from 'cerialize'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Eperson } from './eperson.model'; +import { EPerson } from './eperson.model'; import { mapsTo, relationship } from '../../cache/builders/build-decorators'; import { ResourceType } from '../../shared/resource-type'; -@mapsTo(Eperson) +@mapsTo(EPerson) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedEpersonModel extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedEPerson extends NormalizedDSpaceObject implements CacheableObject, ListableObject { @autoserialize public handle: string; diff --git a/src/app/core/eperson/models/NormalizedGroup.model.ts b/src/app/core/eperson/models/normalized-group.model.ts similarity index 79% rename from src/app/core/eperson/models/NormalizedGroup.model.ts rename to src/app/core/eperson/models/normalized-group.model.ts index 24f7da8eab..be5995d9c5 100644 --- a/src/app/core/eperson/models/NormalizedGroup.model.ts +++ b/src/app/core/eperson/models/normalized-group.model.ts @@ -2,13 +2,12 @@ import { autoserialize, inheritSerialization } from 'cerialize'; import { CacheableObject } from '../../cache/object-cache.reducer'; import { ListableObject } from '../../../shared/object-collection/shared/listable-object.model'; import { NormalizedDSpaceObject } from '../../cache/models/normalized-dspace-object.model'; -import { Eperson } from './eperson.model'; import { mapsTo } from '../../cache/builders/build-decorators'; import { Group } from './group.model'; @mapsTo(Group) @inheritSerialization(NormalizedDSpaceObject) -export class NormalizedGroupModel extends NormalizedDSpaceObject implements CacheableObject, ListableObject { +export class NormalizedGroup extends NormalizedDSpaceObject implements CacheableObject, ListableObject { @autoserialize public handle: string; diff --git a/src/app/core/shared/resource-type.ts b/src/app/core/shared/resource-type.ts index 71053f628b..e67f3339de 100644 --- a/src/app/core/shared/resource-type.ts +++ b/src/app/core/shared/resource-type.ts @@ -6,7 +6,7 @@ export enum ResourceType { Item = 'item', Collection = 'collection', Community = 'community', - Eperson = 'eperson', + EPerson = 'eperson', Group = 'group', ResourcePolicy = 'resourcePolicy' } diff --git a/src/app/header/header.component.spec.ts b/src/app/header/header.component.spec.ts index 87fa2995d6..9d0dd04e40 100644 --- a/src/app/header/header.component.spec.ts +++ b/src/app/header/header.component.spec.ts @@ -19,6 +19,7 @@ import { HostWindowServiceStub } from '../shared/testing/host-window-service-stu import { RouterStub } from '../shared/testing/router-stub'; import { Router } from '@angular/router'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; let comp: HeaderComponent; let fixture: ComponentFixture; @@ -35,11 +36,12 @@ describe('HeaderComponent', () => { NgbCollapseModule.forRoot(), NoopAnimationsModule, ReactiveFormsModule], - declarations: [HeaderComponent, AuthNavMenuComponent, LoadingComponent, LogInComponent, LogOutComponent], + declarations: [HeaderComponent], providers: [ { provide: HostWindowService, useValue: new HostWindowServiceStub(800) }, { provide: Router, useClass: RouterStub }, - ] + ], + schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); // compile template and css })); diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts index 8b9f7c8775..e1a82f4a33 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.spec.ts @@ -5,7 +5,7 @@ import { By } from '@angular/platform-browser'; import { Store, StoreModule } from '@ngrx/store'; import { authReducer, AuthState } from '../../core/auth/auth.reducer'; -import { EpersonMock } from '../testing/eperson-mock'; +import { EPersonMock } from '../testing/eperson-mock'; import { TranslateModule } from '@ngx-translate/core'; import { AppState } from '../../app.reducer'; import { AuthNavMenuComponent } from './auth-nav-menu.component'; @@ -13,6 +13,7 @@ import { HostWindowServiceStub } from '../testing/host-window-service-stub'; import { HostWindowService } from '../host-window.service'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; +import { AuthService } from '../../core/auth/auth.service'; describe('AuthNavMenuComponent', () => { @@ -31,7 +32,7 @@ describe('AuthNavMenuComponent', () => { loaded: true, loading: false, authToken: new AuthTokenInfo('test_token'), - user: EpersonMock + user: EPersonMock }; let routerState = { url: '/home' @@ -53,6 +54,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ {provide: HostWindowService, useValue: window}, + {provide: AuthService, useValue: {setRedirectUrl: () => { /*empty*/ }}} ], schemas: [ CUSTOM_ELEMENTS_SCHEMA @@ -222,6 +224,7 @@ describe('AuthNavMenuComponent', () => { ], providers: [ {provide: HostWindowService, useValue: window}, + {provide: AuthService, useValue: {setRedirectUrl: () => { /*empty*/ }}} ], schemas: [ CUSTOM_ELEMENTS_SCHEMA diff --git a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts index 1c376258fb..c657071987 100644 --- a/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts +++ b/src/app/shared/auth-nav-menu/auth-nav-menu.component.ts @@ -7,9 +7,14 @@ import { fadeInOut, fadeOut } from '../animations/fade'; import { HostWindowService } from '../host-window.service'; import { AppState, routerStateSelector } from '../../app.reducer'; import { isNotUndefined } from '../empty.util'; -import { getAuthenticatedUser, isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors'; -import { Eperson } from '../../core/eperson/models/eperson.model'; -import { LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; +import { + getAuthenticatedUser, + isAuthenticated, + isAuthenticationLoading +} from '../../core/auth/selectors'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { AuthService, LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; +import { Subscription } from 'rxjs/Subscription'; @Component({ selector: 'ds-auth-nav-menu', @@ -34,10 +39,14 @@ export class AuthNavMenuComponent implements OnInit { public showAuth = Observable.of(false); - public user: Observable; + public user: Observable; + + public sub: Subscription; constructor(private store: Store, - private windowService: HostWindowService) { + private windowService: HostWindowService, + private authService: AuthService + ) { this.isXsOrSm$ = this.windowService.isXsOrSm(); } @@ -53,7 +62,12 @@ export class AuthNavMenuComponent implements OnInit { this.showAuth = this.store.select(routerStateSelector) .filter((router: RouterReducerState) => isNotUndefined(router) && isNotUndefined(router.state)) .map((router: RouterReducerState) => { - return !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); + const url = router.state.url; + const show = !router.state.url.startsWith(LOGIN_ROUTE) && !router.state.url.startsWith(LOGOUT_ROUTE); + if (show) { + this.authService.setRedirectUrl(url); + } + return show; }); } } diff --git a/src/app/shared/log-in/log-in.component.spec.ts b/src/app/shared/log-in/log-in.component.spec.ts index dc4a0be1c6..dd2aea35d5 100644 --- a/src/app/shared/log-in/log-in.component.spec.ts +++ b/src/app/shared/log-in/log-in.component.spec.ts @@ -7,8 +7,8 @@ import { Store, StoreModule } from '@ngrx/store'; import { LogInComponent } from './log-in.component'; import { authReducer } from '../../core/auth/auth.reducer'; -import { EpersonMock } from '../testing/eperson-mock'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPersonMock } from '../testing/eperson-mock'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { TranslateModule } from '@ngx-translate/core'; import { AuthService } from '../../core/auth/auth.service'; import { AuthServiceStub } from '../testing/auth-service-stub'; @@ -19,7 +19,7 @@ describe('LogInComponent', () => { let component: LogInComponent; let fixture: ComponentFixture; let page: Page; - let user: Eperson; + let user: EPerson; const authState = { authenticated: false, @@ -28,7 +28,7 @@ describe('LogInComponent', () => { }; beforeEach(() => { - user = EpersonMock; + user = EPersonMock; }); beforeEach(async(() => { diff --git a/src/app/shared/log-out/log-out.component.spec.ts b/src/app/shared/log-out/log-out.component.spec.ts index ad609f0aea..94780ead5a 100644 --- a/src/app/shared/log-out/log-out.component.spec.ts +++ b/src/app/shared/log-out/log-out.component.spec.ts @@ -5,8 +5,8 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { Store, StoreModule } from '@ngrx/store'; import { authReducer } from '../../core/auth/auth.reducer'; -import { EpersonMock } from '../testing/eperson-mock'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPersonMock } from '../testing/eperson-mock'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { TranslateModule } from '@ngx-translate/core'; import { Router } from '@angular/router'; import { AppState } from '../../app.reducer'; @@ -18,7 +18,7 @@ describe('LogOutComponent', () => { let component: LogOutComponent; let fixture: ComponentFixture; let page: Page; - let user: Eperson; + let user: EPerson; const authState = { authenticated: false, @@ -28,7 +28,7 @@ describe('LogOutComponent', () => { const routerStub = new RouterStub(); beforeEach(() => { - user = EpersonMock; + user = EPersonMock; }); beforeEach(async(() => { diff --git a/src/app/shared/mocks/mock-remote-data-build.service.ts b/src/app/shared/mocks/mock-remote-data-build.service.ts index c10032eb94..8f93fe2d96 100644 --- a/src/app/shared/mocks/mock-remote-data-build.service.ts +++ b/src/app/shared/mocks/mock-remote-data-build.service.ts @@ -5,6 +5,7 @@ import { ResponseCacheEntry } from '../../core/cache/response-cache.reducer'; import { RemoteData } from '../../core/data/remote-data'; import { RequestEntry } from '../../core/data/request.reducer'; import { hasValue } from '../empty.util'; +import { NormalizedObject } from '../../core/cache/models/normalized-object.model'; export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observable>): RemoteDataBuildService { return { @@ -17,7 +18,8 @@ export function getMockRemoteDataBuildService(toRemoteDataObservable$?: Observab payload } as RemoteData))) } - } + }, + buildSingle: (href$: string | Observable) => Observable.of(new RemoteData(false, false, true, undefined, {})) } as RemoteDataBuildService; } diff --git a/src/app/shared/testing/auth-request-service-stub.ts b/src/app/shared/testing/auth-request-service-stub.ts index 2c47068af4..576b8c2ddf 100644 --- a/src/app/shared/testing/auth-request-service-stub.ts +++ b/src/app/shared/testing/auth-request-service-stub.ts @@ -2,12 +2,13 @@ import { Observable } from 'rxjs/Observable'; import { HttpOptions } from '../../core/dspace-rest-v2/dspace-rest-v2.service'; import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; import { isNotEmpty } from '../empty.util'; -import { EpersonMock } from './eperson-mock'; +import { EPersonMock } from './eperson-mock'; +import { RemoteData } from '../../core/data/remote-data'; export class AuthRequestServiceStub { - protected mockUser: Eperson = EpersonMock; + protected mockUser: EPerson = EPersonMock; protected mockTokenInfo = new AuthTokenInfo('test_token'); public postToEndpoint(method: string, body: any, options?: HttpOptions): Observable { @@ -26,7 +27,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = [this.mockUser]; + authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } @@ -45,7 +46,7 @@ export class AuthRequestServiceStub { if (this.validateToken(token)) { authStatusStub.authenticated = true; authStatusStub.token = this.mockTokenInfo; - authStatusStub.eperson = [this.mockUser]; + authStatusStub.eperson = Observable.of(new RemoteData(false, false, true, undefined, this.mockUser)); } else { authStatusStub.authenticated = false; } diff --git a/src/app/shared/testing/auth-service-stub.ts b/src/app/shared/testing/auth-service-stub.ts index c7d5556910..d6c20c9520 100644 --- a/src/app/shared/testing/auth-service-stub.ts +++ b/src/app/shared/testing/auth-service-stub.ts @@ -1,8 +1,9 @@ import { AuthStatus } from '../../core/auth/models/auth-status.model'; import { Observable } from 'rxjs/Observable'; import { AuthTokenInfo } from '../../core/auth/models/auth-token-info.model'; -import { EpersonMock } from './eperson-mock'; -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPersonMock } from './eperson-mock'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { RemoteData } from '../../core/data/remote-data'; export class AuthServiceStub { @@ -19,7 +20,7 @@ export class AuthServiceStub { authStatus.okay = true; authStatus.authenticated = true; authStatus.token = this.token; - authStatus.eperson = [EpersonMock]; + authStatus.eperson = Observable.of(new RemoteData(false, false, true, undefined, EPersonMock)); return Observable.of(authStatus); } else { console.log('error'); @@ -27,9 +28,9 @@ export class AuthServiceStub { } } - public authenticatedUser(token: AuthTokenInfo): Observable { + public authenticatedUser(token: AuthTokenInfo): Observable { if (token.accessToken === 'token_test') { - return Observable.of(EpersonMock); + return Observable.of(EPersonMock); } else { throw(new Error('Message Error test')); } diff --git a/src/app/shared/testing/eperson-mock.ts b/src/app/shared/testing/eperson-mock.ts index 9cf938fcf2..f163a490b9 100644 --- a/src/app/shared/testing/eperson-mock.ts +++ b/src/app/shared/testing/eperson-mock.ts @@ -1,6 +1,6 @@ -import { Eperson } from '../../core/eperson/models/eperson.model'; +import { EPerson } from '../../core/eperson/models/eperson.model'; -export const EpersonMock: Eperson = Object.assign(new Eperson(),{ +export const EPersonMock: EPerson = Object.assign(new EPerson(),{ handle: null, groups: [], netid: 'test@test.com', diff --git a/yarn.lock b/yarn.lock index 95cf41ac55..81c0c807c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -90,20 +90,20 @@ resolved "https://registry.yarnpkg.com/@ng-dynamic-forms/ui-ng-bootstrap/-/ui-ng-bootstrap-5.4.7.tgz#66d037a226da96fe84c4dbac98e4dba859c551f8" "@ngrx/effects@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-5.1.0.tgz#cef84576b2d0333f19188aedfe156fd301bff70a" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/effects/-/effects-5.2.0.tgz#aa762b69cb6fd4644d724a1cecd265caa42baf09" "@ngrx/router-store@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-5.0.1.tgz#db872327bb958a2ebf296734c97de68672ec628a" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/router-store/-/router-store-5.2.0.tgz#bf4b174ce19a36eba8211fc1ddeaf1e35ae74368" "@ngrx/store-devtools@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-5.1.0.tgz#7df8a6da652cc792000ad058ca4072a32e3629b1" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/store-devtools/-/store-devtools-5.2.0.tgz#2fff916a9aa349375826772b359dbb64b9e5d622" "@ngrx/store@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-5.1.0.tgz#d957131e62041deede043524fd300db9fa835d68" + version "5.2.0" + resolved "https://registry.yarnpkg.com/@ngrx/store/-/store-5.2.0.tgz#627ed74c9cd95462930485d912a557117b23903e" "@ngtools/webpack@^1.10.0": version "1.10.0" @@ -1963,14 +1963,14 @@ copy-webpack-plugin@^4.4.1: p-limit "^1.0.0" serialize-javascript "^1.4.0" -core-js@2.5.3: - version "2.5.3" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e" - core-js@^2.2.0, core-js@^2.4.0: version "2.5.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" +core-js@^2.5.7: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + core-js@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"