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 {
public type: string = AuthActionTypes.RETRIEVE_AUTHENTICATED_EPERSON_SUCCESS;
payload: EPerson;
payload: string;
constructor(user: EPerson) {
this.payload = user ;
constructor(userId: string) {
this.payload = userId ;
}
}

View File

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

View File

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

View File

@@ -4,7 +4,7 @@ import { HttpHeaders } from '@angular/common/http';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
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 { select, Store } from '@ngrx/store';
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 { AuthStatus } from './models/auth-status.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 { getAuthenticationToken, getRedirectUrl, isAuthenticated, isTokenRefreshing } from './selectors';
import {
getAuthenticatedUserId,
getAuthenticationToken,
getRedirectUrl,
isAuthenticated,
isTokenRefreshing
} from './selectors';
import { AppState, routerStateSelector } from '../../app.reducer';
import {
CheckAuthenticationTokenAction,
@@ -164,7 +170,7 @@ export class AuthService {
}
/**
* Returns the authenticated user
* Returns the authenticated user by href
* @returns {User}
*/
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.
*/

View File

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

View File

@@ -1,9 +1,6 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { Observable } from 'rxjs/internal/Observable';
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 { ProfilePageSecurityFormComponent } from './profile-page-security-form/profile-page-security-form.component';
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 { filter, switchMap, tap } from 'rxjs/operators';
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 { followLink } from '../shared/utils/follow-link-config.model';
import { AuthService } from '../core/auth/auth.service';
@Component({
selector: 'ds-profile-page',
@@ -50,15 +48,14 @@ export class ProfilePageComponent implements OnInit {
*/
NOTIFICATIONS_PREFIX = 'profile.notifications.';
constructor(private store: Store<AppState>,
constructor(private authService: AuthService,
private notificationsService: NotificationsService,
private translate: TranslateService,
private epersonService: EPersonDataService) {
}
ngOnInit(): void {
this.user$ = this.store.pipe(
select(getAuthenticatedUser),
this.user$ = this.authService.getAuthenticatedUserFromStore().pipe(
filter((user: EPerson) => hasValue(user.id)),
switchMap((user: EPerson) => this.epersonService.findById(user.id, followLink('groups'))),
getAllSucceededRemoteData(),

View File

@@ -9,9 +9,9 @@ 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 { 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 { AuthService, LOGIN_ROUTE, LOGOUT_ROUTE } from '../../core/auth/auth.service';
@Component({
selector: 'ds-auth-nav-menu',
@@ -41,7 +41,8 @@ export class AuthNavMenuComponent implements OnInit {
public sub: Subscription;
constructor(private store: Store<AppState>,
private windowService: HostWindowService
private windowService: HostWindowService,
private authService: AuthService
) {
this.isXsOrSm$ = this.windowService.isXsOrSm();
}
@@ -53,7 +54,7 @@ export class AuthNavMenuComponent implements OnInit {
// set loading
this.loading = this.store.pipe(select(isAuthenticationLoading));
this.user = this.store.pipe(select(getAuthenticatedUser));
this.user = this.authService.getAuthenticatedUserFromStore();
this.showAuth = this.store.pipe(
select(routerStateSelector),

View File

@@ -5,9 +5,10 @@ import { select, Store } from '@ngrx/store';
import { EPerson } from '../../../core/eperson/models/eperson.model';
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 { getProfileModulePath } from '../../../app-routing.module';
import { AuthService } from '../../../core/auth/auth.service';
/**
* This component represents the user nav menu.
@@ -42,7 +43,8 @@ export class UserMenuComponent implements OnInit {
*/
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));
// set user
this.user$ = this.store.pipe(select(getAuthenticatedUser));
this.user$ = this.authService.getAuthenticatedUserFromStore();
}
}