Skip to content
Snippets Groups Projects
search-auth.guard.ts 3.97 KiB
/**
 * This file is part of Anis Client.
 *
 * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

import { Store, select } from '@ngrx/store';
import { combineLatest, Observable } from 'rxjs';
import { switchMap, map, skipWhile } from 'rxjs/operators';

import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector';
import * as datasetActions from 'src/app/metamodel/actions/dataset.actions';
import * as datasetGroupSelector from 'src/app/metamodel/selectors/dataset-group.selector';
import * as datasetGroupActions from 'src/app/metamodel/actions/dataset-group.actions';
import * as authSelector from 'src/app/auth/auth.selector';
import { AppConfigService } from 'src/app/app-config.service';
import { isAdmin } from 'src/app/shared/utils';

@Injectable({
    providedIn: 'root',
})
export class SearchAuthGuard implements CanActivate {
    constructor(
        protected readonly router: Router,
        private store: Store<{ }>,
        private config: AppConfigService
    ) { }

    canActivate(): Observable<boolean> {
        return combineLatest([
            this.store.pipe(select(datasetSelector.selectDatasetListIsLoaded)),
            this.store.pipe(select(datasetGroupSelector.selectDatasetGroupListIsLoaded))
        ]).pipe(
            map(([datasetListIsLoaded, datasetGroupListIsLoaded]) => {
                if (!datasetListIsLoaded) {
                    this.store.dispatch(datasetActions.loadDatasetList());
                }
                if (!datasetGroupListIsLoaded) {
                    this.store.dispatch(datasetGroupActions.loadDatasetGroupList());
                }
                return [datasetListIsLoaded, datasetGroupListIsLoaded];
            }),
            skipWhile(([datasetListIsLoaded, datasetGroupListIsLoaded]) => !datasetListIsLoaded || !datasetGroupListIsLoaded),
            switchMap(() => {
                return combineLatest([
                    this.store.pipe(select(datasetSelector.selectDatasetByRouteName)),
                    this.store.pipe(select(authSelector.selectUserRoles)),
                    this.store.pipe(select(authSelector.selectIsAuthenticated)),
                    this.store.pipe(select(datasetGroupSelector.selectAllDatasetGroups))
                ]).pipe(
                    map(([dataset, userRoles, isAuthenticated, datasetGroupList]) => {
                        // No authorization required to continue
                        if (!this.config.authenticationEnabled 
                            || dataset.public
                            || (isAuthenticated && isAdmin(this.config.adminRoles, userRoles))) {
                            return true;
                        }
                        
                        // If user is authenticated and authorized so accessible changes to true
                        let accessible = false
                        if (isAuthenticated) {
                            accessible = datasetGroupList
                                .filter(datasetGroup => datasetGroup.datasets.includes(dataset.name))
                                .filter(datasetGroup => userRoles.includes(datasetGroup.role))
                                .length > 0;
                        }
                        
                        // If user is not authorized to continue go to unauthorized page
                        if (!accessible) {
                            sessionStorage.setItem('redirect_uri', window.location.toString());
                            this.router.navigateByUrl('/unauthorized');
                            return false;
                        }
        
                        // Let "Router" allow user entering the page
                        return true;
                    })
                );
            })
        );
    }
}