Skip to content

Commit fd83809

Browse files
alisaismailatiatarix83
authored andcommitted
Merged in task/ux-plus-2023_02_x/UXP-171 (pull request #17)
Task/ux plus 2023 02 x/UXP-171 Approved-by: Giuseppe Digilio
2 parents 582d95c + 7a2d0f5 commit fd83809

182 files changed

Lines changed: 4467 additions & 923 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

config/config.example.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,12 @@ browseBy:
275275
fiveYearLimit: 30
276276
# The absolute lowest year to display in the dropdown (only used when no lowest date can be found for all items)
277277
defaultLowerLimit: 1900
278+
# Whether to add item badges to BOTH browse and search result lists.
279+
showLabels: true
278280
# If true, thumbnail images for items will be added to BOTH search and browse result lists.
279281
showThumbnails: true
282+
# Whether to add item thumbnail images to BOTH browse and search result lists.
283+
showMetrics: false
280284
# The number of entries in a paginated browse results list.
281285
# Rounded to the nearest size in the list of selectable sizes on the
282286
# settings menu.

server.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ extendEnvironmentWithAppConfig(environment, appConfig);
8383
// Create a DOM window object based on the template
8484
const _window = domino.createWindow(indexHtml);
8585

86+
// The REST server base URL
87+
const REST_BASE_URL = environment.rest.ssrBaseUrl || environment.rest.baseUrl;
88+
8689
// Assign the DOM window and document objects to the global object
8790
(_window as any).screen = {deviceXDPI: 0, logicalXDPI: 0};
8891
(global as any).window = _window;
@@ -185,7 +188,7 @@ export function app() {
185188
* Proxy the sitemaps
186189
*/
187190
router.use('/sitemap**', createProxyMiddleware({
188-
target: `${environment.rest.baseUrl}/sitemaps`,
191+
target: `${REST_BASE_URL}/sitemaps`,
189192
pathRewrite: path => path.replace(environment.ui.nameSpace, '/'),
190193
changeOrigin: true
191194
}));
@@ -194,7 +197,7 @@ export function app() {
194197
* Proxy the linksets
195198
*/
196199
router.use('/signposting**', createProxyMiddleware({
197-
target: `${environment.rest.baseUrl}`,
200+
target: `${REST_BASE_URL}`,
198201
pathRewrite: path => path.replace(environment.ui.nameSpace, '/'),
199202
changeOrigin: true
200203
}));
@@ -645,7 +648,7 @@ function clientHealthCheck(req, res) {
645648
* The callback function to serve health check requests
646649
*/
647650
function healthCheck(req, res) {
648-
const baseUrl = `${environment.rest.baseUrl}${environment.actuators.endpointPath}`;
651+
const baseUrl = `${REST_BASE_URL}${environment.actuators.endpointPath}`;
649652
axios.get(baseUrl)
650653
.then((response) => {
651654
res.status(response.status).send(response.data);

src/app/admin/admin-routing.module.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ import { AdminEditUserAgreementComponent } from './admin-edit-user-agreement/adm
1010
import { NOTIFICATIONS_MODULE_PATH, REGISTRIES_MODULE_PATH } from './admin-routing-paths';
1111
import { EditCmsMetadataComponent } from './edit-cms-metadata/edit-cms-metadata.component';
1212
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
13+
import {
14+
SiteAdministratorGuard
15+
} from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
16+
import {
17+
GenericAdministratorGuard
18+
} from '../core/data/feature-authorization/feature-authorization-guard/generic-administrator-guard';
1319

1420
@NgModule({
1521
imports: [
@@ -18,59 +24,69 @@ import { BatchImportPageComponent } from './admin-import-batch-page/batch-import
1824
path: NOTIFICATIONS_MODULE_PATH,
1925
loadChildren: () => import('./admin-notifications/admin-notifications.module')
2026
.then((m) => m.AdminNotificationsModule),
27+
canActivate: [SiteAdministratorGuard]
2128
},
2229
{
2330
path: REGISTRIES_MODULE_PATH,
2431
loadChildren: () => import('./admin-registries/admin-registries.module')
2532
.then((m) => m.AdminRegistriesModule),
33+
canActivate: [SiteAdministratorGuard]
2634
},
2735
{
2836
path: 'search',
2937
resolve: { breadcrumb: I18nBreadcrumbResolver },
3038
component: AdminSearchPageComponent,
31-
data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' }
39+
data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' },
40+
canActivate: [GenericAdministratorGuard]
3241
},
3342
{
3443
path: 'workflow',
3544
resolve: { breadcrumb: I18nBreadcrumbResolver },
3645
component: AdminWorkflowPageComponent,
37-
data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' }
46+
data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' },
47+
canActivate: [SiteAdministratorGuard]
3848
},
3949
{
4050
path: 'curation-tasks',
4151
resolve: { breadcrumb: I18nBreadcrumbResolver },
4252
component: AdminCurationTasksComponent,
43-
data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' }
53+
data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' },
54+
canActivate: [SiteAdministratorGuard]
4455
},
4556
{
4657
path: 'metadata-import',
4758
resolve: { breadcrumb: I18nBreadcrumbResolver },
4859
component: MetadataImportPageComponent,
49-
data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' }
60+
data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' },
61+
canActivate: [GenericAdministratorGuard]
5062
},
5163
{
5264
path: 'edit-user-agreement',
5365
resolve: { breadcrumb: I18nBreadcrumbResolver },
5466
component: AdminEditUserAgreementComponent,
55-
data: { title: 'admin.edit-user-agreement.title', breadcrumbKey: 'admin.edit-user-agreement' }
67+
data: { title: 'admin.edit-user-agreement.title', breadcrumbKey: 'admin.edit-user-agreement' },
68+
canActivate: [SiteAdministratorGuard]
5669
},
5770
{
5871
path: 'edit-cms-metadata',
5972
resolve: { breadcrumb: I18nBreadcrumbResolver },
6073
component: EditCmsMetadataComponent,
61-
data: { title: 'admin.edit-cms-metadata.title', breadcrumbKey: 'admin.edit-cms-metadata' }
74+
data: { title: 'admin.edit-cms-metadata.title', breadcrumbKey: 'admin.edit-cms-metadata' },
75+
canActivate: [SiteAdministratorGuard]
6276
},
6377
{
6478
path: 'batch-import',
6579
resolve: { breadcrumb: I18nBreadcrumbResolver },
6680
component: BatchImportPageComponent,
67-
data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' }
81+
data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' },
82+
canActivate: [GenericAdministratorGuard]
6883
},
6984
{
7085
path: 'system-wide-alert',
7186
resolve: { breadcrumb: I18nBreadcrumbResolver },
7287
loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule),
73-
data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'}
88+
data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'},
89+
canActivate: [SiteAdministratorGuard]
7490
},
7591
])
7692
],

src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[attr.aria-labelledby]="'sidebarName-' + section.id"
66
[title]="('menu.section.icon.' + section.id) | translate"
77
[routerLink]="itemModel.link"
8+
[queryParams]="itemModel.queryParams"
89
(keyup.space)="navigate($event)"
910
(keyup.enter)="navigate($event)"
1011
href="javascript:void(0);"
@@ -21,3 +22,4 @@
2122
</div>
2223
</a>
2324
</div>
25+

src/app/admin/admin-sidebar/admin-sidebar-section/admin-sidebar-section.component.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ export class AdminSidebarSectionComponent extends MenuSectionComponent implement
4949
navigate(event: any): void {
5050
event.preventDefault();
5151
if (!this.isDisabled) {
52-
this.router.navigate(this.itemModel.link);
52+
const extras = {
53+
queryParams: this.itemModel.queryParams
54+
};
55+
this.router.navigate(this.itemModel.link, extras);
5356
}
5457
}
5558
}

src/app/admin/edit-cms-metadata/edit-cms-metadata.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ export class EditCmsMetadataComponent implements OnInit {
8383
this.notificationsService.error(this.translateService.get('admin.edit-cms-metadata.error'));
8484
}
8585
this.siteService.setStale();
86+
this.siteService.find().subscribe((site) => {
87+
this.site = site;
88+
});
8689
});
8790
}
8891

src/app/app-routing.module.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@ import { NoPreloading, RouterModule } from '@angular/router';
33
import { AuthBlockingGuard } from './core/auth/auth-blocking.guard';
44

55
import { AuthenticatedGuard } from './core/auth/authenticated.guard';
6-
import {
7-
SiteAdministratorGuard
8-
} from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
6+
7+
98
import {
109
ACCESS_CONTROL_MODULE_PATH,
1110
ADMIN_MODULE_PATH,
@@ -44,8 +43,14 @@ import {
4443
import { ServerCheckGuard } from './core/server-check/server-check.guard';
4544
import { MenuResolver } from './menu.resolver';
4645
import { ThemedPageErrorComponent } from './page-error/themed-page-error.component';
46+
import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-check-guard.guard';
4747
import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths';
4848
import { RedirectService } from './redirect/redirect.service';
49+
import {
50+
GenericAdministratorGuard
51+
} from './core/data/feature-authorization/feature-authorization-guard/generic-administrator-guard';
52+
53+
4954

5055
@NgModule({
5156
imports: [
@@ -100,7 +105,10 @@ import { RedirectService } from './redirect/redirect.service';
100105
path: FORGOT_PASSWORD_PATH,
101106
loadChildren: () => import('./forgot-password/forgot-password.module')
102107
.then((m) => m.ForgotPasswordModule),
103-
canActivate: [EndUserAgreementCurrentUserGuard]
108+
canActivate: [
109+
ForgotPasswordCheckGuard,
110+
EndUserAgreementCurrentUserGuard
111+
]
104112
},
105113
{
106114
path: COMMUNITY_MODULE_PATH,
@@ -171,7 +179,7 @@ import { RedirectService } from './redirect/redirect.service';
171179
path: ADMIN_MODULE_PATH,
172180
loadChildren: () => import('./admin/admin.module')
173181
.then((m) => m.AdminModule),
174-
canActivate: [SiteAdministratorGuard, EndUserAgreementCurrentUserGuard]
182+
canActivate: [GenericAdministratorGuard, EndUserAgreementCurrentUserGuard]
175183
},
176184
{
177185
path: 'login',

src/app/app.module.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { RootModule } from './root.module';
3333
import { NuMarkdownModule } from '@ng-util/markdown';
3434
import { FooterModule } from './footer/footer.module';
3535
import { SocialModule } from './social/social.module';
36+
import { DspaceRestInterceptor } from './core/dspace-rest/dspace-rest.interceptor';
3637
import { DirectivesModule } from './directives/directives.module';
3738

3839
export function getConfig() {
@@ -111,6 +112,11 @@ const PROVIDERS = [
111112
useClass: LogInterceptor,
112113
multi: true
113114
},
115+
{
116+
provide: HTTP_INTERCEPTORS,
117+
useClass: DspaceRestInterceptor,
118+
multi: true
119+
},
114120
// register the dynamic matcher used by form. MUST be provided by the app module
115121
...DYNAMIC_MATCHER_PROVIDERS,
116122
];

src/app/core/auth/auth.effects.spec.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ import { AuthStatus } from './models/auth-status.model';
4242
import { EPersonMock } from '../../shared/testing/eperson.mock';
4343
import { AppState, storeModuleConfig } from '../../app.reducer';
4444
import { StoreActionTypes } from '../../store.actions';
45-
import { isAuthenticated, isAuthenticatedLoaded } from './selectors';
45+
import { getAuthenticatedUser, isAuthenticated, isAuthenticatedLoaded } from './selectors';
4646
import { AuthorizationDataService } from '../data/feature-authorization/authorization-data.service';
4747
import { RouterStub } from '../../shared/testing/router.stub';
48+
import { EPerson } from '../eperson/models/eperson.model';
4849

4950

5051
describe('AuthEffects', () => {
@@ -467,6 +468,8 @@ describe('AuthEffects', () => {
467468

468469
describe('when refresh state, token and redirect action', () => {
469470
it('should return a REFRESH_STATE_TOKEN_AND_REDIRECT_SUCCESS action in response to a REFRESH_STATE_TOKEN_AND_REDIRECT action', (done) => {
471+
472+
store.overrideSelector(getAuthenticatedUser, { id: EPersonMock.id } as EPerson);
470473
spyOn((authEffects as any).authService, 'retrieveAuthenticatedUserById').and.returnValue(observableOf(EPersonMock));
471474

472475
actions = hot('--a-', {
@@ -484,7 +487,9 @@ describe('AuthEffects', () => {
484487
});
485488

486489
describe('when refresh state token failed', () => {
487-
it('should return a REFRESH_STATE_TOKEN_AND_REDIRECT_SUCCESS action in response to a REFRESH_STATE_TOKEN_AND_REDIRECT action', (done) => {
490+
it('should return a REFRESH_STATE_TOKEN_AND_REDIRECT_ERROR action in response to a REFRESH_STATE_TOKEN_AND_REDIRECT action', (done) => {
491+
492+
store.overrideSelector(getAuthenticatedUser, { id: 'mock-id'} as EPerson);
488493
spyOn((authEffects as any).authService, 'retrieveAuthenticatedUserById').and.returnValue(observableThrow(''));
489494

490495
actions = hot('--a-', {

src/app/core/auth/auth.effects.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
queueScheduler,
99
timer
1010
} from 'rxjs';
11-
import { catchError, delay, filter, map, observeOn, switchMap, take, tap } from 'rxjs/operators';
11+
import { catchError, delay, filter, map, observeOn, switchMap, take, tap, withLatestFrom } from 'rxjs/operators';
1212
// import @ngrx
1313
import { Actions, createEffect, ofType } from '@ngrx/effects';
1414
import { Action, select, Store } from '@ngrx/store';
@@ -19,7 +19,7 @@ import { EPerson } from '../eperson/models/eperson.model';
1919
import { AuthStatus } from './models/auth-status.model';
2020
import { AuthTokenInfo } from './models/auth-token-info.model';
2121
import { AppState } from '../../app.reducer';
22-
import { isAuthenticated, isAuthenticatedLoaded } from './selectors';
22+
import { getAuthenticatedUser, isAuthenticated, isAuthenticatedLoaded } from './selectors';
2323
import { StoreActionTypes } from '../../store.actions';
2424
import { AuthMethod } from './models/auth.method';
2525
// import actions
@@ -53,7 +53,7 @@ import {
5353
RetrieveTokenAction,
5454
SetUserAsIdleAction
5555
} from './auth.actions';
56-
import { hasValue } from '../../shared/empty.util';
56+
import { hasValue, isNotNull } from '../../shared/empty.util';
5757
import { Router } from '@angular/router';
5858
import { environment } from '../../../environments/environment';
5959
import { RequestActionTypes } from '../data/request.actions';
@@ -187,8 +187,9 @@ export class AuthEffects {
187187
public refreshToken$: Observable<Action> = createEffect(() => this.actions$.pipe(ofType(AuthActionTypes.REFRESH_TOKEN),
188188
switchMap((action: RefreshTokenAction) => {
189189
return this.authService.refreshAuthenticationToken(action.payload).pipe(
190+
take(1),
190191
map((token: AuthTokenInfo) => new RefreshTokenSuccessAction(token)),
191-
catchError((error) => observableOf(new RefreshTokenErrorAction()))
192+
catchError(_ => observableOf(new RefreshTokenErrorAction()))
192193
);
193194
})
194195
));
@@ -259,7 +260,7 @@ export class AuthEffects {
259260
return this.authService.retrieveAuthMethodsFromAuthStatus(action.payload)
260261
.pipe(
261262
map((authMethodModels: AuthMethod[]) => new RetrieveAuthMethodsSuccessAction(authMethodModels)),
262-
catchError((error) => observableOf(new RetrieveAuthMethodsErrorAction()))
263+
catchError(_ => observableOf(new RetrieveAuthMethodsErrorAction()))
263264
);
264265
})
265266
));
@@ -268,21 +269,25 @@ export class AuthEffects {
268269
.pipe(ofType(AuthActionTypes.REFRESH_TOKEN_AND_REDIRECT),
269270
switchMap((action: RefreshTokenAndRedirectAction) => {
270271
return this.authService.refreshAuthenticationToken(action.payload.token)
271-
.pipe(map((token: AuthTokenInfo) => new RefreshTokenAndRedirectSuccessAction(token, action.payload.redirectUrl)),
272-
catchError((error) => observableOf(new RefreshTokenAndRedirectErrorAction()))
272+
.pipe(
273+
take(1),
274+
map((token: AuthTokenInfo) => new RefreshTokenAndRedirectSuccessAction(token, action.payload.redirectUrl)),
275+
catchError(_ => observableOf(new RefreshTokenAndRedirectErrorAction()))
273276
);
274277
}))
275278
);
276279

280+
277281
public refreshStateTokenRedirect$: Observable<Action> = createEffect(() => this.actions$
278282
.pipe(ofType(AuthActionTypes.REFRESH_EPERSON_AND_TOKEN_REDIRECT),
279-
switchMap((action: RefreshEpersonAndTokenRedirectAction) =>
280-
this.authService.getAuthenticatedUserFromStore()
281-
.pipe(
282-
switchMap(user => this.authService.retrieveAuthenticatedUserById(user.id)),
283-
map(user => new RefreshEpersonAndTokenRedirectSuccessAction(user, action.payload.token, action.payload.redirectUrl)),
284-
catchError((error) => observableOf(new RefreshEpersonAndTokenRedirectErrorAction()))
285-
)
283+
map(({ payload }: RefreshEpersonAndTokenRedirectAction) => payload),
284+
withLatestFrom(this.store.pipe(select(getAuthenticatedUser), filter(isNotNull))),
285+
switchMap(([{ token, redirectUrl }, { id }]) =>
286+
this.authService.retrieveAuthenticatedUserById(id).pipe(
287+
take(1),
288+
map(user => new RefreshEpersonAndTokenRedirectSuccessAction(user, token, redirectUrl)),
289+
catchError(_ => observableOf(new RefreshEpersonAndTokenRedirectErrorAction()))
290+
)
286291
)
287292
)
288293
);

0 commit comments

Comments
 (0)