import { computed , observable , makeObservable } from 'mobx' ; import { injectable } from '@cloudbeaver/core-di' ; import { NotificationService } from '@cloudbeaver/core-events' ; import { IExecutor , Executor } from '@cloudbeaver/core-executor' ; import { PermissionsResource , PermissionsService , ServerConfigResource } from '@cloudbeaver/core-root' ; import { ScreenService , RouterState } from '@cloudbeaver/core-routing' ; import { LocalStorageSaveService } from '@cloudbeaver/core-settings' ; import { GlobalConstants } from '@cloudbeaver/core-utils' ; import { AdministrationItemService } from '../AdministrationItem/AdministrationItemService' ; import type { IAdministrationItemRoute } from '../AdministrationItem/IAdministrationItemRoute' ; import type { IRouteParams } from '../AdministrationItem/IRouteParams' ; import { EAdminPermission } from '../EAdminPermission' ; const ADMINISTRATION_ITEMS_STATE = 'administration_items_state' ; const ADMINISTRATION_INFO = 'administration_info' ; interface IAdministrationScreenInfo { workspaceId : string ; version : string ; serverVersion : string ; configurationMode : boolean ; } @ injectable ( ) export class AdministrationScreenService { static screenName = 'administration' ; static itemRouteName = 'administration.item' ; static itemSubRouteName = 'administration.item.sub' ; static itemSubParamRouteName = 'administration.item.sub.param' ; static setupName = 'setup' ; static setupItemRouteName = 'setup.item' ; static setupItemSubRouteName = 'setup.item.sub' ; static setupItemSubParamRouteName = 'setup.item.sub.param' ; info : IAdministrationScreenInfo ; itemState : Map < string , any > ; get isAdministrationPageActive ( ) : boolean { return this . isAdministrationRouteActive ( this . screenService . routerService . state . name ) ; } get activeScreen ( ) : IAdministrationItemRoute | null { return this . getScreen ( this . screenService . routerService . state ) ; } get isConfigurationMode ( ) : boolean { return this . serverConfigResource . configurationMode ; } get publicDisabled ( ) : boolean { return this . serverConfigResource . publicDisabled ; } readonly ensurePermissions : IExecutor < void > ; readonly activationEvent : IExecutor < boolean > ; constructor ( private permissionsResource , private permissionsService , private screenService , private administrationItemService , private autoSaveService , private serverConfigResource , private notificationService ) { this . info = { workspaceId : '' , version : GlobalConstants . version || '' , serverVersion : '' , configurationMode : false , } ; this . itemState = new Map ( ) ; this . activationEvent = new Executor ( ) ; this . ensurePermissions = new Executor ( ) ; makeObservable ( this , { info : observable , itemState : observable , activeScreen : computed , } ) ; this . autoSaveService . withAutoSave ( this . itemState , ADMINISTRATION_ITEMS_STATE ) ; this . autoSaveService . withAutoSave ( this . info , ADMINISTRATION_INFO ) ; this . permissionsResource . onDataUpdate . addPostHandler ( ( ) => { this . checkPermissions ( this . screenService . routerService . state ) ; } ) ; } getRouteName ( item ? , sub ? , param ? ) { if ( this . isConfigurationMode ) { if ( item ) { if ( sub ) { if ( param ) { return AdministrationScreenService . setupItemSubParamRouteName ; } return AdministrationScreenService . setupItemSubRouteName ; } return AdministrationScreenService . setupItemRouteName ; } return AdministrationScreenService . setupName ; } else { if ( item ) { if ( sub ) { if ( param ) { return AdministrationScreenService . itemSubParamRouteName ; } return AdministrationScreenService . itemSubRouteName ; } return AdministrationScreenService . itemRouteName ; } return AdministrationScreenService . screenName ; } } getScreen ( state ? ) { if ( ! state || ! this . isAdministrationRouteActive ( state . name ) ) { return null ; } return this . administrationItemService . getAdministrationItemRoute ( state , this . isConfigurationMode ) ; } navigateToRoot ( ) { this . screenService . navigateToScreen ( this . getRouteName ( ) ) ; } navigateTo ( item , params ? ) { if ( ! params ) { this . navigateToItem ( item ) ; } else { this . navigateToItemSub ( item , params . sub , params . param ) ; } } navigateToItem ( itemName ) { const item = this . administrationItemService . getItem ( itemName , this . isConfigurationMode ) ; this . screenService . navigateToScreen ( this . getRouteName ( itemName , item ?. defaultSub , item ?. defaultParam ) , itemName , item ?. defaultSub , item ?. defaultParam ) ; } navigateToItemSub ( item , sub , param ? ) { this . screenService . navigateToScreen ( this . getRouteName ( item , sub , param ) , item , sub , param ) ; } getItemState < T > ( name ) ; getItemState < T > ( name , defaultState , update ? , validate ? ) ; getItemState < T > ( name , defaultState ? , update ? , validate ? ) { if ( ! this . serverConfigResource . isLoaded ( ) ) { throw new Error ( 'Administration screen getItemState can be used only after server configuration loaded' ) ; } this . validateState ( ) ; if ( defaultState ) { if ( ! this . itemState . has ( name ) || update ) { this . itemState . set ( name , defaultState ( ) ) ; } else if ( validate ) { const state = this . itemState . get ( name ) ! ; if ( ! validate ( state ) ) { this . itemState . set ( name , defaultState ( ) ) ; } } } return this . itemState . get ( name ) ; } clearItemsState ( ) { this . itemState . clear ( ) ; } isAdministrationRouteActive ( routeName ) { return this . screenService . isActive ( routeName , AdministrationScreenService . screenName ) || this . screenService . isActive ( routeName , AdministrationScreenService . setupName ) ; } async handleDeactivate ( state , nextState ) { if ( nextState && ! this . isAdministrationRouteActive ( nextState . name ) ) { await this . activationEvent . execute ( false ) ; } const toScreen = this . getScreen ( nextState ) ; const screen = this . getScreen ( state ) ; if ( screen ) { await this . administrationItemService . deActivate ( screen , this . isConfigurationMode , screen . item !== toScreen ?. item , toScreen === null ) ; } if ( this . isConfigurationMode && ! this . screenService . isActive ( nextState . name , AdministrationScreenService . setupName ) ) { this . navigateToRoot ( ) ; } } async handleCanDeActivate ( fromState , toState ) { if ( ! fromState . params ?. item ) { return true ; } const fromScreen = this . getScreen ( toState ) ; const screen = this . getScreen ( fromState ) ; if ( ! screen ) { return true ; } return this . administrationItemService . canDeActivate ( screen , this . isConfigurationMode , screen . item !== fromScreen ?. item ) ; } async handleCanActivate ( toState , fromState ) { if ( ! toState . params ?. item ) { return false ; } const fromScreen = this . getScreen ( fromState ) ; const screen = this . getScreen ( toState ) ; if ( ! screen ) { return false ; } return this . administrationItemService . canActivate ( screen , this . isConfigurationMode , screen . item !== fromScreen ?. item ) ; } async handleActivate ( state , prevState ? ) { if ( ! ( await this . checkPermissions ( state ) ) ) { return ; } await this . activationEvent . execute ( true ) ; const screen = this . getScreen ( state ) ; const fromScreen = this . getScreen ( prevState ) ; if ( screen ) { await this . administrationItemService . activate ( screen , this . isConfigurationMode , screen . item !== fromScreen ?. item , fromScreen === null ) ; } } private validateState ( ) { if ( this . info . workspaceId !== this . serverConfigResource . workspaceId || this . info . configurationMode !== this . isConfigurationMode || this . info . serverVersion !== this . serverConfigResource . serverVersion || this . info . version !== GlobalConstants . version ) { this . clearItemsState ( ) ; this . info . workspaceId = this . serverConfigResource . workspaceId ; this . info . configurationMode = this . isConfigurationMode ; this . info . serverVersion = this . serverConfigResource . serverVersion ; this . info . version = GlobalConstants . version || '' ; } } private async checkPermissions ( state ) { if ( ! this . isAdministrationRouteActive ( state . name ) ) { return false ; } const accessProvided = await this . isAccessProvided ( state ) ; if ( ! accessProvided ) { this . screenService . navigateToRoot ( ) ; this . notificationService . logInfo ( { title : 'root_permission_no_permission' , uuid : 'no_permission' } ) ; return false ; } return true ; } private async isAccessProvided ( state ) { await this . serverConfigResource . load ( ) ; await this . permissionsResource . load ( ) ; if ( this . isConfigurationMode ) { return true ; } if ( this . screenService . isActive ( state . name , AdministrationScreenService . setupName ) ) { return false ; } await this . ensurePermissions . execute ( ) ; const administrator = await this . permissionsService . hasAsync ( EAdminPermission . admin ) ; if ( ! administrator ) { return false ; } return true ; } }