import * as React from 'react' ; import { ISecurityTrimmedControlProps , ISecurityTrimmedControlState , PermissionLevel } from '.' ; import { SPHttpClient } from '@microsoft/sp-http' ; import { SPPermission } from '@microsoft/sp-page-context' ; import * as telemetry from '../../common/telemetry' ; import { Spinner } from 'office-ui-fabric-react/lib/Spinner' ; export class SecurityTrimmedControl extends React . Component < ISecurityTrimmedControlProps , ISecurityTrimmedControlState > { constructor ( props ) { super ( props ) ; this . state = { allowRender : false , loading : true } ; telemetry . track ( 'SecurityTrimmedControl' , { } ) ; } /**
     * componentDidMount lifecycle method
     */ public componentDidMount ( ) { this . checkPermissions ( ) ; } /**
     * componentDidUpdate lifecycle method
     */ public componentDidUpdate ( prevProps , prevState ) { if ( prevProps . level !== this . props . level || prevProps . permissions !== this . props . permissions || prevProps . relativeLibOrListUrl !== this . props . relativeLibOrListUrl || prevProps . remoteSiteUrl !== this . props . remoteSiteUrl || prevProps . folderPath !== this . props . folderPath || prevProps . itemId !== this . props . itemId ) { this . checkPermissions ( ) ; } } /**
     * Check if the user has the permissions to render the element
     */ private checkPermissions ( ) { const { context , level } = this . props ; if ( level === PermissionLevel . currentWeb || level === PermissionLevel . currentList ) { const { permissions } = level === PermissionLevel . currentWeb ? context . pageContext . web : context . pageContext . list ; if ( permissions . hasAllPermissions ( ... this . props . permissions ) ) { this . setState ( { allowRender : true , loading : false } ) ; } else { this . setState ( { allowRender : false , loading : false } ) ; } } else if ( level === PermissionLevel . remoteWeb ) { this . checkRemoteSitePermissions ( ) ; } else if ( level === PermissionLevel . remoteListOrLib ) { this . checkRemoteListOrLibPermissions ( ) ; } else if ( level === PermissionLevel . remoteListItem ) { this . checkRemoteListItem ( ) ; } else if ( level === PermissionLevel . remoteFolder ) { this . checkRemoteFolder ( ) ; } } /**
     * Check the user its permissions on the remote site
     */ private async checkRemoteSitePermissions ( ) { const { context , remoteSiteUrl , permissions } = this . props ; if ( remoteSiteUrl && permissions ) { for ( const permission of permissions ) { const apiUrl = `${ remoteSiteUrl }/_api/web/DoesUserHavePermissions(@v)?@v=${ JSON . stringify ( permission . value ) }` ; const result = await context . spHttpClient . get ( apiUrl , SPHttpClient . configurations . v1 ) . then ( data => data . json ( ) ) ; if ( result ) { if ( result . error ) { this . setState ( { allowRender : false , loading : false } ) ; console . error ( `Error retrieved while checking user's remote site permissions.` ) ; return ; } if ( typeof result . value !== "undefined" && result . value === false ) { this . setState ( { allowRender : false , loading : false } ) ; return ; } } else { this . setState ( { allowRender : false , loading : false } ) ; console . error ( `No result value was retrieved when checking the user's remote site permissions.` ) ; return ; } } this . setState ( { allowRender : true , loading : false } ) ; } } /**
     * Check the user its permissions on the remote list or library
     */ private async checkRemoteListOrLibPermissions ( ) { const { remoteSiteUrl , relativeLibOrListUrl , permissions } = this . props ; if ( remoteSiteUrl && relativeLibOrListUrl && permissions ) { const apiUrl = `${ remoteSiteUrl }/_api/web/GetList(@listUrl)/EffectiveBasePermissions?@listUrl='${ encodeURIComponent ( relativeLibOrListUrl ) }'` ; const hasPermissions = await this . checkRemotePermissions ( apiUrl ) ; this . setState ( { allowRender : hasPermissions , loading : false } ) ; } } /**
     * Check permissions on item level
     */ private async checkRemoteListItem ( ) { const { remoteSiteUrl , relativeLibOrListUrl , permissions , itemId } = this . props ; if ( remoteSiteUrl && relativeLibOrListUrl && permissions && itemId ) { const apiUrl = `${ remoteSiteUrl }/_api/web/GetList(@listUrl)/Items(${ itemId })/EffectiveBasePermissions?@listUrl='${ encodeURIComponent ( relativeLibOrListUrl ) }'` ; const hasPermissions = await this . checkRemotePermissions ( apiUrl ) ; this . setState ( { allowRender : hasPermissions , loading : false } ) ; } } /**
     * Check permissions on folder
     */ private async checkRemoteFolder ( ) { const { remoteSiteUrl , relativeLibOrListUrl , permissions , folderPath } = this . props ; if ( remoteSiteUrl && relativeLibOrListUrl && permissions && folderPath ) { const folderByServerRelativeUrl = `${ encodeURIComponent ( relativeLibOrListUrl ) }/${ encodeURIComponent ( folderPath ) }` ; const apiUrl = `${ remoteSiteUrl }/_api/web/GetFolderByServerRelativeUrl(@folderByServerRelativeUrl)/ListItemAllFields/EffectiveBasePermissions?@folderByServerRelativeUrl='${ folderByServerRelativeUrl }'` ; const hasPermissions = await this . checkRemotePermissions ( apiUrl ) ; this . setState ( { allowRender : hasPermissions , loading : false } ) ; } } param apiUrl private async checkRemotePermissions ( apiUrl ) { const { context , permissions } = this . props ; const data = await context . spHttpClient . get ( apiUrl , SPHttpClient . configurations . v1 ) ; if ( data && data . ok ) { const result = await data . json ( ) ; if ( result . error ) { console . error ( `Error retrieved while checking permissions` ) ; return false ; } if ( typeof result . High !== "undefined" && typeof result . Low !== "undefined" ) { const permission = new SPPermission ( result ) ; const hasPermissions = permission . hasAllPermissions ( ... permissions ) ; return hasPermissions ; } } else { console . error ( `No result value was retrieved when checking the user's permissions.` ) ; return false ; } } /**
     * Default React render method
     */ public render ( ) { const { className } = this . props ; if ( this . state . loading && this . props . showLoadingAnimation ) { return < Spinner />; } if ( this . state . allowRender ) { return < div className = { className ? className : "" } > { this . props . children } < /div>; } else if ( this . props . noPermissionsControl ) { return this . props . noPermissionsControl ; } return null ; } }