70373: Store authenticated EPerson ID in store instead of object

This commit is contained in:
Kristof De Langhe
2020-04-15 11:14:41 +02:00
parent 638793ca5e
commit e43aa15a70
8 changed files with 72 additions and 38 deletions

View File

@@ -402,10 +402,10 @@ export class RetrieveAuthenticatedEpersonAction implements Action {
*/ */
export class RetrieveAuthenticatedEpersonSuccessAction implements Action { export class RetrieveAuthenticatedEpersonSuccessAction implements Action {
public type: string = AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS; public type: string = AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS;
payload: EPerson; payload: string;
constructor(user: EPerson) { constructor(userId: string) {
this.payload = user ; this.payload = userId ;
} }
} }

View File

@@ -43,6 +43,7 @@ import {
RetrieveAuthMethodsSuccessAction, RetrieveAuthMethodsSuccessAction,
RetrieveTokenAction RetrieveTokenAction
} from './auth.actions'; } from './auth.actions';
import { hasValue } from '../../shared/empty.util';
@Injectable() @Injectable()
export class AuthEffects { export class AuthEffects {
@@ -97,8 +98,15 @@ export class AuthEffects {
public retrieveAuthenticatedEperson$: Observable<Action> = this.actions$.pipe( public retrieveAuthenticatedEperson$: Observable<Action> = this.actions$.pipe(
ofType(AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON), ofType(AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON),
switchMap((action: RetrieveAuthenticatedEpersonAction) => { switchMap((action: RetrieveAuthenticatedEpersonAction) => {
return this.authService.retrieveAuthenticatedUserByHref(action.payload).pipe( const impersonatedUserID = this.authService.getImpersonateID();
map((user: EPerson) => new RetrieveAuthenticatedEpersonSuccessAction(user)), let user$: Observable<EPerson>;
if (hasValue(impersonatedUserID)) {
user$ = this.authService.retrieveAuthenticatedUserById(impersonatedUserID);
} else {
user$ = this.authService.retrieveAuthenticatedUserByHref(action.payload);
}
return user$.pipe(
map((user: EPerson) => new RetrieveAuthenticatedEpersonSuccessAction(user.id)),
catchError((error) => observableOf(new RetrieveAuthenticatedEpersonErrorAction(error)))); catchError((error) => observableOf(new RetrieveAuthenticatedEpersonErrorAction(error))));
}) })
); );

View File

@@ -14,7 +14,6 @@ import {
SetRedirectUrlAction SetRedirectUrlAction
} from './auth.actions'; } from './auth.actions';
// import models // import models
import { EPerson } from '../eperson/models/eperson.model';
import { AuthTokenInfo } from './models/auth-token-info.model'; import { AuthTokenInfo } from './models/auth-token-info.model';
import { AuthMethod } from './models/auth.method'; import { AuthMethod } from './models/auth.method';
import { AuthMethodType } from './models/auth.method-type'; import { AuthMethodType } from './models/auth.method-type';
@@ -49,8 +48,8 @@ export interface AuthState {
// true when refreshing token // true when refreshing token
refreshing?: boolean; refreshing?: boolean;
// the authenticated user // the authenticated user's id
user?: EPerson; userId?: string;
// all authentication Methods enabled at the backend // all authentication Methods enabled at the backend
authMethods?: AuthMethod[]; authMethods?: AuthMethod[];
@@ -112,7 +111,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
error: undefined, error: undefined,
loading: false, loading: false,
info: undefined, info: undefined,
user: (action as RetrieveAuthenticatedEpersonSuccessAction).payload userId: (action as RetrieveAuthenticatedEpersonSuccessAction).payload
}); });
case AuthActionTypes.AUTHENTICATE_ERROR: case AuthActionTypes.AUTHENTICATE_ERROR:
@@ -144,7 +143,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
loading: false, loading: false,
info: undefined, info: undefined,
refreshing: false, refreshing: false,
user: undefined userId: undefined
}); });
case AuthActionTypes.REDIRECT_AUTHENTICATION_REQUIRED: case AuthActionTypes.REDIRECT_AUTHENTICATION_REQUIRED:
@@ -155,7 +154,7 @@ export function authReducer(state: any = initialState, action: AuthActions): Aut
loaded: false, loaded: false,
loading: false, loading: false,
info: (action as RedirectWhenTokenExpiredAction as RedirectWhenAuthenticationIsRequiredAction).payload, info: (action as RedirectWhenTokenExpiredAction as RedirectWhenAuthenticationIsRequiredAction).payload,
user: undefined userId: undefined
}); });
case AuthActionTypes.REGISTRATION: case AuthActionTypes.REGISTRATION:

View File

@@ -4,7 +4,7 @@ import { HttpHeaders } from '@angular/common/http';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens'; import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
import { Observable, of as observableOf } from 'rxjs'; import { Observable, of as observableOf } from 'rxjs';
import { distinctUntilChanged, filter, map, startWith, take, withLatestFrom } from 'rxjs/operators'; import { distinctUntilChanged, filter, map, startWith, switchMap, take, withLatestFrom } from 'rxjs/operators';
import { RouterReducerState } from '@ngrx/router-store'; import { RouterReducerState } from '@ngrx/router-store';
import { select, Store } from '@ngrx/store'; import { select, Store } from '@ngrx/store';
import { CookieAttributes } from 'js-cookie'; import { CookieAttributes } from 'js-cookie';
@@ -14,9 +14,15 @@ import { AuthRequestService } from './auth-request.service';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { AuthStatus } from './models/auth-status.model'; import { AuthStatus } from './models/auth-status.model';
import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model'; import { AuthTokenInfo, TOKENITEM } from './models/auth-token-info.model';
import { hasValue, isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util'; import { hasValue, hasValueOperator, isEmpty, isNotEmpty, isNotNull, isNotUndefined } from '../../shared/empty.util';
import { CookieService } from '../services/cookie.service'; import { CookieService } from '../services/cookie.service';
import { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors'; import {
getAuthenticatedUserId,
getAuthenticationToken,
getRedirectUrl,
isAuthenticated,
isTokenRefreshing
} from './selectors';
import { AppState, routerStateSelector } from '../../app.reducer'; import { AppState, routerStateSelector } from '../../app.reducer';
import { import {
CheckAuthenticationTokenAction, CheckAuthenticationTokenAction,
@@ -164,7 +170,7 @@ export class AuthService {
} }
/** /**
* Returns the authenticated user * Returns the authenticated user by href
* @returns {User} * @returns {User}
*/ */
public retrieveAuthenticatedUserByHref(userHref: string): Observable<EPerson> { public retrieveAuthenticatedUserByHref(userHref: string): Observable<EPerson> {
@@ -173,6 +179,29 @@ export class AuthService {
) )
} }
/**
* Returns the authenticated user by id
* @returns {User}
*/
public retrieveAuthenticatedUserById(userId: string): Observable<EPerson> {
return this.epersonService.findById(userId).pipe(
getAllSucceededRemoteDataPayload()
)
}
/**
* Returns the authenticated user from the store
* @returns {User}
*/
public getAuthenticatedUserFromStore(): Observable<EPerson> {
return this.store.pipe(
select(getAuthenticatedUserId),
hasValueOperator(),
switchMap((id: string) => this.epersonService.findById(id)),
getAllSucceededRemoteDataPayload()
)
}
/** /**
* Checks if token is present into browser storage and is valid. * Checks if token is present into browser storage and is valid.
*/ */

View File

@@ -8,7 +8,6 @@ import { createSelector } from '@ngrx/store';
*/ */
import { AuthState } from './auth.reducer'; import { AuthState } from './auth.reducer';
import { AppState } from '../../app.reducer'; import { AppState } from '../../app.reducer';
import { EPerson } from '../eperson/models/eperson.model';
/** /**
* Returns the user state. * Returns the user state.
@@ -36,12 +35,11 @@ const _isAuthenticatedLoaded = (state: AuthState) => state.loaded;
/** /**
* Return the users state * Return the users state
* NOTE: when state is REHYDRATED user object lose prototype so return always a new EPerson object * @function _getAuthenticatedUserId
* @function _getAuthenticatedUser
* @param {State} state * @param {State} state
* @returns {EPerson} * @returns {string} User ID
*/ */
const _getAuthenticatedUser = (state: AuthState) => Object.assign(new EPerson(), state.user); const _getAuthenticatedUserId = (state: AuthState) => state.userId;
/** /**
* Returns the authentication error. * Returns the authentication error.
@@ -119,13 +117,13 @@ const _getAuthenticationMethods = (state: AuthState) => state.authMethods;
export const getAuthenticationMethods = createSelector(getAuthState, _getAuthenticationMethods); export const getAuthenticationMethods = createSelector(getAuthState, _getAuthenticationMethods);
/** /**
* Returns the authenticated user * Returns the authenticated user id
* @function getAuthenticatedUser * @function getAuthenticatedUserId
* @param {AuthState} state * @param {AuthState} state
* @param {any} props * @param {any} props
* @return {User} * @return {string} User ID
*/ */
export const getAuthenticatedUser = createSelector(getAuthState, _getAuthenticatedUser); export const getAuthenticatedUserId = createSelector(getAuthState, _getAuthenticatedUserId);
/** /**
* Returns the authentication error. * Returns the authentication error.

View File

@@ -1,9 +1,6 @@
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable'; import { Observable } from 'rxjs/internal/Observable';
import { EPerson } from '../core/eperson/models/eperson.model'; import { EPerson } from '../core/eperson/models/eperson.model';
import { select, Store } from '@ngrx/store';
import { getAuthenticatedUser } from '../core/auth/selectors';
import { AppState } from '../app.reducer';
import { ProfilePageMetadataFormComponent } from './profile-page-metadata-form/profile-page-metadata-form.component'; import { ProfilePageMetadataFormComponent } from './profile-page-metadata-form/profile-page-metadata-form.component';
import { ProfilePageSecurityFormComponent } from './profile-page-security-form/profile-page-security-form.component'; import { ProfilePageSecurityFormComponent } from './profile-page-security-form/profile-page-security-form.component';
import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsService } from '../shared/notifications/notifications.service';
@@ -13,9 +10,10 @@ import { RemoteData } from '../core/data/remote-data';
import { PaginatedList } from '../core/data/paginated-list'; import { PaginatedList } from '../core/data/paginated-list';
import { filter, switchMap, tap } from 'rxjs/operators'; import { filter, switchMap, tap } from 'rxjs/operators';
import { EPersonDataService } from '../core/eperson/eperson-data.service'; import { EPersonDataService } from '../core/eperson/eperson-data.service';
import { getAllSucceededRemoteData, getRemoteDataPayload, getSucceededRemoteData } from '../core/shared/operators'; import { getAllSucceededRemoteData, getRemoteDataPayload } from '../core/shared/operators';
import { hasValue } from '../shared/empty.util'; import { hasValue } from '../shared/empty.util';
import { followLink } from '../shared/utils/follow-link-config.model'; import { followLink } from '../shared/utils/follow-link-config.model';
import { AuthService } from '../core/auth/auth.service';
@Component({ @Component({
selector: 'ds-profile-page', selector: 'ds-profile-page',
@@ -50,15 +48,14 @@ export class ProfilePageComponent implements OnInit {
*/ */
NOTIFICATIONS_PREFIX = 'profile.notifications.'; NOTIFICATIONS_PREFIX = 'profile.notifications.';
constructor(private store: Store<AppState>, constructor(private authService: AuthService,
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
private translate: TranslateService, private translate: TranslateService,
private epersonService: EPersonDataService) { private epersonService: EPersonDataService) {
} }
ngOnInit(): void { ngOnInit(): void {
this.user$ = this.store.pipe( this.user$ = this.authService.getAuthenticatedUserFromStore().pipe(
select(getAuthenticatedUser),
filter((user: EPerson) => hasValue(user.id)), filter((user: EPerson) => hasValue(user.id)),
switchMap((user: EPerson) => this.epersonService.findById(user.id, followLink('groups'))), switchMap((user: EPerson) => this.epersonService.findById(user.id, followLink('groups'))),
getAllSucceededRemoteData(), getAllSucceededRemoteData(),

View File

@@ -9,9 +9,9 @@ import { fadeInOut, fadeOut } from '../animations/fade';
import { HostWindowService } from '../host-window.service'; import { HostWindowService } from '../host-window.service';
import { AppState, routerStateSelector } from '../../app.reducer'; import { AppState, routerStateSelector } from '../../app.reducer';
import { isNotUndefined } from '../empty.util'; import { isNotUndefined } from '../empty.util';
import { getAuthenticatedUser, isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors'; import { isAuthenticated, isAuthenticationLoading } from '../../core/auth/selectors';
import { EPerson } from '../../core/eperson/models/eperson.model'; import { EPerson } from '../../core/eperson/models/eperson.model';
import { LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service'; import { AuthService, LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service';
@Component({ @Component({
selector: 'ds-auth-nav-menu', selector: 'ds-auth-nav-menu',
@@ -41,7 +41,8 @@ export class AuthNavMenuComponent implements OnInit {
public sub: Subscription; public sub: Subscription;
constructor(private store: Store<AppState>, constructor(private store: Store<AppState>,
private windowService: HostWindowService private windowService: HostWindowService,
private authService: AuthService
) { ) {
this.isXsOrSm$ = this.windowService.isXsOrSm(); this.isXsOrSm$ = this.windowService.isXsOrSm();
} }
@@ -53,7 +54,7 @@ export class AuthNavMenuComponent implements OnInit {
// set loading // set loading
this.loading = this.store.pipe(select(isAuthenticationLoading)); this.loading = this.store.pipe(select(isAuthenticationLoading));
this.user = this.store.pipe(select(getAuthenticatedUser)); this.user = this.authService.getAuthenticatedUserFromStore();
this.showAuth = this.store.pipe( this.showAuth = this.store.pipe(
select(routerStateSelector), select(routerStateSelector),

View File

@@ -5,9 +5,10 @@ import { select, Store } from '@ngrx/store';
import { EPerson } from '../../../core/eperson/models/eperson.model'; import { EPerson } from '../../../core/eperson/models/eperson.model';
import { AppState } from '../../../app.reducer'; import { AppState } from '../../../app.reducer';
import { getAuthenticatedUser, isAuthenticationLoading } from '../../../core/auth/selectors'; import { isAuthenticationLoading } from '../../../core/auth/selectors';
import { MYDSPACE_ROUTE } from '../../../+my-dspace-page/my-dspace-page.component'; import { MYDSPACE_ROUTE } from '../../../+my-dspace-page/my-dspace-page.component';
import { getProfileModulePath } from '../../../app-routing.module'; import { getProfileModulePath } from '../../../app-routing.module';
import { AuthService } from '../../../core/auth/auth.service';
/** /**
* This component represents the user nav menu. * This component represents the user nav menu.
@@ -42,7 +43,8 @@ export class UserMenuComponent implements OnInit {
*/ */
public profileRoute = getProfileModulePath(); public profileRoute = getProfileModulePath();
constructor(private store: Store<AppState>) { constructor(private store: Store<AppState>,
private authService: AuthService) {
} }
/** /**
@@ -54,7 +56,7 @@ export class UserMenuComponent implements OnInit {
this.loading$ = this.store.pipe(select(isAuthenticationLoading)); this.loading$ = this.store.pipe(select(isAuthenticationLoading));
// set user // set user
this.user$ = this.store.pipe(select(getAuthenticatedUser)); this.user$ = this.authService.getAuthenticatedUserFromStore();
} }
} }