1+ import { CommandBarButton , DefaultButton , Dialog , DialogFooter , DialogType , MessageBar , MessageBarType , Stack , Text } from '@fluentui/react' ;
2+ import { useEffect , useState } from 'react' ;
3+ import { IQuickLinkListProps } from './Actions' ;
4+ import { buttonStyles } from './QuickLinkButton' ;
5+
6+ function fetchSitePermissions ( hostname : string , siteId : string , webId : string ) {
7+ const apiUrl = `https://${ hostname } /_api/v2.1/sites/${ hostname } ,${ siteId } ,${ webId } /permissions` ;
8+
9+ return fetch ( apiUrl , {
10+ method : 'GET' ,
11+ headers : {
12+ 'accept' : 'application/json' ,
13+ 'X-ClientService-ClientTag' : 'SPEDITOR'
14+ } ,
15+ credentials : 'include'
16+ } )
17+ . then ( response => {
18+ if ( ! response . ok ) {
19+ throw new Error ( `Failed to fetch permissions: ${ response . status } ${ response . statusText } ` ) ;
20+ }
21+ return response . json ( ) ;
22+ } )
23+ . then ( data => data . value || [ ] )
24+ . catch ( err => {
25+ throw err ;
26+ } ) ;
27+ }
28+
29+ const SitesSelectedPermissions = ( { plo, tabId, ctx } : IQuickLinkListProps ) => {
30+
31+ const modelProps = {
32+ isBlocking : false ,
33+ styles : { main : { maxWidth : 600 } } ,
34+ } ;
35+ const dialogContentProps = {
36+ type : DialogType . largeHeader ,
37+ title : 'Site Selected Permissions' ,
38+ subText : "Applications with permissions to access this site." ,
39+ } ;
40+
41+ const [ hideDialog , setHideDialog ] = useState ( true ) ;
42+ const [ permissions , setPermissions ] = useState < any [ ] > ( [ ] ) ;
43+ const [ loading , setLoading ] = useState ( false ) ;
44+ const [ error , setError ] = useState < string | null > ( null ) ;
45+
46+ useEffect ( ( ) => {
47+ if ( ! hideDialog && ctx ) {
48+ loadPermissions ( ) ;
49+ }
50+ } , [ hideDialog , ctx ] ) ;
51+
52+ const loadPermissions = async ( ) => {
53+ if ( ! ctx ?. siteId || ! ctx ?. webId ) {
54+ setError ( 'Site ID or Web ID not available' ) ;
55+ return ;
56+ }
57+
58+ if ( ! ctx ?. webAbsoluteUrl ) {
59+ setError ( 'Web absolute URL not available' ) ;
60+ return ;
61+ }
62+
63+ setLoading ( true ) ;
64+ setError ( null ) ;
65+
66+ try {
67+ // Extract hostname from context
68+ const hostname = new URL ( ctx . webAbsoluteUrl ) . hostname ;
69+
70+ if ( ! hostname ) {
71+ throw new Error ( 'Failed to extract hostname from URL' ) ;
72+ }
73+
74+ // Execute the fetch in the page context
75+ const results = await chrome . scripting . executeScript ( {
76+ target : { tabId : tabId } ,
77+ world : 'MAIN' ,
78+ args : [ hostname , ctx . siteId , ctx . webId ] ,
79+ func : fetchSitePermissions ,
80+ } ) ;
81+
82+ if ( results && results [ 0 ] && results [ 0 ] . result ) {
83+ setPermissions ( results [ 0 ] . result ) ;
84+ } else {
85+ setPermissions ( [ ] ) ;
86+ }
87+ } catch ( err ) {
88+ setError ( err instanceof Error ? err . message : 'Failed to fetch permissions' ) ;
89+ console . error ( 'Error fetching site permissions:' , err ) ;
90+ } finally {
91+ setLoading ( false ) ;
92+ }
93+ } ;
94+
95+ return ( < >
96+ < CommandBarButton
97+ text = { 'Select Sites Permissions' }
98+ iconProps = { { iconName : 'Permissions' } }
99+ styles = { buttonStyles }
100+ onClick = { ( ) => setHideDialog ( false ) }
101+ />
102+ < Dialog
103+ hidden = { hideDialog }
104+ onDismiss = { ( ) => setHideDialog ( true ) }
105+ dialogContentProps = { dialogContentProps }
106+ modalProps = { modelProps } >
107+
108+ { loading && < MessageBar messageBarType = { MessageBarType . info } > Loading permissions...</ MessageBar > }
109+
110+ { error && < MessageBar messageBarType = { MessageBarType . error } > { error } </ MessageBar > }
111+
112+ { ! loading && ! error && permissions . length === 0 && (
113+ < MessageBar messageBarType = { MessageBarType . warning } > No permissions found</ MessageBar >
114+ ) }
115+
116+ { ! loading && permissions . length > 0 && (
117+ < Stack tokens = { { childrenGap : 12 } } styles = { { root : { marginTop : 16 , maxHeight : '400px' , overflowY : 'auto' } } } >
118+ { permissions . map ( ( permission , index ) => {
119+ const app = permission . grantedToIdentities ?. [ 0 ] ?. application ;
120+ return (
121+ < Stack key = { index } >
122+ < Stack tokens = { { childrenGap : 8 } } >
123+ < Text variant = "medium" styles = { { root : { fontWeight : 600 , color : '#323130' } } } >
124+ { app ?. displayName || 'Unknown Application' }
125+ </ Text >
126+ < Stack tokens = { { childrenGap : 4 } } >
127+ < Text variant = "small" styles = { { root : { color : '#605e5c' , fontWeight : 600 } } } >
128+ Application ID:
129+ </ Text >
130+ < Text variant = "small" styles = { { root : { color : '#323130' , fontFamily : 'monospace' , fontSize : '11px' } } } >
131+ { app ?. id || 'N/A' }
132+ </ Text >
133+ </ Stack >
134+ < Stack tokens = { { childrenGap : 4 } } >
135+ < Text variant = "small" styles = { { root : { color : '#605e5c' , fontWeight : 600 } } } >
136+ Roles:
137+ </ Text >
138+ < Text variant = "small" styles = { { root : { color : '#323130' } } } >
139+ { permission . roles ?. join ( ', ' ) || 'No roles assigned' }
140+ </ Text >
141+ </ Stack >
142+ </ Stack >
143+ { index < permissions . length - 1 && (
144+ < div style = { {
145+ borderBottom : '1px solid #edebe9' ,
146+ marginTop : '12px'
147+ } } />
148+ ) }
149+ </ Stack >
150+ ) ;
151+ } ) }
152+ </ Stack >
153+ ) }
154+
155+ < DialogFooter >
156+ < DefaultButton onClick = { ( ) => setHideDialog ( true ) } text = "Close" />
157+ </ DialogFooter >
158+ </ Dialog >
159+ </ >
160+ )
161+ }
162+
163+ export default SitesSelectedPermissions ;
0 commit comments