/**
 * -------------------------------------------------------------------------------------------
 * 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 { ResponseType } from '@microsoft/microsoft-graph-client' ; import * as MicrosoftGraph from '@microsoft/microsoft-graph-types' ; import { blobToBase64 } from '../utils/Utils' ; import { schemas } from './cacheStores' ; import { findContactsByEmail , getEmailFromGraphEntity } from './graph.people' ; import { findUsers } from './graph.user' ; import { IDynamicPerson } from './types' ; /**
 * photo object stored in cache
 */ export interface CachePhoto extends CacheItem { /**
     * user tag associated with photo
     */ eTag ? : string ; /**
     * user/contact photo
     */ photo ? : string ; } /**
 * Defines expiration time
 */ export const getPhotoInvalidationTime = ( ) => CacheService . config . photos . invalidationPeriod || CacheService . config . defaultInvalidationPeriod ; /**
 * Whether photo store is enabled
 */ export const getIsPhotosCacheEnabled = ( ) => CacheService . config . photos . isEnabled && CacheService . config . isEnabled ; param { string } resource param { string [ ] } scopes returns { Promise < string > } export async function getPhotoForResource ( graph , resource , scopes ) { try { const response = ( await graph . api ( `${ resource }/photo/$value` ) . responseType ( ResponseType . RAW ) . middlewareOptions ( prepScopes ( ... scopes ) ) . get ( ) ) as Response ; if ( response . status === 404 ) { return { eTag : null , photo : null } ; } else if ( ! response . ok ) { return null ; } const eTag = response . headers . get ( 'eTag' ) ; const blob = await blobToBase64 ( await response . blob ( ) ) ; return { eTag , photo : blob } ; } catch ( e ) { return null ; } } param contactId returns { Promise < string > } memberof export async function getContactPhoto ( graph , contactId ) { let cache ; let photoDetails ; if ( getIsPhotosCacheEnabled ( ) ) { cache = CacheService . getCache < CachePhoto > ( schemas . photos , schemas . photos . stores . contacts ) ; photoDetails = await cache . getValue ( contactId ) ; if ( photoDetails && getPhotoInvalidationTime ( ) > Date . now ( ) - photoDetails . timeCached ) { return photoDetails . photo ; } } photoDetails = await getPhotoForResource ( graph , `me/contacts/${ contactId }` , [ 'contacts.read' ] ) ; if ( getIsPhotosCacheEnabled ( ) && photoDetails ) { cache . putValue ( contactId , photoDetails ) ; } return photoDetails ? photoDetails . photo : null ; } param userId returns { Promise < string > } memberof export async function getUserPhoto ( graph , userId ) { let cache ; let photoDetails ; if ( getIsPhotosCacheEnabled ( ) ) { cache = CacheService . getCache < CachePhoto > ( schemas . photos , schemas . photos . stores . users ) ; photoDetails = await cache . getValue ( userId ) ; if ( photoDetails && getPhotoInvalidationTime ( ) > Date . now ( ) - photoDetails . timeCached ) { return photoDetails . photo ; } else if ( photoDetails ) { try { const response = await graph . api ( `users/${ userId }/photo` ) . get ( ) ; if ( response && ( response [ '@odata.mediaEtag' ] !== photoDetails . eTag || ( response [ '@odata.mediaEtag' ] === null && response . eTag === null ) ) ) { photoDetails = null ; } } catch { return null ; } } } photoDetails = photoDetails || ( await getPhotoForResource ( graph , `users/${ userId }` , [ 'user.readbasic.all' ] ) ) ; if ( getIsPhotosCacheEnabled ( ) && photoDetails ) { cache . putValue ( userId , photoDetails ) ; } return photoDetails ? photoDetails . photo : null ; } returns { Promise < string > } memberof export async function myPhoto ( graph ) { let cache ; let photoDetails ; if ( getIsPhotosCacheEnabled ( ) ) { cache = CacheService . getCache < CachePhoto > ( schemas . photos , schemas . photos . stores . users ) ; photoDetails = await cache . getValue ( 'me' ) ; if ( photoDetails && getPhotoInvalidationTime ( ) > Date . now ( ) - photoDetails . timeCached ) { return photoDetails . photo ; } } try { const response = await graph . api ( 'me/photo' ) . get ( ) ; if ( response && ( response [ '@odata.mediaEtag' ] !== photoDetails . eTag || ( response [ '@odata.mediaEtag' ] === null && response . eTag === null ) ) ) { photoDetails = null ; } } catch { return null ; } photoDetails = photoDetails || ( await getPhotoForResource ( graph , 'me' , [ 'user.read' ] ) ) ; if ( getIsPhotosCacheEnabled ( ) ) { cache . putValue ( 'me' , photoDetails || { } ) ; } return photoDetails ? photoDetails . photo : null ; } export export async function getPersonImage ( graph , person , useContactsApis = true ) { if ( 'personType' in person && ( person as any ) . personType . subclass !== 'OrganizationUser' ) { if ( ( person as any ) . personType . subclass === 'PersonalContact' && useContactsApis ) { const email = getEmailFromGraphEntity ( person ) ; const contact = await findContactsByEmail ( graph , email ) ; if ( contact && contact . length && contact [ 0 ] . id ) { return await getContactPhoto ( graph , contact [ 0 ] . id ) ; } } return null ; } if ( ( person as MicrosoftGraph . Person ) . userPrincipalName || person . id ) { const id = ( person as MicrosoftGraph . Person ) . userPrincipalName || person . id ; return await getUserPhoto ( graph , id ) ; } if ( person . id ) { const image = await getUserPhoto ( graph , person . id ) ; if ( image ) { return image ; } } const email = getEmailFromGraphEntity ( person ) ; if ( email ) { const users = await findUsers ( graph , email , 1 ) ; if ( users && users . length ) { return await getUserPhoto ( graph , users [ 0 ] . id ) ; } if ( useContactsApis ) { const contacts = await findContactsByEmail ( graph , email ) ; if ( contacts && contacts . length ) { return await getContactPhoto ( graph , contacts [ 0 ] . id ) ; } } } return null ; } export async function getGroupImage ( graph , group , useContactsApis = true ) { let photoDetails ; let cache ; let groupId = group . id ; if ( getIsPhotosCacheEnabled ( ) ) { cache = CacheService . getCache < CachePhoto > ( schemas . photos , schemas . photos . stores . groups ) ; photoDetails = await cache . getValue ( groupId ) ; if ( photoDetails && getPhotoInvalidationTime ( ) > Date . now ( ) - photoDetails . timeCached ) { return photoDetails . photo ; } else if ( photoDetails ) { try { const response = await graph . api ( `group/${ groupId }/photo` ) . get ( ) ; if ( response && ( response [ '@odata.mediaEtag' ] !== photoDetails . eTag || ( response [ '@odata.mediaEtag' ] === null && response . eTag === null ) ) ) { photoDetails = null ; } } catch { return null ; } } } photoDetails = photoDetails || ( await getPhotoForResource ( graph , `groups/${ groupId }` , [ 'user.readbasic.all' ] ) ) ; if ( getIsPhotosCacheEnabled ( ) && photoDetails ) { cache . putValue ( groupId , photoDetails ) ; } return photoDetails ? photoDetails . photo : null ; } param userId returns { CachePhoto } memberof export async function getPhotoFromCache ( userId , storeName ) { const cache = CacheService . getCache < CachePhoto > ( schemas . photos , storeName ) ; const item = await cache . getValue ( userId ) ; return item ; } param userId returns { void } memberof export async function storePhotoInCache ( userId , storeName , value ) { const cache = CacheService . getCache < CachePhoto > ( schemas . photos , storeName ) ; cache . putValue ( userId , value ) ; }