import { runInAction } from 'mobx' ; import { injectable } from '@cloudbeaver/core-di' ; import { ServerConfigResource } from '@cloudbeaver/core-root' ; import { GraphQLService , CachedMapResource , ResourceKey , AdminConnectionGrantInfo , AdminUserInfoFragment , AdminUserInfo , ResourceKeyUtils , GetUsersListQueryVariables , CachedMapAllKey , resourceKeyList } from '@cloudbeaver/core-sdk' ; import { AUTH_PROVIDER_LOCAL_ID } from './AUTH_PROVIDER_LOCAL_ID' ; import { AuthInfoService } from './AuthInfoService' ; import { AuthProviderService } from './AuthProviderService' ; import type { IAuthCredentials } from './IAuthCredentials' ; const NEW_USER_SYMBOL = Symbol ( 'new-user' ) ; export type AdminUser = AdminUserInfoFragment ; type AdminUserNew = AdminUser & { [ NEW_USER_SYMBOL ] : boolean ; } ; type UserResourceIncludes = Omit < GetUsersListQueryVariables , 'userId' > ; interface UserCreateOptions { userId : string ; roles : string [ ] ; credentials : IAuthCredentials ; metaParameters : Record < string , any > ; grantedConnections : string [ ] ; } @ injectable ( ) export class UsersResource extends CachedMapResource < string , AdminUser , UserResourceIncludes > { constructor ( private graphQLService , private serverConfigResource , private authProviderService , private authInfoService ) { super ( ) ; this . serverConfigResource . onDataUpdate . addHandler ( this . refreshAllLazy . bind ( this ) ) ; } isNew ( id ) { if ( ! this . has ( id ) ) { return true ; } return NEW_USER_SYMBOL in this . get ( id ) ! ; } getEmptyUser ( ) { return { userId : '' , grantedRoles : [ ] , grantedConnections : [ ] , configurationParameters : { } , metaParameters : { } , origins : [ { type : AUTH_PROVIDER_LOCAL_ID , displayName : 'Local' , } ] , linkedAuthProviders : [ AUTH_PROVIDER_LOCAL_ID ] , } ; } async loadConnections ( userId ) { const { grantedConnections } = await this . graphQLService . sdk . getUserGrantedConnections ( { userId } ) ; return grantedConnections ; } async setConnections ( userId , connections ) { await this . graphQLService . sdk . setConnections ( { userId , connections } ) ; } async setMetaParameters ( userId , parameters ) { await this . graphQLService . sdk . saveUserMetaParameters ( { userId , parameters } ) ; } async create ( { userId , roles , credentials , metaParameters , grantedConnections , } ) { const { user } = await this . graphQLService . sdk . createUser ( { userId , ... this . getDefaultIncludes ( ) , ... this . getIncludesMap ( userId ) , } ) ; try { await this . updateCredentials ( userId , credentials ) ; for ( const roleId of roles ) { await this . grantRole ( userId , roleId , true ) ; } await this . setConnections ( userId , grantedConnections ) ; await this . setMetaParameters ( userId , metaParameters ) ; const user = await this . refresh ( userId ) as AdminUserNew ; user [ NEW_USER_SYMBOL ] = true ; } catch ( exception ) { this . delete ( userId ) ; throw exception ; } return this . get ( user . userId ) ! ; } async grantRole ( userId , roleId , skipUpdate ? ) { await this . graphQLService . sdk . grantUserRole ( { userId , roleId } ) ; if ( ! skipUpdate ) { await this . refresh ( userId ) ; } } async revokeRole ( userId , roleId , skipUpdate ? ) { await this . graphQLService . sdk . revokeUserRole ( { userId , roleId } ) ; if ( ! skipUpdate ) { await this . refresh ( userId ) ; } } async updateCredentials ( userId , credentials ) { const processedCredentials = await this . authProviderService . processCredentials ( AUTH_PROVIDER_LOCAL_ID , credentials ) ; await this . graphQLService . sdk . setUserCredentials ( { providerId : AUTH_PROVIDER_LOCAL_ID , userId , credentials : processedCredentials . credentials , } ) ; } async updateLocalPassword ( oldPassword , newPassword ) { await this . graphQLService . sdk . authChangeLocalPassword ( { oldPassword : this . authProviderService . hashValue ( oldPassword ) , newPassword : this . authProviderService . hashValue ( newPassword ) , } ) ; } async delete ( key ) { await ResourceKeyUtils . forEachAsync ( key , async ( key ) => { if ( this . isActiveUser ( key ) ) { throw new Error ( 'You can\'t delete current logged user' ) ; } await this . graphQLService . sdk . deleteUser ( { userId : key } ) ; runInAction ( ( ) => { this . data . delete ( key ) ; this . markUpdated ( key ) ; this . onItemDelete . execute ( key ) ; } ) ; } ) ; } async loadAll ( ) { this . resetIncludes ( ) ; await this . load ( CachedMapAllKey ) ; return this . data ; } async refreshAll ( ) { this . resetIncludes ( ) ; await this . refresh ( CachedMapAllKey ) ; return this . data ; } refreshAllLazy ( ) { this . resetIncludes ( ) ; this . markOutdated ( CachedMapAllKey ) ; } isActiveUser ( userId ) { return this . authInfoService . userInfo ?. userId === userId ; } protected async loader ( key , includes ) { const all = ResourceKeyUtils . includes ( key , CachedMapAllKey ) ; key = this . transformParam ( key ) ; const usersList = [ ] ; await ResourceKeyUtils . forEachAsync ( all ? CachedMapAllKey : key , async ( key ) => { const userId = all ? undefined : key ; const { users } = await this . graphQLService . sdk . getUsersList ( { userId , ... this . getDefaultIncludes ( ) , ... this . getIncludesMap ( userId , includes ) , } ) ; usersList . push ( ... users ) ; } ) ; runInAction ( ( ) => { if ( all ) { this . data . clear ( ) ; } this . set ( resourceKeyList ( usersList . map ( user => user . userId ) ) , usersList ) ; } ) ; return this . data ; } private getDefaultIncludes ( ) { return { customIncludeOriginDetails : false , includeMetaParameters : false , } ; } } export function isLocalUser ( user ) { return user . origins . some ( origin => origin . type === AUTH_PROVIDER_LOCAL_ID ) ; }