/**
 * -------------------------------------------------------------------------------------------
 * Copyright (c) Microsoft Corporation.  All Rights Reserved.  Licensed under the MIT License.
 * See License in the project root for license information.
 * -------------------------------------------------------------------------------------------
 */ import { IGraph , prepScopes , CacheItem , CacheService , CacheStore } from '@microsoft/mgt-element' ; import { Group } from '@microsoft/microsoft-graph-types' ; import { schemas } from './cacheStores' ; export enum { number } export enum GroupType { /**
     * Any group Type
     */ any = 0 , /**
     * Office 365 group
     */ unified = 1 << 0 , /**
     * Security group
     */ security = 1 << 1 , /**
     * Mail Enabled Security group
     */ mailenabledsecurity = 1 << 2 , /**
     * Distribution Group
     */ distribution = 1 << 3 } /**
 * Object to be stored in cache
 */ export interface CacheGroup extends CacheItem { /**
     * stringified json representing a user
     */ group ? : string ; } /**
 * Object to be stored in cache representing individual people
 */ interface CacheGroupQuery extends CacheItem { /**
     * json representing a person stored as string
     */ groups ? : string [ ] ; /**
     * top number of results
     */ top ? : number ; } /**
 * Defines the expiration time
 */ const getGroupsInvalidationTime = ( ) : number => CacheService . config . groups . invalidationPeriod || CacheService . config . defaultInvalidationPeriod ; /**
 * Whether the groups store is enabled
 */ const getIsGroupsCacheEnabled = ( ) : boolean => CacheService . config . groups . isEnabled && CacheService . config . isEnabled ; export param { IGraph } graph param { string } query param { number } top param { GroupType } groupTypes returns { Promise < Group [ ] > } export async function findGroups ( graph , query , top = 10 , groupTypes = GroupType . any ) { const scopes = 'Group.Read.All' ; let cache ; const key = query || '*' + groupTypes ; if ( getIsGroupsCacheEnabled ( ) ) { cache = CacheService . getCache ( schemas . groups , schemas . groups . stores . groupsQuery ) ; const cacheGroupQuery = await cache . getValue ( key ) ; if ( cacheGroupQuery && getGroupsInvalidationTime ( ) > Date . now ( ) - cacheGroupQuery . timeCached ) { if ( cacheGroupQuery . top >= top ) { return cacheGroupQuery . groups . map ( x => JSON . parse ( x ) ) . slice ( 0 , top + 1 ) ; } } } let filterQuery = '' ; let responses ; let batchedResult = [ ] ; if ( query !== '' ) { filterQuery = `(startswith(displayName,'${ query }') or startswith(mailNickname,'${ query }') or startswith(mail,'${ query }'))` ; } if ( groupTypes !== GroupType . any ) { const batch = graph . createBatch ( ) ; const filterGroups = [ ] ; if ( GroupType . unified === ( groupTypes & GroupType . unified ) ) { filterGroups . push ( "groupTypes/any(c:c+eq+'Unified')" ) ; } if ( GroupType . security === ( groupTypes & GroupType . security ) ) { filterGroups . push ( '(mailEnabled eq false and securityEnabled eq true)' ) ; } if ( GroupType . mailenabledsecurity === ( groupTypes & GroupType . mailenabledsecurity ) ) { filterGroups . push ( '(mailEnabled eq true and securityEnabled eq true)' ) ; } if ( GroupType . distribution === ( groupTypes & GroupType . distribution ) ) { filterGroups . push ( '(mailEnabled eq true and securityEnabled eq false)' ) ; } if ( query !== '' ) { filterQuery = filterQuery + ' and ' ; } for ( let filter of filterGroups ) { batch . get ( filter , `/groups?$filter=${ filterQuery + filter }` , [ 'Group.Read.All' ] ) ; } try { responses = await batch . executeAll ( ) ; for ( let i = 0 ; i < filterGroups . length ; i ++ ) { if ( responses . get ( filterGroups [ i ] ) . content . value ) { for ( let group of responses . get ( filterGroups [ i ] ) . content . value ) { let repeat = batchedResult . filter ( batchedGroup => batchedGroup . id === group . id ) ; if ( repeat . length === 0 ) { batchedResult . push ( group ) ; } repeat = [ ] ; } } } } catch ( _ ) { try { let queries = [ ] ; for ( let filter of filterGroups ) { queries . push ( await graph . api ( 'groups' ) . filter ( filterQuery + filter ) . top ( top ) . middlewareOptions ( prepScopes ( scopes ) ) . get ( ) ) ; } return Promise . all ( queries ) ; } catch ( _ ) { return [ ] ; } } } else { if ( batchedResult . length === 0 ) { const result = await graph . api ( 'groups' ) . filter ( filterQuery ) . top ( top ) . middlewareOptions ( prepScopes ( scopes ) ) . get ( ) ; if ( getIsGroupsCacheEnabled ( ) && result ) { cache . putValue ( key , { groups : result . value . map ( x => JSON . stringify ( x ) ) , top : top } ) ; } return result ? result . value : null ; } } return batchedResult ; } export param { IGraph } graph param { string } query param { string } groupId param { number } top param { boolean } transitive param { GroupType } groupTypes returns { Promise < Group [ ] > } export async function findGroupsFromGroup ( graph , query , groupId , top = 10 , transitive = false , groupTypes = GroupType . any ) { const scopes = 'Group.Read.All' ; let cache ; const key = `${ groupId }:${ query || '*' }:${ groupTypes }:${ transitive }` ; if ( getIsGroupsCacheEnabled ( ) ) { cache = CacheService . getCache ( schemas . groups , schemas . groups . stores . groupsQuery ) ; const cacheGroupQuery = await cache . getValue ( key ) ; if ( cacheGroupQuery && getGroupsInvalidationTime ( ) > Date . now ( ) - cacheGroupQuery . timeCached ) { if ( cacheGroupQuery . top >= top ) { return cacheGroupQuery . groups . map ( x => JSON . parse ( x ) ) . slice ( 0 , top + 1 ) ; } } } const apiUrl = `groups/${ groupId }/${ transitive ? 'transitiveMembers' : 'members' }/microsoft.graph.group` ; let filterQuery = '' ; if ( query !== '' ) { filterQuery = `(startswith(displayName,'${ query }') or startswith(mailNickname,'${ query }') or startswith(mail,'${ query }'))` ; } if ( groupTypes !== GroupType . any ) { const filterGroups = [ ] ; if ( GroupType . unified === ( groupTypes & GroupType . unified ) ) { filterGroups . push ( "groupTypes/any(c:c+eq+'Unified')" ) ; } if ( GroupType . security === ( groupTypes & GroupType . security ) ) { filterGroups . push ( '(mailEnabled eq false and securityEnabled eq true)' ) ; } if ( GroupType . mailenabledsecurity === ( groupTypes & GroupType . mailenabledsecurity ) ) { filterGroups . push ( '(mailEnabled eq true and securityEnabled eq true)' ) ; } if ( GroupType . distribution === ( groupTypes & GroupType . distribution ) ) { filterGroups . push ( '(mailEnabled eq true and securityEnabled eq false)' ) ; } filterQuery += ( query !== '' ? ' and ' : '' ) + filterGroups . join ( ' or ' ) ; } const result = await graph . api ( apiUrl ) . filter ( filterQuery ) . count ( true ) . top ( top ) . header ( 'ConsistencyLevel' , 'eventual' ) . middlewareOptions ( prepScopes ( scopes ) ) . get ( ) ; if ( getIsGroupsCacheEnabled ( ) && result ) { cache . putValue ( key , { groups : result . value . map ( x => JSON . stringify ( x ) ) , top : top } ) ; } return result ? result . value : null ; } param { string } id returns { ( Promise < User > ) } memberof export async function getGroup ( graph , id , requestedProps ? ) { const scopes = 'Group.Read.All' ; let cache ; if ( getIsGroupsCacheEnabled ( ) ) { cache = CacheService . getCache ( schemas . groups , schemas . groups . stores . groups ) ; const group = await cache . getValue ( id ) ; if ( group && getGroupsInvalidationTime ( ) > Date . now ( ) - group . timeCached ) { const cachedData = group . group ? JSON . parse ( group . group ) : null ; const uniqueProps = requestedProps && cachedData ? requestedProps . filter ( prop => ! Object . keys ( cachedData ) . includes ( prop ) ) : null ; if ( ! uniqueProps || uniqueProps . length <= 1 ) { return cachedData ; } } } let apiString = `/groups/${ id }` ; if ( requestedProps ) { apiString = apiString + '?$select=' + requestedProps . toString ( ) ; } const response = await graph . api ( apiString ) . middlewareOptions ( prepScopes ( scopes ) ) . get ( ) ; if ( getIsGroupsCacheEnabled ( ) ) { cache . putValue ( id , { group : JSON . stringify ( response ) } ) ; } return response ; } export param { IGraph } graph param { string [ ] } groupIds returns { Promise < Group [ ] > } export async function getGroupsForGroupIds ( graph , groupIds ) { if ( ! groupIds || groupIds . length === 0 ) { return [ ] ; } const batch = graph . createBatch ( ) ; const groupDict = { } ; const notInCache = [ ] ; let cache ; if ( getIsGroupsCacheEnabled ( ) ) { cache = CacheService . getCache ( schemas . groups , schemas . groups . stores . groups ) ; } for ( const id of groupIds ) { groupDict [ id ] = null ; let group = null ; if ( getIsGroupsCacheEnabled ( ) ) { group = await cache . getValue ( id ) ; } if ( group && getGroupsInvalidationTime ( ) > Date . now ( ) - group . timeCached ) { groupDict [ id ] = group . group ? JSON . parse ( group . group ) : null ; } else if ( id !== '' ) { batch . get ( id , `/groups/${ id }` , [ 'Group.Read.All' ] ) ; notInCache . push ( id ) ; } } try { const responses = await batch . executeAll ( ) ; for ( const id of groupIds ) { const response = responses . get ( id ) ; if ( response && response . content ) { groupDict [ id ] = response . content ; if ( getIsGroupsCacheEnabled ( ) ) { cache . putValue ( id , { group : JSON . stringify ( response . content ) } ) ; } } } return Promise . all ( Object . values ( groupDict ) ) ; } catch ( _ ) { try { groupIds . filter ( id => notInCache . includes ( id ) ) . forEach ( id => ( groupDict [ id ] = getGroup ( graph , id ) ) ) ; if ( getIsGroupsCacheEnabled ( ) ) { groupIds . filter ( id => notInCache . includes ( id ) ) . forEach ( async ( id ) => cache . putValue ( id , { group : JSON . stringify ( await groupDict [ id ] ) } ) ) ; } return Promise . all ( Object . values ( groupDict ) ) ; } catch ( _ ) { return [ ] ; } } }