mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
[CST-15073][CST-15074] Adaptation with standalone components
This commit is contained in:

committed by
Vincenzo Mecca

parent
214a77a65c
commit
83615a1c90
@@ -1,4 +1,8 @@
|
||||
import { InMemoryScrollingOptions, Route, RouterConfigOptions, } from '@angular/router';
|
||||
import {
|
||||
InMemoryScrollingOptions,
|
||||
Route,
|
||||
RouterConfigOptions,
|
||||
} from '@angular/router';
|
||||
|
||||
import { NOTIFICATIONS_MODULE_PATH } from './admin/admin-routing-paths';
|
||||
import {
|
||||
@@ -21,12 +25,8 @@ import { COLLECTION_MODULE_PATH } from './collection-page/collection-page-routin
|
||||
import { COMMUNITY_MODULE_PATH } from './community-page/community-page-routing-paths';
|
||||
import { authBlockingGuard } from './core/auth/auth-blocking.guard';
|
||||
import { authenticatedGuard } from './core/auth/authenticated.guard';
|
||||
import {
|
||||
groupAdministratorGuard
|
||||
} from './core/data/feature-authorization/feature-authorization-guard/group-administrator.guard';
|
||||
import {
|
||||
siteAdministratorGuard
|
||||
} from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
|
||||
import { groupAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/group-administrator.guard';
|
||||
import { siteAdministratorGuard } from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
|
||||
import { siteRegisterGuard } from './core/data/feature-authorization/feature-authorization-guard/site-register.guard';
|
||||
import { endUserAgreementCurrentUserGuard } from './core/end-user-agreement/end-user-agreement-current-user.guard';
|
||||
import { reloadGuard } from './core/reload/reload.guard';
|
||||
@@ -37,9 +37,7 @@ import { ITEM_MODULE_PATH } from './item-page/item-page-routing-paths';
|
||||
import { menuResolver } from './menuResolver';
|
||||
import { provideSuggestionNotificationsState } from './notifications/provide-suggestion-notifications-state';
|
||||
import { ThemedPageErrorComponent } from './page-error/themed-page-error.component';
|
||||
import {
|
||||
ThemedPageInternalServerErrorComponent
|
||||
} from './page-internal-server-error/themed-page-internal-server-error.component';
|
||||
import { ThemedPageInternalServerErrorComponent } from './page-internal-server-error/themed-page-internal-server-error.component';
|
||||
import { ThemedPageNotFoundComponent } from './pagenotfound/themed-pagenotfound.component';
|
||||
import { PROCESS_MODULE_PATH } from './process-page/process-page-routing.paths';
|
||||
import { provideSubmissionState } from './submission/provide-submission-state';
|
||||
@@ -261,17 +259,17 @@ export const APP_ROUTES: Route[] = [
|
||||
},
|
||||
{
|
||||
path: 'external-login/:token',
|
||||
loadChildren: () => import('./external-login-page/external-login-routes').then((m) => m.ROUTES)
|
||||
loadChildren: () => import('./external-login-page/external-login-routes').then((m) => m.ROUTES),
|
||||
},
|
||||
{
|
||||
path: 'review-account/:token',
|
||||
loadChildren: () => import('./external-login-review-account-info-page/external-login-review-account-info-page-routes')
|
||||
.then((m) => m.ROUTES)
|
||||
.then((m) => m.ROUTES),
|
||||
},
|
||||
{
|
||||
path: 'email-confirmation',
|
||||
loadChildren: () => import('./external-login-email-confirmation-page/external-login-email-confirmation-page-routes')
|
||||
.then((m) => m.ROUTES)
|
||||
.then((m) => m.ROUTES),
|
||||
},
|
||||
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent },
|
||||
],
|
||||
|
@@ -1,22 +1,36 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, map, switchMap, take, tap, } from 'rxjs/operators';
|
||||
import {
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
map,
|
||||
switchMap,
|
||||
take,
|
||||
tap,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import { isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
|
||||
import {
|
||||
isNotEmpty,
|
||||
isNotEmptyOperator,
|
||||
} from '../../shared/empty.util';
|
||||
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { DeleteRequest, GetRequest, PostRequest } from '../data/request.models';
|
||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||
import { getFirstCompletedRemoteData } from '../shared/operators';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import {
|
||||
DeleteRequest,
|
||||
GetRequest,
|
||||
PostRequest,
|
||||
} from '../data/request.models';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { RestRequest } from '../data/rest-request.model';
|
||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { getFirstCompletedRemoteData } from '../shared/operators';
|
||||
import { sendRequest } from '../shared/request.operators';
|
||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||
import { AuthStatus } from './models/auth-status.model';
|
||||
import { ShortLivedToken } from './models/short-lived-token.model';
|
||||
import { MachineToken } from './models/machine-token.model';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { sendRequest } from '../shared/request.operators';
|
||||
import { ShortLivedToken } from './models/short-lived-token.model';
|
||||
|
||||
/**
|
||||
* Abstract service to send authentication requests
|
||||
@@ -144,7 +158,7 @@ export abstract class AuthRequestService {
|
||||
map((href: string) => new URLCombiner(href, this.machinetokenEndpoint).toString()),
|
||||
map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL)),
|
||||
tap((request: RestRequest) => this.requestService.send(request)),
|
||||
switchMap((request: RestRequest) => this.rdbService.buildFromRequestUUID<MachineToken>(request.uuid))
|
||||
switchMap((request: RestRequest) => this.rdbService.buildFromRequestUUID<MachineToken>(request.uuid)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,14 +1,33 @@
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { Inject, Injectable, Optional, } from '@angular/core';
|
||||
import {
|
||||
Inject,
|
||||
Injectable,
|
||||
Optional,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { select, Store, } from '@ngrx/store';
|
||||
import {
|
||||
select,
|
||||
Store,
|
||||
} from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CookieAttributes } from 'js-cookie';
|
||||
import { Observable, of as observableOf, } from 'rxjs';
|
||||
import { filter, map, startWith, switchMap, take, } from 'rxjs/operators';
|
||||
import {
|
||||
Observable,
|
||||
of as observableOf,
|
||||
} from 'rxjs';
|
||||
import {
|
||||
filter,
|
||||
map,
|
||||
startWith,
|
||||
switchMap,
|
||||
take,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { REQUEST, RESPONSE, } from '../../../express.tokens';
|
||||
import {
|
||||
REQUEST,
|
||||
RESPONSE,
|
||||
} from '../../../express.tokens';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import {
|
||||
hasNoValue,
|
||||
@@ -22,7 +41,10 @@ import {
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { followLink } from '../../shared/utils/follow-link-config.model';
|
||||
import { buildPaginatedList, PaginatedList, } from '../data/paginated-list.model';
|
||||
import {
|
||||
buildPaginatedList,
|
||||
PaginatedList,
|
||||
} from '../data/paginated-list.model';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||
import { EPersonDataService } from '../eperson/eperson-data.service';
|
||||
@@ -32,17 +54,16 @@ import { CookieService } from '../services/cookie.service';
|
||||
import { HardRedirectService } from '../services/hard-redirect.service';
|
||||
import { RouteService } from '../services/route.service';
|
||||
import {
|
||||
getAuthenticatedUserId,
|
||||
getAuthenticationToken,
|
||||
getExternalAuthCookieStatus,
|
||||
getRedirectUrl,
|
||||
isAuthenticated,
|
||||
isAuthenticatedLoaded,
|
||||
isIdle,
|
||||
isTokenRefreshing
|
||||
} from './selectors';
|
||||
import { getAllSucceededRemoteDataPayload, getFirstCompletedRemoteData, } from '../shared/operators';
|
||||
NativeWindowRef,
|
||||
NativeWindowService,
|
||||
} from '../services/window.service';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import {
|
||||
getAllSucceededRemoteDataPayload,
|
||||
getFirstCompletedRemoteData,
|
||||
} from '../shared/operators';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||
import {
|
||||
CheckAuthenticationTokenAction,
|
||||
RefreshTokenAction,
|
||||
@@ -55,11 +76,21 @@ import {
|
||||
import { AuthRequestService } from './auth-request.service';
|
||||
import { AuthMethod } from './models/auth.method';
|
||||
import { AuthStatus } from './models/auth-status.model';
|
||||
import { AuthTokenInfo, TOKENITEM, } from './models/auth-token-info.model';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { URLCombiner } from '../url-combiner/url-combiner';
|
||||
import {
|
||||
AuthTokenInfo,
|
||||
TOKENITEM,
|
||||
} from './models/auth-token-info.model';
|
||||
import { MachineToken } from './models/machine-token.model';
|
||||
import { NativeWindowRef, NativeWindowService } from '../services/window.service';
|
||||
import {
|
||||
getAuthenticatedUserId,
|
||||
getAuthenticationToken,
|
||||
getExternalAuthCookieStatus,
|
||||
getRedirectUrl,
|
||||
isAuthenticated,
|
||||
isAuthenticatedLoaded,
|
||||
isIdle,
|
||||
isTokenRefreshing,
|
||||
} from './selectors';
|
||||
|
||||
export const LOGIN_ROUTE = '/login';
|
||||
export const LOGOUT_ROUTE = '/logout';
|
||||
|
@@ -1,10 +1,14 @@
|
||||
import { autoserialize, autoserializeAs, deserialize } from 'cerialize';
|
||||
import {
|
||||
autoserialize,
|
||||
autoserializeAs,
|
||||
deserialize,
|
||||
} from 'cerialize';
|
||||
|
||||
import { typedObject } from '../../cache/builders/build-decorators';
|
||||
import { CacheableObject } from '../../cache/cacheable-object.model';
|
||||
import { excludeFromEquals } from '../../utilities/equals.decorators';
|
||||
import { ResourceType } from '../../shared/resource-type';
|
||||
import { HALLink } from '../../shared/hal-link.model';
|
||||
import { ResourceType } from '../../shared/resource-type';
|
||||
import { excludeFromEquals } from '../../utilities/equals.decorators';
|
||||
import { MACHINE_TOKEN } from './machine-token.resource-type';
|
||||
|
||||
/**
|
||||
|
@@ -1,22 +1,36 @@
|
||||
import { HttpHeaders, HttpParams, } from '@angular/common/http';
|
||||
import {
|
||||
HttpHeaders,
|
||||
HttpParams,
|
||||
} from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { RequestService } from './request.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { GetRequest, PatchRequest, PostRequest } from './request.models';
|
||||
import { Operation } from 'fast-json-patch';
|
||||
import { Observable } from 'rxjs';
|
||||
import { filter, find, map, } from 'rxjs/operators';
|
||||
import {
|
||||
filter,
|
||||
find,
|
||||
map,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import { hasValue, isNotEmpty, } from '../../shared/empty.util';
|
||||
import {
|
||||
hasValue,
|
||||
isNotEmpty,
|
||||
} from '../../shared/empty.util';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { HttpOptions } from '../dspace-rest/dspace-rest.service';
|
||||
import { GenericConstructor } from '../shared/generic-constructor';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { getFirstCompletedRemoteData } from '../shared/operators';
|
||||
import { Registration } from '../shared/registration.model';
|
||||
import { ResponseParsingService } from './parsing.service';
|
||||
import { RegistrationResponseParsingService } from './registration-response-parsing.service';
|
||||
import { RemoteData } from './remote-data';
|
||||
import { Operation } from 'fast-json-patch';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import {
|
||||
GetRequest,
|
||||
PatchRequest,
|
||||
PostRequest,
|
||||
} from './request.models';
|
||||
import { RequestService } from './request.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -116,10 +130,10 @@ export class EpersonRegistrationService {
|
||||
map((rd) => {
|
||||
if (rd.hasSucceeded && hasValue(rd.payload)) {
|
||||
return Object.assign(rd, { payload: Object.assign(new Registration(), {
|
||||
email: rd.payload.email,
|
||||
token: token,
|
||||
user: rd.payload.user,
|
||||
}) });
|
||||
email: rd.payload.email,
|
||||
token: token,
|
||||
user: rd.payload.user,
|
||||
}) });
|
||||
} else {
|
||||
return rd;
|
||||
}
|
||||
@@ -144,7 +158,7 @@ export class EpersonRegistrationService {
|
||||
Object.assign(request, {
|
||||
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
||||
return RegistrationResponseParsingService;
|
||||
}
|
||||
},
|
||||
});
|
||||
this.requestService.send(request, true);
|
||||
});
|
||||
@@ -186,7 +200,7 @@ export class EpersonRegistrationService {
|
||||
let operations = [];
|
||||
if (values.length > 0 && hasValue(field) ) {
|
||||
operations = [{
|
||||
op: operator, path: `/${field}`, value: values
|
||||
op: operator, path: `/${field}`, value: values,
|
||||
}];
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,19 @@
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { fakeAsync, TestBed, tick, waitForAsync, } from '@angular/core/testing';
|
||||
import {
|
||||
fakeAsync,
|
||||
TestBed,
|
||||
tick,
|
||||
waitForAsync,
|
||||
} from '@angular/core/testing';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { MockStore, provideMockStore, } from '@ngrx/store/testing';
|
||||
import { compare, Operation, } from 'fast-json-patch';
|
||||
import {
|
||||
MockStore,
|
||||
provideMockStore,
|
||||
} from '@ngrx/store/testing';
|
||||
import {
|
||||
compare,
|
||||
Operation,
|
||||
} from 'fast-json-patch';
|
||||
import { cold } from 'jasmine-marbles';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
|
||||
@@ -13,12 +24,21 @@ import {
|
||||
import { getMockRemoteDataBuildServiceHrefMap } from '../../shared/mocks/remote-data-build.service.mock';
|
||||
import { getMockRequestService } from '../../shared/mocks/request.service.mock';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { createNoContentRemoteDataObject$, createSuccessfulRemoteDataObject$, } from '../../shared/remote-data.utils';
|
||||
import { EPersonMock, EPersonMock2, } from '../../shared/testing/eperson.mock';
|
||||
import {
|
||||
createNoContentRemoteDataObject$,
|
||||
createSuccessfulRemoteDataObject$,
|
||||
} from '../../shared/remote-data.utils';
|
||||
import {
|
||||
EPersonMock,
|
||||
EPersonMock2,
|
||||
} from '../../shared/testing/eperson.mock';
|
||||
import { GroupMock } from '../../shared/testing/group-mock';
|
||||
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service.stub';
|
||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||
import { createPaginatedList, createRequestEntry$, } from '../../shared/testing/utils.test';
|
||||
import {
|
||||
createPaginatedList,
|
||||
createRequestEntry$,
|
||||
} from '../../shared/testing/utils.test';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { RequestParam } from '../cache/models/request-param.model';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
@@ -26,13 +46,19 @@ import { CoreState } from '../core-state.model';
|
||||
import { ChangeAnalyzer } from '../data/change-analyzer';
|
||||
import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
|
||||
import { FindListOptions } from '../data/find-list-options.model';
|
||||
import { PatchRequest, PostRequest, } from '../data/request.models';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import {
|
||||
PatchRequest,
|
||||
PostRequest,
|
||||
} from '../data/request.models';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { Item } from '../shared/item.model';
|
||||
import { editEPersonSelector, EPersonDataService, } from './eperson-data.service';
|
||||
import {
|
||||
editEPersonSelector,
|
||||
EPersonDataService,
|
||||
} from './eperson-data.service';
|
||||
import { EPerson } from './models/eperson.model';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
|
||||
describe('EPersonDataService', () => {
|
||||
let service: EPersonDataService;
|
||||
|
@@ -1,8 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { createSelector, select, Store, } from '@ngrx/store';
|
||||
import {
|
||||
createSelector,
|
||||
select,
|
||||
Store,
|
||||
} from '@ngrx/store';
|
||||
import { Operation } from 'fast-json-patch';
|
||||
import { Observable } from 'rxjs';
|
||||
import { find, map, take, } from 'rxjs/operators';
|
||||
import {
|
||||
find,
|
||||
map,
|
||||
take,
|
||||
} from 'rxjs/operators';
|
||||
|
||||
import { getEPersonEditRoute } from '../../access-control/access-control-routing-paths';
|
||||
import {
|
||||
@@ -11,27 +19,51 @@ import {
|
||||
} from '../../access-control/epeople-registry/epeople-registry.actions';
|
||||
import { EPeopleRegistryState } from '../../access-control/epeople-registry/epeople-registry.reducers';
|
||||
import { AppState } from '../../app.reducer';
|
||||
import { hasNoValue, hasValue, } from '../../shared/empty.util';
|
||||
import {
|
||||
hasNoValue,
|
||||
hasValue,
|
||||
} from '../../shared/empty.util';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { RequestParam } from '../cache/models/request-param.model';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { CreateData, CreateDataImpl, } from '../data/base/create-data';
|
||||
import { DeleteData, DeleteDataImpl, } from '../data/base/delete-data';
|
||||
import {
|
||||
CreateData,
|
||||
CreateDataImpl,
|
||||
} from '../data/base/create-data';
|
||||
import {
|
||||
DeleteData,
|
||||
DeleteDataImpl,
|
||||
} from '../data/base/delete-data';
|
||||
import { IdentifiableDataService } from '../data/base/identifiable-data.service';
|
||||
import { PatchData, PatchDataImpl, } from '../data/base/patch-data';
|
||||
import { SearchData, SearchDataImpl, } from '../data/base/search-data';
|
||||
import {
|
||||
PatchData,
|
||||
PatchDataImpl,
|
||||
} from '../data/base/patch-data';
|
||||
import {
|
||||
SearchData,
|
||||
SearchDataImpl,
|
||||
} from '../data/base/search-data';
|
||||
import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
|
||||
import { FindListOptions } from '../data/find-list-options.model';
|
||||
import { buildPaginatedList, PaginatedList, } from '../data/paginated-list.model';
|
||||
import {
|
||||
buildPaginatedList,
|
||||
PaginatedList,
|
||||
} from '../data/paginated-list.model';
|
||||
import { RemoteData } from '../data/remote-data';
|
||||
import { PatchRequest, PostRequest, } from '../data/request.models';
|
||||
import {
|
||||
PatchRequest,
|
||||
PostRequest,
|
||||
} from '../data/request.models';
|
||||
import { RequestService } from '../data/request.service';
|
||||
import { RestRequestMethod } from '../data/rest-request-method';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { NoContent } from '../shared/NoContent.model';
|
||||
import { getFirstSucceededRemoteData, getRemoteDataPayload, } from '../shared/operators';
|
||||
import {
|
||||
getFirstSucceededRemoteData,
|
||||
getRemoteDataPayload,
|
||||
} from '../shared/operators';
|
||||
import { PageInfo } from '../shared/page-info.model';
|
||||
import { EPerson } from './models/eperson.model';
|
||||
|
||||
@@ -375,8 +407,8 @@ export class EPersonDataService extends IdentifiableDataService<EPerson> impleme
|
||||
map((href: string) =>
|
||||
hasValue(metadataKey)
|
||||
? `${href}/${uuid}?token=${token}&override=${metadataKey}`
|
||||
: `${href}/${uuid}?token=${token}`
|
||||
)
|
||||
: `${href}/${uuid}?token=${token}`,
|
||||
),
|
||||
);
|
||||
|
||||
hrefObs.pipe(
|
||||
|
@@ -1,10 +1,10 @@
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import { AuthRegistrationType } from '../auth/models/auth.registration-type';
|
||||
import { typedObject } from '../cache/builders/build-decorators';
|
||||
import { MetadataValue } from './metadata.models';
|
||||
import { REGISTRATION } from './registration.resource-type';
|
||||
import { ResourceType } from './resource-type';
|
||||
import { UnCacheableObject } from './uncacheable-object.model';
|
||||
import { MetadataValue } from './metadata.models';
|
||||
import { AuthRegistrationType } from '../auth/models/auth.registration-type';
|
||||
|
||||
export class RegistrationDataMetadataMap {
|
||||
[key: string]: RegistrationDataMetadataValue[];
|
||||
|
@@ -9,7 +9,7 @@ const authMethodsMap = new Map();
|
||||
* @param authMethodType the type of the external login method
|
||||
*/
|
||||
export function renderExternalLoginConfirmationFor(
|
||||
authMethodType: AuthRegistrationType
|
||||
authMethodType: AuthRegistrationType,
|
||||
) {
|
||||
return function decorator(objectElement: any) {
|
||||
if (!objectElement) {
|
||||
@@ -23,7 +23,7 @@ export function renderExternalLoginConfirmationFor(
|
||||
* @param authMethodType the type of the external login method
|
||||
*/
|
||||
export function getExternalLoginConfirmationType(
|
||||
authMethodType: AuthRegistrationType
|
||||
authMethodType: AuthRegistrationType,
|
||||
) {
|
||||
return authMethodsMap.get(authMethodType);
|
||||
}
|
||||
|
@@ -1,22 +1,20 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Inject } from '@angular/core';
|
||||
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
|
||||
/**
|
||||
* This component renders a form to complete the registration process
|
||||
*/
|
||||
@Component({
|
||||
template: ''
|
||||
})
|
||||
export abstract class ExternalLoginMethodEntryComponent {
|
||||
|
||||
/**
|
||||
* The registration data object
|
||||
*/
|
||||
public registratioData: Registration;
|
||||
public registrationData: Registration;
|
||||
|
||||
constructor(
|
||||
protected constructor(
|
||||
@Inject('registrationDataProvider') protected injectedRegistrationDataObject: Registration,
|
||||
) {
|
||||
this.registratioData = injectedRegistrationDataObject;
|
||||
this.registrationData = injectedRegistrationDataObject;
|
||||
}
|
||||
}
|
||||
|
@@ -1,24 +1,40 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConfirmEmailComponent } from './confirm-email.component';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateLoader, TranslateModule, TranslateService, } from '@ngx-translate/core';
|
||||
import { EventEmitter, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
import {
|
||||
EventEmitter,
|
||||
NO_ERRORS_SCHEMA,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
FormBuilder,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../../core/auth/auth.service';
|
||||
import { AuthMethodType } from '../../../core/auth/models/auth.method-type';
|
||||
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
|
||||
import { EPerson } from '../../../core/eperson/models/eperson.model';
|
||||
import { HardRedirectService } from '../../../core/services/hard-redirect.service';
|
||||
import { NativeWindowService } from '../../../core/services/window.service';
|
||||
import { Registration } from '../../../core/shared/registration.model';
|
||||
import {
|
||||
MockWindow,
|
||||
NativeWindowMockFactory,
|
||||
} from '../../../shared/mocks/mock-native-window-ref';
|
||||
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||
import { NativeWindowService } from '../../../core/services/window.service';
|
||||
import { MockWindow, NativeWindowMockFactory } from '../../../shared/mocks/mock-native-window-ref';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
import { ConfirmEmailComponent } from './confirm-email.component';
|
||||
|
||||
describe('ConfirmEmailComponent', () => {
|
||||
let component: ConfirmEmailComponent;
|
||||
@@ -52,7 +68,6 @@ describe('ConfirmEmailComponent', () => {
|
||||
redirect: {},
|
||||
});
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ConfirmEmailComponent],
|
||||
providers: [
|
||||
FormBuilder,
|
||||
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
||||
@@ -65,13 +80,14 @@ describe('ConfirmEmailComponent', () => {
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ConfirmEmailComponent,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock,
|
||||
},
|
||||
}),
|
||||
ReactiveFormsModule
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
}).compileComponents();
|
||||
@@ -108,7 +124,7 @@ describe('ConfirmEmailComponent', () => {
|
||||
spyOn(component as any, 'postCreateAccountFromToken');
|
||||
component.submitForm();
|
||||
expect(
|
||||
(component as any).postCreateAccountFromToken
|
||||
(component as any).postCreateAccountFromToken,
|
||||
).toHaveBeenCalledWith('test-token', component.registrationData);
|
||||
});
|
||||
|
||||
@@ -127,7 +143,7 @@ describe('ConfirmEmailComponent', () => {
|
||||
spyOn(component as any, 'patchUpdateRegistration');
|
||||
component.submitForm();
|
||||
expect(
|
||||
(component as any).postCreateAccountFromToken
|
||||
(component as any).postCreateAccountFromToken,
|
||||
).not.toHaveBeenCalled();
|
||||
expect((component as any).patchUpdateRegistration).not.toHaveBeenCalled();
|
||||
});
|
||||
|
@@ -1,24 +1,60 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NgIf } from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
FormBuilder,
|
||||
FormGroup,
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms';
|
||||
import {
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { combineLatest, Subscription, take } from 'rxjs';
|
||||
import {
|
||||
combineLatest,
|
||||
Subscription,
|
||||
take,
|
||||
} from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../../core/auth/auth.service';
|
||||
import { EPersonDataService } from '../../../core/eperson/eperson-data.service';
|
||||
import { EPerson } from '../../../core/eperson/models/eperson.model';
|
||||
import { HardRedirectService } from '../../../core/services/hard-redirect.service';
|
||||
import { getFirstCompletedRemoteData, getRemoteDataPayload } from '../../../core/shared/operators';
|
||||
import {
|
||||
NativeWindowRef,
|
||||
NativeWindowService,
|
||||
} from '../../../core/services/window.service';
|
||||
import {
|
||||
getFirstCompletedRemoteData,
|
||||
getRemoteDataPayload,
|
||||
} from '../../../core/shared/operators';
|
||||
import { Registration } from '../../../core/shared/registration.model';
|
||||
import { hasNoValue, hasValue } from '../../../shared/empty.util';
|
||||
import {
|
||||
hasNoValue,
|
||||
hasValue,
|
||||
} from '../../../shared/empty.util';
|
||||
import { NotificationsService } from '../../../shared/notifications/notifications.service';
|
||||
import { NativeWindowRef, NativeWindowService } from '../../../core/services/window.service';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-confirm-email',
|
||||
templateUrl: './confirm-email.component.html',
|
||||
styleUrls: ['./confirm-email.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [
|
||||
TranslateModule,
|
||||
NgIf,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
})
|
||||
export class ConfirmEmailComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
@@ -55,7 +91,7 @@ export class ConfirmEmailComponent implements OnInit, OnDestroy {
|
||||
|
||||
ngOnInit() {
|
||||
this.emailForm = this.formBuilder.group({
|
||||
email: [this.registrationData.email, [Validators.required, Validators.email]]
|
||||
email: [this.registrationData.email, [Validators.required, Validators.email]],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -102,7 +138,7 @@ export class ConfirmEmailComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
private postCreateAccountFromToken(
|
||||
token: string,
|
||||
registrationData: Registration
|
||||
registrationData: Registration,
|
||||
) {
|
||||
// check if the netId is present
|
||||
// in order to create an account, the netId is required (since the user is created without a password)
|
||||
@@ -131,13 +167,13 @@ export class ConfirmEmailComponent implements OnInit, OnDestroy {
|
||||
getFirstCompletedRemoteData(),
|
||||
),
|
||||
this.externalLoginService.getExternalAuthLocation(this.registrationData.registrationType),
|
||||
this.authService.getRedirectUrl().pipe(take(1))
|
||||
this.authService.getRedirectUrl().pipe(take(1)),
|
||||
])
|
||||
.subscribe(([rd, location, redirectRoute]) => {
|
||||
if (rd.hasFailed) {
|
||||
this.notificationService.error(
|
||||
this.translate.get('external-login-page.provide-email.create-account.notifications.error.header'),
|
||||
this.translate.get('external-login-page.provide-email.create-account.notifications.error.content')
|
||||
this.translate.get('external-login-page.provide-email.create-account.notifications.error.content'),
|
||||
);
|
||||
} else if (rd.hasSucceeded) {
|
||||
// set Redirect URL to User profile, so the user is redirected to the profile page after logging in
|
||||
@@ -145,12 +181,12 @@ export class ConfirmEmailComponent implements OnInit, OnDestroy {
|
||||
const externalServerUrl = this.authService.getExternalServerRedirectUrl(
|
||||
this._window.nativeWindow.origin,
|
||||
redirectRoute,
|
||||
location
|
||||
location,
|
||||
);
|
||||
// redirect to external registration type authentication url
|
||||
this.hardRedirectService.redirect(externalServerUrl);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,11 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ConfirmationSentComponent } from './confirmation-sent.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, EventEmitter } from '@angular/core';
|
||||
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
CUSTOM_ELEMENTS_SCHEMA,
|
||||
EventEmitter,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
|
||||
import { ConfirmationSentComponent } from './confirmation-sent.component';
|
||||
|
||||
describe('ConfirmationSentComponent', () => {
|
||||
let component: ConfirmationSentComponent;
|
||||
@@ -17,27 +27,27 @@ describe('ConfirmationSentComponent', () => {
|
||||
instant: (key: any) => 'Mocked Translation Text',
|
||||
onLangChange: new EventEmitter(),
|
||||
onTranslationChange: new EventEmitter(),
|
||||
onDefaultLangChange: new EventEmitter()
|
||||
onDefaultLangChange: new EventEmitter(),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ConfirmationSentComponent ],
|
||||
providers: [
|
||||
{ provide: TranslateService, useValue: translateServiceStub },
|
||||
],
|
||||
imports: [
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ConfirmationSentComponent,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock
|
||||
}
|
||||
useClass: TranslateLoaderMock,
|
||||
},
|
||||
}),
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -1,9 +1,16 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-confirmation-sent',
|
||||
templateUrl: './confirmation-sent.component.html',
|
||||
styleUrls: ['./confirmation-sent.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [TranslateModule],
|
||||
standalone: true,
|
||||
|
||||
})
|
||||
export class ConfirmationSentComponent { }
|
||||
|
@@ -1,12 +1,18 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ProvideEmailComponent } from './provide-email.component';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
} from '@ngx-translate/core';
|
||||
|
||||
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
import { ProvideEmailComponent } from './provide-email.component';
|
||||
|
||||
describe('ProvideEmailComponent', () => {
|
||||
let component: ProvideEmailComponent;
|
||||
@@ -17,23 +23,23 @@ describe('ProvideEmailComponent', () => {
|
||||
const externalLoginService = jasmine.createSpyObj('ExternalLoginService', ['patchUpdateRegistration']);
|
||||
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ProvideEmailComponent ],
|
||||
providers: [
|
||||
FormBuilder,
|
||||
{ provide: ExternalLoginService, useValue: externalLoginService },
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ProvideEmailComponent,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock
|
||||
}
|
||||
useClass: TranslateLoaderMock,
|
||||
},
|
||||
}),
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -1,14 +1,33 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
import { NgIf } from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
OnDestroy,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
FormBuilder,
|
||||
FormGroup,
|
||||
ReactiveFormsModule,
|
||||
Validators,
|
||||
} from '@angular/forms';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
import { ExternalLoginService } from '../../services/external-login.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-provide-email',
|
||||
templateUrl: './provide-email.component.html',
|
||||
styleUrls: ['./provide-email.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
TranslateModule,
|
||||
NgIf,
|
||||
ReactiveFormsModule,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
export class ProvideEmailComponent implements OnDestroy {
|
||||
/**
|
||||
|
@@ -1,20 +1,28 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExternalLogInComponent } from './external-log-in.component';
|
||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { EventEmitter } from '@angular/core';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
|
||||
import { MetadataValue } from '../../core/shared/metadata.models';
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthServiceMock } from '../../shared/mocks/auth.service.mock';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { OrcidConfirmationComponent } from '../registration-types/orcid-confirmation/orcid-confirmation.component';
|
||||
import { AuthServiceMock } from '../../shared/mocks/auth.service.mock';
|
||||
import { BrowserOnlyPipe } from '../../shared/utils/browser-only.pipe';
|
||||
import { ConfirmEmailComponent } from '../email-confirmation/confirm-email/confirm-email.component';
|
||||
import { OrcidConfirmationComponent } from '../registration-types/orcid-confirmation/orcid-confirmation.component';
|
||||
import { ExternalLogInComponent } from './external-log-in.component';
|
||||
|
||||
describe('ExternalLogInComponent', () => {
|
||||
let component: ExternalLogInComponent;
|
||||
@@ -37,27 +45,32 @@ describe('ExternalLogInComponent', () => {
|
||||
place: -1,
|
||||
}),
|
||||
],
|
||||
}
|
||||
},
|
||||
};
|
||||
const translateServiceStub = {
|
||||
get: () => observableOf('Info Text'),
|
||||
instant: (key: any) => 'Info Text',
|
||||
onLangChange: new EventEmitter(),
|
||||
onTranslationChange: new EventEmitter(),
|
||||
onDefaultLangChange: new EventEmitter()
|
||||
onDefaultLangChange: new EventEmitter(),
|
||||
};
|
||||
|
||||
beforeEach(() =>
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CommonModule, TranslateModule.forRoot({})],
|
||||
declarations: [BrowserOnlyPipe, ExternalLogInComponent, OrcidConfirmationComponent],
|
||||
imports: [CommonModule, TranslateModule.forRoot({}), BrowserOnlyPipe, ExternalLogInComponent, OrcidConfirmationComponent, BrowserAnimationsModule],
|
||||
providers: [
|
||||
{ provide: TranslateService, useValue: translateServiceStub },
|
||||
{ provide: AuthService, useValue: new AuthServiceMock() },
|
||||
{ provide: NgbModal, useValue: modalService },
|
||||
FormBuilder
|
||||
]
|
||||
}).compileComponents()
|
||||
FormBuilder,
|
||||
],
|
||||
})
|
||||
.overrideComponent(ExternalLogInComponent, {
|
||||
remove: {
|
||||
imports: [ConfirmEmailComponent],
|
||||
},
|
||||
})
|
||||
.compileComponents(),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -1,19 +1,54 @@
|
||||
import { ChangeDetectionStrategy, Component, Injector, Input, OnDestroy, OnInit, } from '@angular/core';
|
||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
NgComponentOutlet,
|
||||
NgIf,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Injector,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
NgbModal,
|
||||
NgbModalRef,
|
||||
} from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { hasValue, isEmpty } from '../../shared/empty.util';
|
||||
import { getExternalLoginConfirmationType } from '../decorators/external-log-in.methods-decorator';
|
||||
import { AlertComponent } from '../../shared/alert/alert.component';
|
||||
import { AlertType } from '../../shared/alert/alert-type';
|
||||
import {
|
||||
hasValue,
|
||||
isEmpty,
|
||||
} from '../../shared/empty.util';
|
||||
import { ThemedLogInComponent } from '../../shared/log-in/themed-log-in.component';
|
||||
import { getExternalLoginConfirmationType } from '../decorators/external-log-in.methods-decorator';
|
||||
import { ConfirmEmailComponent } from '../email-confirmation/confirm-email/confirm-email.component';
|
||||
import { ProvideEmailComponent } from '../email-confirmation/provide-email/provide-email.component';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-external-log-in',
|
||||
templateUrl: './external-log-in.component.html',
|
||||
styleUrls: ['./external-log-in.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
ProvideEmailComponent,
|
||||
AlertComponent,
|
||||
TranslateModule,
|
||||
ConfirmEmailComponent,
|
||||
ThemedLogInComponent,
|
||||
NgIf,
|
||||
NgComponentOutlet,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
export class ExternalLogInComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
@@ -108,7 +143,7 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
|
||||
const authMethodUppercase = authMethod.toUpperCase();
|
||||
return this.translate.instant(
|
||||
'external-login.haveEmail.informationText',
|
||||
{ authMethod: authMethodUppercase }
|
||||
{ authMethod: authMethodUppercase },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,35 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ConfirmEmailComponent } from './email-confirmation/confirm-email/confirm-email.component';
|
||||
import { ConfirmationSentComponent } from './email-confirmation/confirmation-sent/confirmation-sent.component';
|
||||
import { ProvideEmailComponent } from './email-confirmation/provide-email/provide-email.component';
|
||||
import { ExternalLogInComponent } from './external-log-in/external-log-in.component';
|
||||
import { OrcidConfirmationComponent } from './registration-types/orcid-confirmation/orcid-confirmation.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
const COMPONENTS = [
|
||||
ExternalLogInComponent,
|
||||
ProvideEmailComponent,
|
||||
ConfirmEmailComponent,
|
||||
ConfirmationSentComponent,
|
||||
];
|
||||
|
||||
const ENTRY_COMPONENTS = [OrcidConfirmationComponent];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...COMPONENTS, ...ENTRY_COMPONENTS],
|
||||
imports: [CommonModule, SharedModule],
|
||||
exports: [...COMPONENTS, ...ENTRY_COMPONENTS],
|
||||
})
|
||||
export class ExternalLoginModule {
|
||||
/**
|
||||
* NOTE: this method allows to resolve issue with components that using a custom decorator
|
||||
* which are not loaded during SSR otherwise
|
||||
*/
|
||||
static withEntryComponents() {
|
||||
return {
|
||||
ngModule: ExternalLoginModule,
|
||||
providers: ENTRY_COMPONENTS.map((component) => ({ provide: component })),
|
||||
};
|
||||
}
|
||||
}
|
53
src/app/external-log-in/guards/registration-token-guard.ts
Normal file
53
src/app/external-log-in/guards/registration-token-guard.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { inject } from '@angular/core';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
CanActivateFn,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import {
|
||||
map,
|
||||
Observable,
|
||||
of,
|
||||
} from 'rxjs';
|
||||
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
|
||||
/**
|
||||
* Determines if a user can activate a route based on the registration token.
|
||||
* @param route - The activated route snapshot.
|
||||
* @param state - The router state snapshot.
|
||||
* @param epersonRegistrationService - The eperson registration service.
|
||||
* @param router - The router.
|
||||
* @returns A value indicating if the user can activate the route.
|
||||
*/
|
||||
export const registrationTokenGuard: CanActivateFn = (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot,
|
||||
): Observable<boolean> => {
|
||||
const epersonRegistrationService = inject(EpersonRegistrationService);
|
||||
const router = inject(Router);
|
||||
if (route.params.token) {
|
||||
return epersonRegistrationService
|
||||
.searchByTokenAndHandleError(route.params.token)
|
||||
.pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
map(
|
||||
(data: RemoteData<Registration>) => {
|
||||
if (data.hasSucceeded && hasValue(data)) {
|
||||
return true;
|
||||
} else {
|
||||
router.navigate(['/404']);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
router.navigate(['/404']);
|
||||
return of(false);
|
||||
}
|
||||
};
|
@@ -1,79 +1,101 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { RegistrationTokenGuard } from './registration-token.guard';
|
||||
import { ActivatedRoute, convertToParamMap, Params, Router } from '@angular/router';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import {
|
||||
fakeAsync,
|
||||
TestBed,
|
||||
tick,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
ActivatedRoute,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import {
|
||||
Observable,
|
||||
of as observableOf,
|
||||
} from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { registrationTokenGuard } from './registration-token-guard';
|
||||
|
||||
describe('RegistrationTokenGuard', () => {
|
||||
let guard: RegistrationTokenGuard;
|
||||
const route = new RouterMock();
|
||||
const registrationWithGroups = Object.assign(new Registration(),
|
||||
{
|
||||
email: 'test@email.org',
|
||||
token: 'test-token',
|
||||
describe('RegistrationTokenGuard',
|
||||
() => {
|
||||
const route = new RouterMock();
|
||||
const registrationWithGroups = Object.assign(new Registration(),
|
||||
{
|
||||
email: 'test@email.org',
|
||||
token: 'test-token',
|
||||
});
|
||||
const epersonRegistrationService = jasmine.createSpyObj('epersonRegistrationService', {
|
||||
searchByTokenAndHandleError: createSuccessfulRemoteDataObject$(registrationWithGroups),
|
||||
});
|
||||
const epersonRegistrationService = jasmine.createSpyObj('epersonRegistrationService', {
|
||||
searchByTokenAndHandleError: createSuccessfulRemoteDataObject$(registrationWithGroups)
|
||||
});
|
||||
const authService = {
|
||||
getAuthenticatedUserFromStore: () => observableOf(ePerson),
|
||||
setRedirectUrl: () => {
|
||||
return true;
|
||||
}
|
||||
} as any;
|
||||
const ePerson = Object.assign(new EPerson(), {
|
||||
id: 'test-eperson',
|
||||
uuid: 'test-eperson'
|
||||
});
|
||||
beforeEach(() => {
|
||||
const paramObject: Params = {};
|
||||
paramObject.token = '1234';
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{provide: Router, useValue: route},
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
queryParamMap: observableOf(convertToParamMap(paramObject))
|
||||
},
|
||||
const authService = {
|
||||
getAuthenticatedUserFromStore: () => observableOf(ePerson),
|
||||
setRedirectUrl: () => {
|
||||
return true;
|
||||
},
|
||||
} as any;
|
||||
const ePerson = Object.assign(new EPerson(), {
|
||||
id: 'test-eperson',
|
||||
uuid: 'test-eperson',
|
||||
});
|
||||
|
||||
let arouteStub = {
|
||||
snapshot: {
|
||||
params: {
|
||||
token: '123456789',
|
||||
},
|
||||
{provide: EpersonRegistrationService, useValue: epersonRegistrationService},
|
||||
{provide: AuthService, useValue: authService}
|
||||
]
|
||||
});
|
||||
guard = TestBed.get(RegistrationTokenGuard);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
it('should be created', () => {
|
||||
expect(guard).toBeTruthy();
|
||||
});
|
||||
describe('based on the response of "searchByToken have', () => {
|
||||
it('can activate must return true when registration data includes groups', () => {
|
||||
(guard.canActivate({ params: { token: '123456789' } } as any, {} as any) as any)
|
||||
.subscribe(
|
||||
(canActivate) => {
|
||||
expect(canActivate).toEqual(true);
|
||||
}
|
||||
);
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{ provide: Router, useValue: route },
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: arouteStub,
|
||||
},
|
||||
{ provide: EpersonRegistrationService, useValue: epersonRegistrationService },
|
||||
{ provide: AuthService, useValue: authService },
|
||||
],
|
||||
});
|
||||
});
|
||||
it('can activate must return false when registration data includes groups', () => {
|
||||
const registrationWithDifferentUsedFromLoggedInt = Object.assign(new Registration(),
|
||||
{
|
||||
|
||||
describe('when token provided', () => {
|
||||
it('can activate must return true when registration data includes groups', fakeAsync(() => {
|
||||
const activatedRoute = TestBed.inject(ActivatedRoute);
|
||||
|
||||
const result$ = TestBed.runInInjectionContext(() => {
|
||||
return registrationTokenGuard(activatedRoute.snapshot, {} as RouterStateSnapshot) as Observable<boolean>;
|
||||
});
|
||||
|
||||
let output = null;
|
||||
result$.subscribe((result) => (output = result));
|
||||
tick(100);
|
||||
expect(output).toBeTrue();
|
||||
}));
|
||||
});
|
||||
|
||||
describe('when no token provided', () => {
|
||||
it('can activate must return false when registration data includes groups', fakeAsync(() => {
|
||||
const registrationWithDifferentUserFromLoggedIn = Object.assign(new Registration(), {
|
||||
email: 't1@email.org',
|
||||
token: 'test-token',
|
||||
});
|
||||
epersonRegistrationService.searchByTokenAndHandleError.and.returnValue(observableOf(registrationWithDifferentUsedFromLoggedInt));
|
||||
(guard.canActivate({ params: { token: '123456789' } } as any, {} as any) as any)
|
||||
.subscribe(
|
||||
(canActivate) => {
|
||||
expect(canActivate).toEqual(false);
|
||||
}
|
||||
);
|
||||
});
|
||||
epersonRegistrationService.searchByTokenAndHandleError.and.returnValue(observableOf(registrationWithDifferentUserFromLoggedIn));
|
||||
let activatedRoute = TestBed.inject(ActivatedRoute);
|
||||
activatedRoute.snapshot.params.token = null;
|
||||
|
||||
const result$ = TestBed.runInInjectionContext(() => {
|
||||
return registrationTokenGuard(activatedRoute.snapshot, {} as RouterStateSnapshot) as Observable<boolean>;
|
||||
});
|
||||
|
||||
let output = null;
|
||||
result$.subscribe((result) => (output = result));
|
||||
expect(output).toBeFalse();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,49 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, } from '@angular/router';
|
||||
import { map, Observable, of } from 'rxjs';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class RegistrationTokenGuard implements CanActivate {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private epersonRegistrationService: EpersonRegistrationService
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Determines if a user can activate a route based on the registration token.
|
||||
* @param route - The activated route snapshot.
|
||||
* @param state - The router state snapshot.
|
||||
* @returns A value indicating if the user can activate the route.
|
||||
*/
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Observable<boolean> {
|
||||
if (route.params.token) {
|
||||
return this.epersonRegistrationService
|
||||
.searchByTokenAndHandleError(route.params.token)
|
||||
.pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
map(
|
||||
(data: RemoteData<Registration>) => {
|
||||
if (data.hasSucceeded && hasValue(data)) {
|
||||
return true;
|
||||
} else {
|
||||
this.router.navigate(['/404']);
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
} else {
|
||||
this.router.navigate(['/404']);
|
||||
return of(false);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import { MetadataValue } from '../../core/shared/metadata.models';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
|
||||
export const mockRegistrationDataModel: Registration = Object.assign(
|
||||
new Registration(),
|
||||
@@ -41,5 +41,5 @@ export const mockRegistrationDataModel: Registration = Object.assign(
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<form class="form-login"
|
||||
[formGroup]="form" novalidate>
|
||||
<label class="font-weight-bold mb-0 text-uppercase">{{ registratioData.registrationType }}</label>
|
||||
<label class="font-weight-bold mb-0 text-uppercase">{{ registrationData.registrationType }}</label>
|
||||
<input [attr.aria-label]="'netId' | translate"
|
||||
autocomplete="off"
|
||||
autofocus
|
||||
@@ -23,7 +23,7 @@
|
||||
formControlName="firstname"
|
||||
type="text"
|
||||
[attr.data-test]="'firstname' | dsBrowserOnly">
|
||||
<ng-container *ngIf="registratioData?.email">
|
||||
<ng-container *ngIf="registrationData?.email">
|
||||
<label class="font-weight-bold mb-0">{{"Email" | translate}}</label>
|
||||
<input [attr.aria-label]="'Email' | translate"
|
||||
autocomplete="off"
|
||||
|
@@ -1,14 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { OrcidConfirmationComponent } from './orcid-confirmation.component';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
FormBuilder,
|
||||
FormGroup,
|
||||
} from '@angular/forms';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
} from '@ngx-translate/core';
|
||||
import { Registration } from 'src/app/core/shared/registration.model';
|
||||
import { mockRegistrationDataModel } from '../../models/registration-data.mock.model';
|
||||
import { BrowserOnlyMockPipe } from '../../../shared/testing/browser-only-mock.pipe';
|
||||
|
||||
import { TranslateLoaderMock } from '../../../shared/mocks/translate-loader.mock';
|
||||
import { BrowserOnlyMockPipe } from '../../../shared/testing/browser-only-mock.pipe';
|
||||
import { mockRegistrationDataModel } from '../../models/registration-data.mock.model';
|
||||
import { OrcidConfirmationComponent } from './orcid-confirmation.component';
|
||||
|
||||
describe('OrcidConfirmationComponent', () => {
|
||||
let component: OrcidConfirmationComponent;
|
||||
@@ -17,24 +26,22 @@ describe('OrcidConfirmationComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
OrcidConfirmationComponent,
|
||||
BrowserOnlyMockPipe,
|
||||
],
|
||||
providers: [
|
||||
FormBuilder,
|
||||
{ provide: 'registrationDataProvider', useValue: mockRegistrationDataModel },
|
||||
],
|
||||
imports: [
|
||||
OrcidConfirmationComponent,
|
||||
CommonModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock
|
||||
}
|
||||
useClass: TranslateLoaderMock,
|
||||
},
|
||||
}),
|
||||
BrowserOnlyMockPipe,
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
@@ -59,7 +66,7 @@ describe('OrcidConfirmationComponent', () => {
|
||||
|
||||
|
||||
it('should initialize the form with null email as an empty string', () => {
|
||||
component.registratioData.email = null;
|
||||
component.registrationData.email = null;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
const emailFormControl = component.form.get('email');
|
||||
|
@@ -1,7 +1,20 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { NgIf } from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Inject,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
FormBuilder,
|
||||
FormGroup,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { AuthRegistrationType } from '../../../core/auth/models/auth.registration-type';
|
||||
import { Registration } from '../../../core/shared/registration.model';
|
||||
import { BrowserOnlyPipe } from '../../../shared/utils/browser-only.pipe';
|
||||
import { renderExternalLoginConfirmationFor } from '../../decorators/external-log-in.methods-decorator';
|
||||
import { ExternalLoginMethodEntryComponent } from '../../decorators/external-login-method-entry.component';
|
||||
|
||||
@@ -9,7 +22,14 @@ import { ExternalLoginMethodEntryComponent } from '../../decorators/external-log
|
||||
selector: 'ds-orcid-confirmation',
|
||||
templateUrl: './orcid-confirmation.component.html',
|
||||
styleUrls: ['./orcid-confirmation.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
BrowserOnlyPipe,
|
||||
NgIf,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
@renderExternalLoginConfirmationFor(AuthRegistrationType.Orcid)
|
||||
export class OrcidConfirmationComponent extends ExternalLoginMethodEntryComponent implements OnInit {
|
||||
@@ -25,7 +45,7 @@ export class OrcidConfirmationComponent extends ExternalLoginMethodEntryComponen
|
||||
*/
|
||||
constructor(
|
||||
@Inject('registrationDataProvider') protected injectedRegistrationDataObject: Registration,
|
||||
private formBuilder: FormBuilder
|
||||
private formBuilder: FormBuilder,
|
||||
) {
|
||||
super(injectedRegistrationDataObject);
|
||||
}
|
||||
@@ -35,10 +55,10 @@ export class OrcidConfirmationComponent extends ExternalLoginMethodEntryComponen
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.form = this.formBuilder.group({
|
||||
netId: [{ value: this.registratioData.netId, disabled: true }],
|
||||
netId: [{ value: this.registrationData.netId, disabled: true }],
|
||||
firstname: [{ value: this.getFirstname(), disabled: true }],
|
||||
lastname: [{ value: this.getLastname(), disabled: true }],
|
||||
email: [{ value: this.registratioData?.email || '', disabled: true }], // email can be null
|
||||
email: [{ value: this.registrationData?.email || '', disabled: true }], // email can be null
|
||||
});
|
||||
}
|
||||
|
||||
@@ -47,7 +67,7 @@ export class OrcidConfirmationComponent extends ExternalLoginMethodEntryComponen
|
||||
* @returns the firstname of the user
|
||||
*/
|
||||
private getFirstname(): string {
|
||||
return this.registratioData.registrationMetadata?.['eperson.firstname']?.[0]?.value || '';
|
||||
return this.registrationData.registrationMetadata?.['eperson.firstname']?.[0]?.value || '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,6 +75,6 @@ export class OrcidConfirmationComponent extends ExternalLoginMethodEntryComponen
|
||||
* @returns the lastname of the user
|
||||
*/
|
||||
private getLastname(): string {
|
||||
return this.registratioData.registrationMetadata?.['eperson.lastname']?.[0]?.value || '';
|
||||
return this.registrationData.registrationMetadata?.['eperson.lastname']?.[0]?.value || '';
|
||||
}
|
||||
}
|
||||
|
@@ -1,16 +1,22 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
|
||||
import { RegistrationDataResolver } from './registration-data.resolver';
|
||||
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { createSuccessfulRemoteDataObject, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import {
|
||||
createSuccessfulRemoteDataObject,
|
||||
createSuccessfulRemoteDataObject$,
|
||||
} from '../../shared/remote-data.utils';
|
||||
import { RegistrationDataResolver } from './registration-data.resolver';
|
||||
|
||||
describe('RegistrationDataResolver', () => {
|
||||
let resolver: RegistrationDataResolver;
|
||||
let epersonRegistrationServiceSpy: jasmine.SpyObj<EpersonRegistrationService>;
|
||||
const registrationMock = Object.assign(new Registration(), {
|
||||
email: 'test@user.com',
|
||||
email: 'test@user.com',
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -19,8 +25,8 @@ describe('RegistrationDataResolver', () => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
RegistrationDataResolver,
|
||||
{ provide: EpersonRegistrationService, useValue: spy }
|
||||
]
|
||||
{ provide: EpersonRegistrationService, useValue: spy },
|
||||
],
|
||||
});
|
||||
resolver = TestBed.inject(RegistrationDataResolver);
|
||||
epersonRegistrationServiceSpy = TestBed.inject(EpersonRegistrationService) as jasmine.SpyObj<EpersonRegistrationService>;
|
||||
|
@@ -1,11 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot, } from '@angular/router';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
Resolve,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -30,7 +35,7 @@ export class RegistrationDataResolver implements Resolve<RemoteData<Registration
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<RemoteData<Registration>> {
|
||||
const token = route.params.token;
|
||||
if (hasValue(token)) {
|
||||
return this.epersonRegistrationService.searchByTokenAndHandleError(token).pipe(
|
||||
return this.epersonRegistrationService.searchByTokenAndHandleError(token).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
);
|
||||
}
|
||||
|
@@ -1,18 +1,28 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExternalLoginService } from './external-login.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import {
|
||||
fakeAsync,
|
||||
TestBed,
|
||||
tick,
|
||||
} from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { getTestScheduler } from 'jasmine-marbles';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { NoContent } from '../../core/shared/NoContent.model';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import {
|
||||
createFailedRemoteDataObject,
|
||||
createSuccessfulRemoteDataObject$,
|
||||
} from '../../shared/remote-data.utils';
|
||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||
import { ExternalLoginService } from './external-login.service';
|
||||
|
||||
describe('ExternalLoginService', () => {
|
||||
let service: ExternalLoginService;
|
||||
@@ -20,6 +30,7 @@ describe('ExternalLoginService', () => {
|
||||
let router: any;
|
||||
let notificationService;
|
||||
let translate;
|
||||
let scheduler: TestScheduler;
|
||||
|
||||
const values = ['value1', 'value2'];
|
||||
const field = 'field1';
|
||||
@@ -29,7 +40,7 @@ describe('ExternalLoginService', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
epersonRegistrationService = jasmine.createSpyObj('epersonRegistrationService', {
|
||||
patchUpdateRegistration: createSuccessfulRemoteDataObject$(new Registration)
|
||||
patchUpdateRegistration: createSuccessfulRemoteDataObject$(new Registration),
|
||||
});
|
||||
router = new RouterMock();
|
||||
notificationService = new NotificationsServiceStub();
|
||||
@@ -42,11 +53,12 @@ describe('ExternalLoginService', () => {
|
||||
{ provide: Router, useValue: router },
|
||||
{ provide: NotificationsService, useValue: notificationService },
|
||||
{ provide: TranslateService, useValue: translate },
|
||||
{ provide: Store, useValue: {} },
|
||||
provideMockStore(),
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
});
|
||||
service = TestBed.inject(ExternalLoginService);
|
||||
scheduler = getTestScheduler();
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
@@ -60,19 +72,21 @@ describe('ExternalLoginService', () => {
|
||||
});
|
||||
|
||||
it('should navigate to /email-confirmation if the remote data has succeeded', () => {
|
||||
const remoteData = { hasSucceeded: true } as RemoteData<Registration>;
|
||||
epersonRegistrationService.patchUpdateRegistration.and.returnValue(observableOf(remoteData));
|
||||
service.patchUpdateRegistration(values, field, registrationId, token, operation).subscribe(() => {
|
||||
expect((router as any).navigate).toHaveBeenCalledWith(['/email-confirmation']);
|
||||
});
|
||||
epersonRegistrationService.patchUpdateRegistration.and.returnValue(createSuccessfulRemoteDataObject$(new Registration()));
|
||||
scheduler.schedule(() => service.patchUpdateRegistration(values, field, registrationId, token, operation).subscribe());
|
||||
scheduler.flush();
|
||||
expect((router as any).navigate).toHaveBeenCalledWith(['/email-confirmation']);
|
||||
});
|
||||
|
||||
it('should show an error notification if the remote data has failed', () => {
|
||||
const remoteData = { hasFailed: true } as RemoteData<Registration>;
|
||||
it('should show an error notification if the remote data has failed', fakeAsync(() => {
|
||||
const remoteData = createFailedRemoteDataObject<NoContent>('error message');
|
||||
epersonRegistrationService.patchUpdateRegistration.and.returnValue(observableOf(remoteData));
|
||||
translate.get.and.returnValue(observableOf('error message'));
|
||||
service.patchUpdateRegistration(values, field, registrationId, token, operation).subscribe(() => {
|
||||
expect(notificationService.error).toHaveBeenCalledWith('error message');
|
||||
});
|
||||
});
|
||||
|
||||
let result = null;
|
||||
service.patchUpdateRegistration(values, field, registrationId, token, operation).subscribe((data) => (result = data));
|
||||
tick(100);
|
||||
expect(result).toEqual(remoteData);
|
||||
expect(notificationService.error).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
@@ -1,19 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { filter, map, Observable } from 'rxjs';
|
||||
import {
|
||||
select,
|
||||
Store,
|
||||
} from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import {
|
||||
filter,
|
||||
map,
|
||||
Observable,
|
||||
} from 'rxjs';
|
||||
import { AuthMethod } from 'src/app/core/auth/models/auth.method';
|
||||
import { getAuthenticationMethods } from 'src/app/core/auth/selectors';
|
||||
import { select, Store } from '@ngrx/store';
|
||||
import { CoreState } from 'src/app/core/core-state.model';
|
||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { NoContent } from '../../core/shared/NoContent.model';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ExternalLoginService {
|
||||
|
||||
@@ -46,7 +54,7 @@ export class ExternalLoginService {
|
||||
this.notificationService.error(this.translate.get('external-login-page.provide-email.notifications.error'));
|
||||
}
|
||||
return rd;
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
import { ExternalLoginEmailConfirmationPageComponent } from './external-login-email-confirmation-page.component';
|
||||
|
||||
export const ROUTES: Routes = [
|
||||
|
@@ -1,17 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { ExternalLoginEmailConfirmationPageComponent } from './external-login-email-confirmation-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ExternalLoginEmailConfirmationPageComponent,
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ExternalLoginEmailConfirmationPageRoutingModule {}
|
@@ -1,11 +1,15 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExternalLoginEmailConfirmationPageComponent } from './external-login-email-confirmation-page.component';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
||||
import {
|
||||
ConfirmationSentComponent
|
||||
} from '../external-log-in/email-confirmation/confirmation-sent/confirmation-sent.component';
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
} from '@ngx-translate/core';
|
||||
|
||||
import { ConfirmationSentComponent } from '../external-log-in/email-confirmation/confirmation-sent/confirmation-sent.component';
|
||||
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
||||
import { ExternalLoginEmailConfirmationPageComponent } from './external-login-email-confirmation-page.component';
|
||||
|
||||
describe('ExternalLoginEmailConfirmationPageComponent', () => {
|
||||
let component: ExternalLoginEmailConfirmationPageComponent;
|
||||
@@ -13,19 +17,18 @@ describe('ExternalLoginEmailConfirmationPageComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
imports: [
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock,
|
||||
},
|
||||
}),
|
||||
ExternalLoginEmailConfirmationPageComponent,
|
||||
ConfirmationSentComponent ],
|
||||
imports: [
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderMock,
|
||||
},
|
||||
}),
|
||||
]
|
||||
ConfirmationSentComponent,
|
||||
],
|
||||
})
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -1,8 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { ConfirmationSentComponent } from '../external-log-in/email-confirmation/confirmation-sent/confirmation-sent.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './external-login-email-confirmation-page.component.html',
|
||||
styleUrls: ['./external-login-email-confirmation-page.component.scss']
|
||||
styleUrls: ['./external-login-email-confirmation-page.component.scss'],
|
||||
standalone: true,
|
||||
imports: [ConfirmationSentComponent],
|
||||
})
|
||||
export class ExternalLoginEmailConfirmationPageComponent {
|
||||
}
|
||||
|
@@ -1,21 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
ExternalLoginEmailConfirmationPageRoutingModule
|
||||
} from './external-login-email-confirmation-page-routing.module';
|
||||
import { ExternalLoginEmailConfirmationPageComponent } from './external-login-email-confirmation-page.component';
|
||||
import { ExternalLoginModule } from '../external-log-in/external-login.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ExternalLoginEmailConfirmationPageComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ExternalLoginEmailConfirmationPageRoutingModule,
|
||||
ExternalLoginModule,
|
||||
]
|
||||
})
|
||||
export class ExternalLoginEmailConfirmationPageModule { }
|
@@ -1,22 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { ThemedExternalLoginPageComponent } from './themed-external-login-page.component';
|
||||
import { RegistrationDataResolver } from '../external-log-in/resolvers/registration-data.resolver';
|
||||
import { RegistrationTokenGuard } from '../external-log-in/guards/registration-token.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ThemedExternalLoginPageComponent,
|
||||
canActivate: [RegistrationTokenGuard],
|
||||
resolve: { registrationData: RegistrationDataResolver },
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
providers: [],
|
||||
})
|
||||
export class ExternalLoginPageRoutingModule {}
|
@@ -1,12 +1,19 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ExternalLoginPageComponent } from './external-login-page.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { of } from 'rxjs';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
} from '@ngx-translate/core';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import { ExternalLogInComponent } from '../external-log-in/external-log-in/external-log-in.component';
|
||||
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
|
||||
import { ExternalLoginPageComponent } from './external-login-page.component';
|
||||
|
||||
describe('ExternalLoginPageComponent', () => {
|
||||
let component: ExternalLoginPageComponent;
|
||||
@@ -26,7 +33,6 @@ describe('ExternalLoginPageComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ ExternalLoginPageComponent ],
|
||||
providers: [
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
@@ -42,6 +48,7 @@ describe('ExternalLoginPageComponent', () => {
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ExternalLoginPageComponent,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
@@ -50,7 +57,12 @@ describe('ExternalLoginPageComponent', () => {
|
||||
}),
|
||||
],
|
||||
})
|
||||
.compileComponents();
|
||||
.overrideComponent(ExternalLoginPageComponent, {
|
||||
remove: {
|
||||
imports: [ExternalLogInComponent],
|
||||
},
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -1,14 +1,38 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {
|
||||
AsyncPipe,
|
||||
NgIf,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { hasNoValue } from '../shared/empty.util';
|
||||
import { first, map, Observable, tap } from 'rxjs';
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import {
|
||||
first,
|
||||
map,
|
||||
Observable,
|
||||
tap,
|
||||
} from 'rxjs';
|
||||
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import { ExternalLogInComponent } from '../external-log-in/external-log-in/external-log-in.component';
|
||||
import { AlertComponent } from '../shared/alert/alert.component';
|
||||
import { AlertType } from '../shared/alert/alert-type';
|
||||
import { hasNoValue } from '../shared/empty.util';
|
||||
|
||||
@Component({
|
||||
templateUrl: './external-login-page.component.html',
|
||||
styleUrls: ['./external-login-page.component.scss'],
|
||||
imports: [
|
||||
TranslateModule,
|
||||
AsyncPipe,
|
||||
NgIf,
|
||||
ExternalLogInComponent,
|
||||
AlertComponent,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
export class ExternalLoginPageComponent implements OnInit {
|
||||
/**
|
||||
@@ -31,7 +55,7 @@ export class ExternalLoginPageComponent implements OnInit {
|
||||
public hasErrors = false;
|
||||
|
||||
constructor(
|
||||
private arouter: ActivatedRoute
|
||||
private arouter: ActivatedRoute,
|
||||
) {
|
||||
this.token = this.arouter.snapshot.params.token;
|
||||
this.hasErrors = hasNoValue(this.arouter.snapshot.params.token);
|
||||
@@ -42,7 +66,7 @@ export class ExternalLoginPageComponent implements OnInit {
|
||||
this.arouter.data.pipe(
|
||||
first(),
|
||||
tap((data) => this.hasErrors = (data.registrationData as RemoteData<Registration>).hasFailed),
|
||||
map((data) => (data.registrationData as RemoteData<Registration>).payload)
|
||||
map((data) => (data.registrationData as RemoteData<Registration>).payload),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { ExternalLoginPageRoutingModule } from './external-login-page-routing.module';
|
||||
import { ExternalLoginPageComponent } from './external-login-page.component';
|
||||
import { ThemedExternalLoginPageComponent } from './themed-external-login-page.component';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ExternalLoginModule } from '../external-log-in/external-login.module';
|
||||
|
||||
const COMPONENTS = [
|
||||
ExternalLoginPageComponent,
|
||||
ThemedExternalLoginPageComponent,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
...COMPONENTS
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ExternalLoginPageRoutingModule,
|
||||
SharedModule,
|
||||
ExternalLoginModule
|
||||
]
|
||||
})
|
||||
export class ExternalLoginPageModule { }
|
@@ -1,14 +1,15 @@
|
||||
import { Route } from '@angular/router';
|
||||
import { ThemedExternalLoginPageComponent } from './themed-external-login-page.component';
|
||||
import { RegistrationTokenGuard } from '../external-log-in/guards/registration-token.guard';
|
||||
|
||||
import { registrationTokenGuard } from '../external-log-in/guards/registration-token-guard';
|
||||
import { RegistrationDataResolver } from '../external-log-in/resolvers/registration-data.resolver';
|
||||
import { ThemedExternalLoginPageComponent } from './themed-external-login-page.component';
|
||||
|
||||
export const ROUTES: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ThemedExternalLoginPageComponent,
|
||||
canActivate: [RegistrationTokenGuard],
|
||||
canActivate: [registrationTokenGuard],
|
||||
resolve: { registrationData: RegistrationDataResolver },
|
||||
},
|
||||
];
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { ThemedComponent } from '../shared/theme-support/themed.component';
|
||||
import { ExternalLoginPageComponent } from './external-login-page.component';
|
||||
|
||||
@@ -6,9 +7,11 @@ import { ExternalLoginPageComponent } from './external-login-page.component';
|
||||
* Themed wrapper for ExternalLoginPageComponent
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-themed-external-login-page',
|
||||
selector: 'ds-external-login-page',
|
||||
styleUrls: [],
|
||||
templateUrl: './../shared/theme-support/themed.component.html'
|
||||
templateUrl: './../shared/theme-support/themed.component.html',
|
||||
standalone: true,
|
||||
imports: [ExternalLoginPageComponent],
|
||||
})
|
||||
export class ThemedExternalLoginPageComponent extends ThemedComponent<ExternalLoginPageComponent> {
|
||||
protected getComponentName(): string {
|
||||
|
@@ -1,14 +1,15 @@
|
||||
import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-review-account-info-page.component';
|
||||
import { ReviewAccountGuard } from './helpers/review-account.guard';
|
||||
import { RegistrationDataResolver } from '../external-log-in/resolvers/registration-data.resolver';
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { RegistrationDataResolver } from '../external-log-in/resolvers/registration-data.resolver';
|
||||
import { ReviewAccountGuard } from './helpers/review-account.guard';
|
||||
import { ThemedExternalLoginReviewAccountInfoPageComponent } from './themed-external-login-review-account-info-page.component';
|
||||
|
||||
export const ROUTES: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ExternalLoginReviewAccountInfoPageComponent,
|
||||
component: ThemedExternalLoginReviewAccountInfoPageComponent,
|
||||
canActivate: [ReviewAccountGuard],
|
||||
resolve: { registrationData: RegistrationDataResolver },
|
||||
},
|
||||
]
|
||||
];
|
||||
|
@@ -1,21 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-review-account-info-page.component';
|
||||
import { ReviewAccountGuard } from './helpers/review-account.guard';
|
||||
import { RegistrationDataResolver } from '../external-log-in/resolvers/registration-data.resolver';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ExternalLoginReviewAccountInfoPageComponent,
|
||||
canActivate: [ReviewAccountGuard],
|
||||
resolve: { registrationData: RegistrationDataResolver },
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ExternalLoginReviewAccountInfoRoutingModule {}
|
@@ -1,8 +1,15 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
} from '@angular/core/testing';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { of } from 'rxjs';
|
||||
import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-review-account-info-page.component';
|
||||
|
||||
import { mockRegistrationDataModel } from '../external-log-in/models/registration-data.mock.model';
|
||||
import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-review-account-info-page.component';
|
||||
import { ReviewAccountInfoComponent } from './review-account-info/review-account-info.component';
|
||||
|
||||
describe('ExternalLoginReviewAccountInfoPageComponent', () => {
|
||||
let component: ExternalLoginReviewAccountInfoPageComponent;
|
||||
@@ -11,21 +18,30 @@ describe('ExternalLoginReviewAccountInfoPageComponent', () => {
|
||||
const mockActivatedRoute = {
|
||||
snapshot: {
|
||||
params: {
|
||||
token: '1234567890'
|
||||
}
|
||||
token: '1234567890',
|
||||
},
|
||||
},
|
||||
data: of({
|
||||
registrationData: mockRegistrationDataModel
|
||||
})
|
||||
registrationData: mockRegistrationDataModel,
|
||||
}),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ExternalLoginReviewAccountInfoPageComponent],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: mockActivatedRoute }
|
||||
]
|
||||
{ provide: ActivatedRoute, useValue: mockActivatedRoute },
|
||||
],
|
||||
imports: [
|
||||
ExternalLoginReviewAccountInfoPageComponent,
|
||||
BrowserAnimationsModule,
|
||||
TranslateModule.forRoot({}),
|
||||
],
|
||||
})
|
||||
.overrideComponent(ExternalLoginReviewAccountInfoPageComponent, {
|
||||
remove: {
|
||||
imports: [ReviewAccountInfoComponent],
|
||||
},
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
|
@@ -1,14 +1,36 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { first, map, Observable, tap } from 'rxjs';
|
||||
import {
|
||||
AsyncPipe,
|
||||
NgIf,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { hasNoValue } from '../shared/empty.util';
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import {
|
||||
first,
|
||||
map,
|
||||
Observable,
|
||||
tap,
|
||||
} from 'rxjs';
|
||||
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import { AlertComponent } from '../shared/alert/alert.component';
|
||||
import { AlertType } from '../shared/alert/alert-type';
|
||||
import { hasNoValue } from '../shared/empty.util';
|
||||
import { ReviewAccountInfoComponent } from './review-account-info/review-account-info.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './external-login-review-account-info-page.component.html',
|
||||
styleUrls: ['./external-login-review-account-info-page.component.scss']
|
||||
styleUrls: ['./external-login-review-account-info-page.component.scss'],
|
||||
imports: [
|
||||
ReviewAccountInfoComponent,
|
||||
AsyncPipe,
|
||||
NgIf,
|
||||
AlertComponent,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
export class ExternalLoginReviewAccountInfoPageComponent implements OnInit {
|
||||
/**
|
||||
@@ -31,7 +53,7 @@ export class ExternalLoginReviewAccountInfoPageComponent implements OnInit {
|
||||
public hasErrors = false;
|
||||
|
||||
constructor(
|
||||
private arouter: ActivatedRoute
|
||||
private arouter: ActivatedRoute,
|
||||
) {
|
||||
this.token = this.arouter.snapshot.params.token;
|
||||
this.hasErrors = hasNoValue(this.arouter.snapshot.params.token);
|
||||
|
@@ -1,30 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { ExternalLoginReviewAccountInfoRoutingModule } from './external-login-review-account-info-page-routing.module';
|
||||
import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-review-account-info-page.component';
|
||||
import { CompareValuesPipe } from './helpers/compare-values.pipe';
|
||||
import {
|
||||
ThemedExternalLoginReviewAccountInfoPageComponent
|
||||
} from './themed-external-login-review-account-info-page.component';
|
||||
import { ReviewAccountInfoComponent } from './review-account-info/review-account-info.component';
|
||||
import { UiSwitchModule } from 'ngx-ui-switch';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ExternalLoginModule } from '../external-log-in/external-login.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ExternalLoginReviewAccountInfoPageComponent,
|
||||
CompareValuesPipe,
|
||||
ThemedExternalLoginReviewAccountInfoPageComponent,
|
||||
ReviewAccountInfoComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
ExternalLoginReviewAccountInfoRoutingModule,
|
||||
SharedModule,
|
||||
UiSwitchModule,
|
||||
ExternalLoginModule
|
||||
]
|
||||
})
|
||||
export class ExternalLoginReviewAccountInfoModule { }
|
@@ -1,7 +1,11 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import {
|
||||
Pipe,
|
||||
PipeTransform,
|
||||
} from '@angular/core';
|
||||
|
||||
@Pipe({
|
||||
name: 'dsCompareValues'
|
||||
name: 'dsCompareValues',
|
||||
standalone: true,
|
||||
})
|
||||
export class CompareValuesPipe implements PipeTransform {
|
||||
|
||||
|
@@ -1,78 +1,121 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { ReviewAccountGuard } from './review-account.guard';
|
||||
import { ActivatedRoute, convertToParamMap, Params, Router } from '@angular/router';
|
||||
import { of as observableOf, of } from 'rxjs';
|
||||
import {
|
||||
fakeAsync,
|
||||
TestBed,
|
||||
tick,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
ActivatedRoute,
|
||||
convertToParamMap,
|
||||
Params,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import {
|
||||
Observable,
|
||||
of as observableOf,
|
||||
of,
|
||||
} from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import {
|
||||
createFailedRemoteDataObject$,
|
||||
createSuccessfulRemoteDataObject$,
|
||||
} from '../../shared/remote-data.utils';
|
||||
import { ReviewAccountGuard } from './review-account.guard';
|
||||
|
||||
describe('ReviewAccountGuard', () => {
|
||||
let guard: ReviewAccountGuard;
|
||||
let epersonRegistrationService: any;
|
||||
let authService: any;
|
||||
let router: any;
|
||||
|
||||
const route = new RouterMock();
|
||||
const registrationMock = Object.assign(new Registration(),
|
||||
{
|
||||
email: 'test@email.org',
|
||||
registrationType: AuthRegistrationType.Validation
|
||||
|
||||
});
|
||||
const registrationMock = Object.assign(new Registration(), {
|
||||
email: 'test@email.org',
|
||||
registrationType: AuthRegistrationType.Validation,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
const paramObject: Params = {};
|
||||
paramObject.token = '1234';
|
||||
const paramObject: Params = { token: '1234' };
|
||||
epersonRegistrationService = jasmine.createSpyObj('epersonRegistrationService', {
|
||||
searchByTokenAndHandleError: createSuccessfulRemoteDataObject$(registrationMock)
|
||||
searchByTokenAndHandleError: createSuccessfulRemoteDataObject$(registrationMock),
|
||||
});
|
||||
authService = {
|
||||
isAuthenticated: () => observableOf(true)
|
||||
isAuthenticated: () => observableOf(true),
|
||||
} as any;
|
||||
router = new RouterMock();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{ provide: Router, useValue: route },
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
queryParamMap: observableOf(convertToParamMap(paramObject))
|
||||
providers: [
|
||||
{ provide: Router, useValue: router },
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
queryParamMap: observableOf(convertToParamMap(paramObject)),
|
||||
snapshot: {
|
||||
params: {
|
||||
token: '1234',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{ provide: EpersonRegistrationService, useValue: epersonRegistrationService },
|
||||
{ provide: AuthService, useValue: authService }
|
||||
]
|
||||
{ provide: EpersonRegistrationService, useValue: epersonRegistrationService },
|
||||
{ provide: AuthService, useValue: authService },
|
||||
],
|
||||
});
|
||||
guard = TestBed.inject(ReviewAccountGuard);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(guard).toBeTruthy();
|
||||
});
|
||||
|
||||
it('can activate must return true when registration type is validation', () => {
|
||||
(guard.canActivate({ params: { token: 'valid token' } } as any, {} as any) as any)
|
||||
.subscribe(
|
||||
(canActivate) => {
|
||||
expect(canActivate).toEqual(true);
|
||||
}
|
||||
);
|
||||
});
|
||||
it('should return true when registration type is validation', fakeAsync(() => {
|
||||
const state = {} as RouterStateSnapshot;
|
||||
const activatedRoute = TestBed.inject(ActivatedRoute);
|
||||
|
||||
it('should navigate to 404 if the registration search fails', () => {
|
||||
const result$ = TestBed.runInInjectionContext(()=> {
|
||||
return ReviewAccountGuard(activatedRoute.snapshot, state) as Observable<boolean>;
|
||||
});
|
||||
|
||||
let output = null;
|
||||
result$.subscribe((result) => (output = result));
|
||||
tick(100);
|
||||
expect(output).toBeTrue();
|
||||
}));
|
||||
|
||||
|
||||
it('should navigate to 404 if the registration search fails', fakeAsync(() => {
|
||||
const state = {} as RouterStateSnapshot;
|
||||
const activatedRoute = TestBed.inject(ActivatedRoute);
|
||||
epersonRegistrationService.searchByTokenAndHandleError.and.returnValue(createFailedRemoteDataObject$());
|
||||
(guard.canActivate({ params: { token: 'invalid-token' } } as any, {} as any) as any).subscribe((result) => {
|
||||
expect(result).toBeFalse();
|
||||
expect(route.navigate).toHaveBeenCalledWith(['/404']);
|
||||
});
|
||||
});
|
||||
|
||||
it('should navigate to 404 if the registration type is not validation and the user is not authenticated', () => {
|
||||
const result$ = TestBed.runInInjectionContext(() => {
|
||||
return ReviewAccountGuard(activatedRoute.snapshot, state) as Observable<boolean>;
|
||||
});
|
||||
|
||||
let output = null;
|
||||
result$.subscribe((result) => (output = result));
|
||||
tick(100);
|
||||
expect(output).toBeFalse();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/404']);
|
||||
}));
|
||||
|
||||
|
||||
|
||||
it('should navigate to 404 if the registration type is not validation and the user is not authenticated', fakeAsync(() => {
|
||||
registrationMock.registrationType = AuthRegistrationType.Orcid;
|
||||
epersonRegistrationService.searchByTokenAndHandleError.and.returnValue(createSuccessfulRemoteDataObject$(registrationMock));
|
||||
spyOn(authService, 'isAuthenticated').and.returnValue(of(false));
|
||||
(guard.canActivate({ params: { token: 'invalid-token' } } as any, {} as any) as any).subscribe((result) => {
|
||||
expect(route.navigate).toHaveBeenCalledWith(['/404']);
|
||||
const activatedRoute = TestBed.inject(ActivatedRoute);
|
||||
|
||||
const result$ = TestBed.runInInjectionContext(() => {
|
||||
return ReviewAccountGuard(activatedRoute.snapshot, {} as RouterStateSnapshot) as Observable<boolean>;
|
||||
});
|
||||
});
|
||||
|
||||
let output = null;
|
||||
result$.subscribe((result) => (output = result));
|
||||
tick(100);
|
||||
expect(output).toBeFalse();
|
||||
expect(router.navigate).toHaveBeenCalledWith(['/404']);
|
||||
}));
|
||||
});
|
||||
|
||||
|
@@ -1,6 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, } from '@angular/router';
|
||||
import { catchError, mergeMap, Observable, of, tap } from 'rxjs';
|
||||
import { inject } from '@angular/core';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
CanActivateFn,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import {
|
||||
catchError,
|
||||
mergeMap,
|
||||
Observable,
|
||||
of,
|
||||
tap,
|
||||
} from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
|
||||
import { EpersonRegistrationService } from '../../core/data/eperson-registration.service';
|
||||
@@ -9,57 +21,49 @@ import { getFirstCompletedRemoteData } from '../../core/shared/operators';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ReviewAccountGuard implements CanActivate {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private epersonRegistrationService: EpersonRegistrationService,
|
||||
private authService: AuthService
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Determines if a user can activate a route based on the registration token.
|
||||
* @param route - The activated route snapshot.
|
||||
* @param state - The router state snapshot.
|
||||
* @returns A value indicating if the user can activate the route.
|
||||
*/
|
||||
canActivate(
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot
|
||||
): Promise<boolean> | boolean | Observable<boolean> {
|
||||
if (route.params.token) {
|
||||
return this.epersonRegistrationService
|
||||
.searchByTokenAndHandleError(route.params.token)
|
||||
.pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
mergeMap(
|
||||
(data: RemoteData<Registration>) => {
|
||||
if (data.hasSucceeded && hasValue(data.payload)) {
|
||||
// is the registration type validation (account valid)
|
||||
if (hasValue(data.payload.registrationType) && data.payload.registrationType.includes(AuthRegistrationType.Validation)) {
|
||||
return of(true);
|
||||
} else {
|
||||
return this.authService.isAuthenticated();
|
||||
}
|
||||
/**
|
||||
* Determines if a user can activate a route based on the registration token.z
|
||||
* @param route - The activated route snapshot.
|
||||
* @param state - The router state snapshot.
|
||||
* @returns A value indicating if the user can activate the route.
|
||||
*/
|
||||
export const ReviewAccountGuard: CanActivateFn = (
|
||||
route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot,
|
||||
): Observable<boolean> => {
|
||||
const authService = inject(AuthService);
|
||||
const router = inject(Router);
|
||||
const epersonRegistrationService = inject(EpersonRegistrationService);
|
||||
if (route.params.token) {
|
||||
return epersonRegistrationService
|
||||
.searchByTokenAndHandleError(route.params.token)
|
||||
.pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
mergeMap(
|
||||
(data: RemoteData<Registration>) => {
|
||||
if (data.hasSucceeded && hasValue(data.payload)) {
|
||||
// is the registration type validation (account valid)
|
||||
if (hasValue(data.payload.registrationType) && data.payload.registrationType.includes(AuthRegistrationType.Validation)) {
|
||||
return of(true);
|
||||
} else {
|
||||
return authService.isAuthenticated();
|
||||
}
|
||||
return of(false);
|
||||
}
|
||||
),
|
||||
tap((isValid: boolean) => {
|
||||
if (!isValid) {
|
||||
this.router.navigate(['/404']);
|
||||
}
|
||||
}),
|
||||
catchError(() => {
|
||||
this.router.navigate(['/404']);
|
||||
return of(false);
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.router.navigate(['/404']);
|
||||
return of(false);
|
||||
}
|
||||
},
|
||||
),
|
||||
tap((isValid: boolean) => {
|
||||
if (!isValid) {
|
||||
router.navigate(['/404']);
|
||||
}
|
||||
}),
|
||||
catchError(() => {
|
||||
router.navigate(['/404']);
|
||||
return of(false);
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
router.navigate(['/404']);
|
||||
return of(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -19,7 +19,7 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row text-uppercase">{{ registrationData.registrationType }}</th>
|
||||
<th scope="row" class="text-uppercase">{{ registrationData.registrationType }}</th>
|
||||
<td>{{ registrationData.netId }}</td>
|
||||
<td>
|
||||
<span>
|
||||
|
@@ -1,29 +1,43 @@
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
import { ReviewAccountInfoComponent } from './review-account-info.component';
|
||||
import { TranslateLoader, TranslateModule, TranslateService, } from '@ngx-translate/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock';
|
||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||
import { Observable, of, Subscription } from 'rxjs';
|
||||
import { EventEmitter } from '@angular/core';
|
||||
import {
|
||||
ComponentFixture,
|
||||
fakeAsync,
|
||||
TestBed,
|
||||
tick,
|
||||
} from '@angular/core/testing';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { Router } from '@angular/router';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
TranslateLoader,
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import {
|
||||
Observable,
|
||||
of,
|
||||
Subscription,
|
||||
} from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||
import { HardRedirectService } from '../../core/services/hard-redirect.service';
|
||||
import { NativeWindowService } from '../../core/services/window.service';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { ExternalLoginService } from '../../external-log-in/services/external-login.service';
|
||||
import { AuthServiceMock } from '../../shared/mocks/auth.service.mock';
|
||||
import { NativeWindowMockFactory } from '../../shared/mocks/mock-native-window-ref';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { EPersonMock } from '../../shared/testing/eperson.mock';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterMock } from '../../shared/mocks/router.mock';
|
||||
import { EventEmitter } from '@angular/core';
|
||||
import { CompareValuesPipe } from '../helpers/compare-values.pipe';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthServiceMock } from '../../shared/mocks/auth.service.mock';
|
||||
import { HardRedirectService } from '../../core/services/hard-redirect.service';
|
||||
import { ExternalLoginService } from '../../external-log-in/services/external-login.service';
|
||||
import { NativeWindowService } from '../../core/services/window.service';
|
||||
import { NativeWindowMockFactory } from '../../shared/mocks/mock-native-window-ref';
|
||||
import { ReviewAccountInfoComponent } from './review-account-info.component';
|
||||
|
||||
describe('ReviewAccountInfoComponent', () => {
|
||||
let component: ReviewAccountInfoComponent;
|
||||
@@ -40,11 +54,11 @@ describe('ReviewAccountInfoComponent', () => {
|
||||
get: () => of('test-message'),
|
||||
onLangChange: new EventEmitter(),
|
||||
onTranslationChange: new EventEmitter(),
|
||||
onDefaultLangChange: new EventEmitter()
|
||||
onDefaultLangChange: new EventEmitter(),
|
||||
};
|
||||
const mockEPerson = EPersonMock;
|
||||
const modalStub = {
|
||||
open: () => ({ componentInstance: { response: of(true) }}),
|
||||
open: () => ({ componentInstance: { response: of(true) } }),
|
||||
close: () => null,
|
||||
dismiss: () => null,
|
||||
};
|
||||
@@ -67,7 +81,7 @@ describe('ReviewAccountInfoComponent', () => {
|
||||
},
|
||||
mergeEPersonDataWithToken(
|
||||
token: string,
|
||||
metadata?: string
|
||||
metadata?: string,
|
||||
): Observable<RemoteData<EPerson>> {
|
||||
return createSuccessfulRemoteDataObject$(mockEPerson);
|
||||
},
|
||||
@@ -82,7 +96,6 @@ describe('ReviewAccountInfoComponent', () => {
|
||||
});
|
||||
authService = new AuthServiceMock();
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ReviewAccountInfoComponent, CompareValuesPipe],
|
||||
providers: [
|
||||
{ provide: NativeWindowService, useFactory: NativeWindowMockFactory },
|
||||
{ provide: EPersonDataService, useValue: ePersonDataServiceStub },
|
||||
@@ -99,6 +112,9 @@ describe('ReviewAccountInfoComponent', () => {
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
BrowserAnimationsModule,
|
||||
ReviewAccountInfoComponent,
|
||||
CompareValuesPipe,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
@@ -115,7 +131,7 @@ describe('ReviewAccountInfoComponent', () => {
|
||||
componentAsAny = component;
|
||||
component.registrationData = Object.assign(
|
||||
new Registration(),
|
||||
registrationDataMock
|
||||
registrationDataMock,
|
||||
);
|
||||
component.registrationToken = 'test-token';
|
||||
fixture.detectChanges();
|
||||
@@ -166,7 +182,7 @@ describe('ReviewAccountInfoComponent', () => {
|
||||
it('should merge EPerson data with token when overrideValue is true', fakeAsync(() => {
|
||||
component.dataToCompare[0].overrideValue = true;
|
||||
spyOn(ePersonDataServiceStub, 'mergeEPersonDataWithToken').and.returnValue(
|
||||
of({ hasSucceeded: true })
|
||||
of({ hasSucceeded: true }),
|
||||
);
|
||||
component.mergeEPersonDataWithToken(registrationDataMock.user, registrationDataMock.registrationType);
|
||||
tick();
|
||||
|
@@ -1,21 +1,53 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject, Input, OnDestroy, OnInit, } from '@angular/core';
|
||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||
import { combineLatest, filter, from, map, Observable, Subscription, switchMap, take, tap } from 'rxjs';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import {
|
||||
NgFor,
|
||||
NgIf,
|
||||
TitleCasePipe,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Inject,
|
||||
Input,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import {
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import { UiSwitchModule } from 'ngx-ui-switch';
|
||||
import {
|
||||
combineLatest,
|
||||
filter,
|
||||
from,
|
||||
map,
|
||||
Observable,
|
||||
Subscription,
|
||||
switchMap,
|
||||
take,
|
||||
tap,
|
||||
} from 'rxjs';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { HardRedirectService } from '../../core/services/hard-redirect.service';
|
||||
import { AuthRegistrationType } from '../../core/auth/models/auth.registration-type';
|
||||
import { RemoteData } from '../../core/data/remote-data';
|
||||
import { EPersonDataService } from '../../core/eperson/eperson-data.service';
|
||||
import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||
import { HardRedirectService } from '../../core/services/hard-redirect.service';
|
||||
import {
|
||||
NativeWindowRef,
|
||||
NativeWindowService,
|
||||
} from '../../core/services/window.service';
|
||||
import { Registration } from '../../core/shared/registration.model';
|
||||
import { ExternalLoginService } from '../../external-log-in/services/external-login.service';
|
||||
import { NativeWindowRef, NativeWindowService } from '../../core/services/window.service';
|
||||
import { AlertComponent } from '../../shared/alert/alert.component';
|
||||
import { AlertType } from '../../shared/alert/alert-type';
|
||||
import { ConfirmationModalComponent } from '../../shared/confirmation-modal/confirmation-modal.component';
|
||||
import { hasValue } from '../../shared/empty.util';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { CompareValuesPipe } from '../helpers/compare-values.pipe';
|
||||
|
||||
export interface ReviewAccountInfoData {
|
||||
label: string;
|
||||
@@ -29,7 +61,17 @@ export interface ReviewAccountInfoData {
|
||||
selector: 'ds-review-account-info',
|
||||
templateUrl: './review-account-info.component.html',
|
||||
styleUrls: ['./review-account-info.component.scss'],
|
||||
imports: [
|
||||
CompareValuesPipe,
|
||||
NgFor,
|
||||
NgIf,
|
||||
TitleCasePipe,
|
||||
TranslateModule,
|
||||
AlertComponent,
|
||||
UiSwitchModule,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
})
|
||||
export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
@@ -82,7 +124,7 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
public onOverrideChange(value: boolean, identifier: string) {
|
||||
this.dataToCompare.find(
|
||||
(data) => data.identifier === identifier
|
||||
(data) => data.identifier === identifier,
|
||||
).overrideValue = value;
|
||||
}
|
||||
|
||||
@@ -120,11 +162,11 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
if (confirm) {
|
||||
this.mergeEPersonDataWithToken(userId, this.registrationData.registrationType);
|
||||
}
|
||||
})
|
||||
)
|
||||
)
|
||||
}),
|
||||
),
|
||||
),
|
||||
)
|
||||
.subscribe()
|
||||
.subscribe(),
|
||||
);
|
||||
} else if (this.registrationData.user) {
|
||||
this.subs.push(
|
||||
@@ -135,7 +177,7 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
const registrationType = this.registrationData.registrationType.split(AuthRegistrationType.Validation)[1];
|
||||
this.mergeEPersonDataWithToken(this.registrationData.user, registrationType);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -154,14 +196,14 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
return this.ePersonService.mergeEPersonDataWithToken(
|
||||
userId,
|
||||
this.registrationToken,
|
||||
data.identifier
|
||||
data.identifier,
|
||||
);
|
||||
})
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
override$ = this.ePersonService.mergeEPersonDataWithToken(
|
||||
userId,
|
||||
this.registrationToken
|
||||
this.registrationToken,
|
||||
);
|
||||
}
|
||||
if (this.registrationData.user && this.registrationData.registrationType.includes(AuthRegistrationType.Validation)) {
|
||||
@@ -182,18 +224,18 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
if (response.hasSucceeded) {
|
||||
this.notificationService.success(
|
||||
this.translateService.get(
|
||||
'review-account-info.merge-data.notification.success'
|
||||
)
|
||||
'review-account-info.merge-data.notification.success',
|
||||
),
|
||||
);
|
||||
this.router.navigate(['/profile']);
|
||||
} else if (response.hasFailed) {
|
||||
this.notificationService.error(
|
||||
this.translateService.get(
|
||||
'review-account-info.merge-data.notification.error'
|
||||
)
|
||||
'review-account-info.merge-data.notification.error',
|
||||
),
|
||||
);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -214,26 +256,26 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
if (response.hasSucceeded) {
|
||||
this.notificationService.success(
|
||||
this.translateService.get(
|
||||
'review-account-info.merge-data.notification.success'
|
||||
)
|
||||
'review-account-info.merge-data.notification.success',
|
||||
),
|
||||
);
|
||||
// set Redirect URL to User profile, so the user is redirected to the profile page after logging in
|
||||
this.authService.setRedirectUrl('/profile');
|
||||
const externalServerUrl = this.authService.getExternalServerRedirectUrl(
|
||||
this._window.nativeWindow.origin,
|
||||
redirectRoute,
|
||||
location
|
||||
location,
|
||||
);
|
||||
// redirect to external registration type authentication url
|
||||
this.hardRedirectService.redirect(externalServerUrl);
|
||||
} else if (response.hasFailed) {
|
||||
this.notificationService.error(
|
||||
this.translateService.get(
|
||||
'review-account-info.merge-data.notification.error'
|
||||
)
|
||||
'review-account-info.merge-data.notification.error',
|
||||
),
|
||||
);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -269,7 +311,7 @@ export class ReviewAccountInfoComponent implements OnInit, OnDestroy {
|
||||
overrideValue: false,
|
||||
identifier: key,
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return dataToCompare;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { ThemedComponent } from '../shared/theme-support/themed.component';
|
||||
import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-review-account-info-page.component';
|
||||
|
||||
@@ -6,9 +7,11 @@ import { ExternalLoginReviewAccountInfoPageComponent } from './external-login-re
|
||||
* Themed wrapper for ExternalLoginReviewAccountInfoPageComponent
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ds-themed-external-login-page',
|
||||
selector: 'ds-external-login-page',
|
||||
styleUrls: [],
|
||||
templateUrl: './../shared/theme-support/themed.component.html'
|
||||
templateUrl: './../shared/theme-support/themed.component.html',
|
||||
standalone: true,
|
||||
imports: [ExternalLoginReviewAccountInfoPageComponent],
|
||||
})
|
||||
export class ThemedExternalLoginReviewAccountInfoPageComponent extends ThemedComponent<ExternalLoginReviewAccountInfoPageComponent> {
|
||||
protected getComponentName(): string {
|
||||
|
@@ -14,7 +14,7 @@ describe('registrationResolver', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
epersonRegistrationService = jasmine.createSpyObj('epersonRegistrationService', {
|
||||
searchByTokenAndUpdateData: createSuccessfulRemoteDataObject$(registration)
|
||||
searchByTokenAndUpdateData: createSuccessfulRemoteDataObject$(registration),
|
||||
});
|
||||
resolver = registrationResolver;
|
||||
});
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, ResolveFn, RouterStateSnapshot, } from '@angular/router';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
ResolveFn,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { EpersonRegistrationService } from '../core/data/eperson-registration.service';
|
||||
|
@@ -1,11 +1,18 @@
|
||||
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot, } from '@angular/router';
|
||||
import {
|
||||
ActivatedRouteSnapshot,
|
||||
Router,
|
||||
RouterStateSnapshot,
|
||||
} from '@angular/router';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
|
||||
import { AuthService } from '../core/auth/auth.service';
|
||||
import { EpersonRegistrationService } from '../core/data/eperson-registration.service';
|
||||
import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject, } from '../shared/remote-data.utils';
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import { of as observableOf } from 'rxjs/internal/observable/of';
|
||||
import { RemoteData } from '../core/data/remote-data';
|
||||
import { Registration } from '../core/shared/registration.model';
|
||||
import {
|
||||
createFailedRemoteDataObject$,
|
||||
createSuccessfulRemoteDataObject,
|
||||
} from '../shared/remote-data.utils';
|
||||
import { registrationGuard } from './registration.guard';
|
||||
|
||||
describe('registrationGuard', () => {
|
||||
|
@@ -26,7 +26,7 @@ export const registrationGuard: CanActivateFn = (
|
||||
router: Router = inject(Router),
|
||||
): Observable<boolean> => {
|
||||
const token = route.params.token;
|
||||
return epersonRegistrationService.searchByToken(token).pipe(
|
||||
return epersonRegistrationService.searchByTokenAndUpdateData(token).pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
redirectOn4xx(router, authService),
|
||||
map((rd) => {
|
||||
|
@@ -1,10 +1,25 @@
|
||||
import { AsyncPipe, NgFor, NgIf, } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit, } from '@angular/core';
|
||||
import { select, Store, } from '@ngrx/store';
|
||||
import { Observable, } from 'rxjs';
|
||||
import {
|
||||
AsyncPipe,
|
||||
NgFor,
|
||||
NgIf,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Input,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
select,
|
||||
Store,
|
||||
} from '@ngrx/store';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthMethod } from '../../core/auth/models/auth.method';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import {
|
||||
getAuthenticationError,
|
||||
getAuthenticationMethods,
|
||||
@@ -12,13 +27,10 @@ import {
|
||||
isAuthenticationLoading,
|
||||
} from '../../core/auth/selectors';
|
||||
import { CoreState } from '../../core/core-state.model';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { hasValue } from '../empty.util';
|
||||
import { ThemedLoadingComponent } from '../loading/themed-loading.component';
|
||||
import { LogInContainerComponent } from './container/log-in-container.component';
|
||||
import { rendersAuthMethodType } from './methods/log-in.methods-decorator';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-base-log-in',
|
||||
@@ -78,7 +90,7 @@ export class LogInComponent implements OnInit {
|
||||
.sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position),
|
||||
),
|
||||
// ignore the ip authentication method when it's returned by the backend
|
||||
map((authMethods: AuthMethod[]) => uniqBy(authMethods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType'))
|
||||
map((authMethods: AuthMethod[]) => uniqBy(authMethods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType')),
|
||||
);
|
||||
|
||||
// set loading
|
||||
|
@@ -1,6 +1,13 @@
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync, } from '@angular/core/testing';
|
||||
import { ActivatedRoute, Router, } from '@angular/router';
|
||||
import {
|
||||
ComponentFixture,
|
||||
TestBed,
|
||||
waitForAsync,
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
ActivatedRoute,
|
||||
Router,
|
||||
} from '@angular/router';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { provideMockStore } from '@ngrx/store/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
@@ -1,17 +1,29 @@
|
||||
import { Component, Inject, OnInit, } from '@angular/core';
|
||||
import { select, Store, } from '@ngrx/store';
|
||||
import {
|
||||
Component,
|
||||
Inject,
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
select,
|
||||
Store,
|
||||
} from '@ngrx/store';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
import { AuthMethod } from '../../../../core/auth/models/auth.method';
|
||||
|
||||
import { isAuthenticated, isAuthenticationLoading } from '../../../../core/auth/selectors';
|
||||
import { NativeWindowRef, NativeWindowService } from '../../../../core/services/window.service';
|
||||
import { isEmpty } from '../../../empty.util';
|
||||
import { AuthService } from '../../../../core/auth/auth.service';
|
||||
import { AuthMethod } from '../../../../core/auth/models/auth.method';
|
||||
import {
|
||||
isAuthenticated,
|
||||
isAuthenticationLoading,
|
||||
} from '../../../../core/auth/selectors';
|
||||
import { CoreState } from '../../../../core/core-state.model';
|
||||
import { HardRedirectService } from '../../../../core/services/hard-redirect.service';
|
||||
import {
|
||||
NativeWindowRef,
|
||||
NativeWindowService,
|
||||
} from '../../../../core/services/window.service';
|
||||
import { isEmpty } from '../../../empty.util';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-log-in-external-provider',
|
||||
@@ -91,7 +103,7 @@ export class LogInExternalProviderComponent implements OnInit {
|
||||
const externalServerUrl = this.authService.getExternalServerRedirectUrl(
|
||||
this._window.nativeWindow.origin,
|
||||
redirectRoute,
|
||||
this.location
|
||||
this.location,
|
||||
);
|
||||
// redirect to shibboleth/orcid/(external) authentication url
|
||||
this.hardRedirectService.redirect(externalServerUrl);
|
||||
|
@@ -3,6 +3,7 @@ import {
|
||||
Input,
|
||||
} from '@angular/core';
|
||||
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import { ThemedComponent } from '../theme-support/themed.component';
|
||||
import { LogInComponent } from './log-in.component';
|
||||
|
||||
@@ -20,8 +21,12 @@ export class ThemedLogInComponent extends ThemedComponent<LogInComponent> {
|
||||
|
||||
@Input() isStandalonePage: boolean;
|
||||
|
||||
@Input() excludedAuthMethod: AuthMethodType;
|
||||
|
||||
@Input() showRegisterLink = true;
|
||||
|
||||
protected inAndOutputNames: (keyof LogInComponent & keyof this)[] = [
|
||||
'isStandalonePage',
|
||||
'isStandalonePage', 'excludedAuthMethod', 'showRegisterLink',
|
||||
];
|
||||
|
||||
protected getComponentName(): string {
|
||||
|
@@ -1,5 +1,8 @@
|
||||
/* eslint-disable no-empty, @typescript-eslint/no-empty-function */
|
||||
import { Observable, of as observableOf, } from 'rxjs';
|
||||
import {
|
||||
Observable,
|
||||
of as observableOf,
|
||||
} from 'rxjs';
|
||||
|
||||
export class AuthServiceMock {
|
||||
public checksAuthenticationToken() {
|
||||
|
@@ -1,5 +1,9 @@
|
||||
import { Observable, of as observableOf, } from 'rxjs';
|
||||
import {
|
||||
Observable,
|
||||
of as observableOf,
|
||||
} from 'rxjs';
|
||||
|
||||
import { RetrieveAuthMethodsAction } from '../../core/auth/auth.actions';
|
||||
import { AuthMethod } from '../../core/auth/models/auth.method';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import { AuthStatus } from '../../core/auth/models/auth-status.model';
|
||||
@@ -8,7 +12,6 @@ import { EPerson } from '../../core/eperson/models/eperson.model';
|
||||
import { hasValue } from '../empty.util';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
||||
import { EPersonMock } from './eperson.mock';
|
||||
import { RetrieveAuthMethodsAction } from '../../core/auth/auth.actions';
|
||||
|
||||
export const authMethodsMock: AuthMethod[] = [
|
||||
new AuthMethod(AuthMethodType.Password, 0),
|
||||
|
Reference in New Issue
Block a user