Skip to content

Commit cb3eb7c

Browse files
committed
feat: Add pages for Deleted Sites and External Users; update navigation
1 parent 0a5fa50 commit cb3eb7c

4 files changed

Lines changed: 97 additions & 19 deletions

File tree

src/layouts/config.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,11 +696,21 @@ export const nativeMenuItems = [
696696
path: '/teams-share/sharepoint',
697697
permissions: ['Sharepoint.Admin.*'],
698698
},
699+
{
700+
title: 'Deleted Sites',
701+
path: '/teams-share/deleted-sites',
702+
permissions: ['Sharepoint.Admin.*'],
703+
},
699704
{
700705
title: 'Sharing Report',
701706
path: '/teams-share/sharing-report',
702707
permissions: ['Sharepoint.Site.*'],
703708
},
709+
{
710+
title: 'External Users',
711+
path: '/teams-share/external-users',
712+
permissions: ['Sharepoint.Site.*'],
713+
},
704714
{
705715
title: 'Teams',
706716
permissions: ['Teams.Group.*'],

src/pages/teams-share/sharepoint/deleted-sites.js renamed to src/pages/teams-share/deleted-sites.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import { Layout as DashboardLayout } from '../../../layouts/index.js'
2-
import { usePermissions } from '../../../hooks/use-permissions'
3-
import { CippTablePage } from '../../../components/CippComponents/CippTablePage.jsx'
4-
import { Button } from '@mui/material'
5-
import { ArrowBack, RestoreFromTrash } from '@mui/icons-material'
6-
import Link from 'next/link'
1+
import { Layout as DashboardLayout } from '../../layouts/index.js'
2+
import { usePermissions } from '../../hooks/use-permissions'
3+
import { CippTablePage } from '../../components/CippComponents/CippTablePage.jsx'
4+
import { RestoreFromTrash } from '@mui/icons-material'
75

86
const Page = () => {
97
const { checkPermissions } = usePermissions()
@@ -30,7 +28,6 @@ const Page = () => {
3028
title="Deleted SharePoint Sites"
3129
apiUrl="/api/ListDeletedSites"
3230
apiDataKey="Results"
33-
queryKey="ListDeletedSites"
3431
actions={actions}
3532
simpleColumns={[
3633
'Name',
@@ -40,11 +37,6 @@ const Page = () => {
4037
'DaysRemaining',
4138
'StorageMaximumLevel',
4239
]}
43-
cardButton={
44-
<Button component={Link} href="/teams-share/sharepoint" startIcon={<ArrowBack />}>
45-
Back to Sites
46-
</Button>
47-
}
4840
/>
4941
)
5042
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { Layout as DashboardLayout } from '../../layouts/index.js'
2+
import { usePermissions } from '../../hooks/use-permissions'
3+
import { useSettings } from '../../hooks/use-settings'
4+
import { CippTablePage } from '../../components/CippComponents/CippTablePage.jsx'
5+
import { NoAccounts } from '@mui/icons-material'
6+
7+
/*
8+
* Lists SharePoint Online's tenant external users store (live) and classifies every entry:
9+
* - Entra B2B: backed by a live Entra guest object
10+
* - Orphaned B2B: the Entra guest was deleted but SharePoint still knows the user
11+
* - SharePoint-only: legacy email-authenticated guest that never had an Entra object
12+
*/
13+
const Page = () => {
14+
const tenantFilter = useSettings().currentTenant
15+
const { checkPermissions } = usePermissions()
16+
const canWriteSite = checkPermissions(['Sharepoint.Site.ReadWrite'])
17+
18+
const actions = [
19+
{
20+
label: 'Remove Guest Access',
21+
type: 'POST',
22+
icon: <NoAccounts />,
23+
url: '/api/ExecRemoveSPOExternalUser',
24+
customDataformatter: (row) => {
25+
const r = Array.isArray(row) ? row[0] : row
26+
return {
27+
tenantFilter: r.Tenant ?? tenantFilter,
28+
EntraUserId: r.EntraUserId,
29+
LoginName: r.LoginName,
30+
SiteUrls: Array.isArray(r.Sites) ? r.Sites : [],
31+
DisplayName: r.DisplayName,
32+
}
33+
},
34+
confirmText:
35+
'Fully remove guest access for [DisplayName]? This deletes their Entra guest account (if one exists) AND removes them from every site listed in the Sites column, so nothing is left orphaned. Sharing links they hold can be revoked from the Sharing Report; the inert SharePoint store entry ages out on its own.',
36+
color: 'error',
37+
condition: (row) => canWriteSite && (row.InEntra || (row.Sites ?? []).length > 0),
38+
multiPost: false,
39+
},
40+
]
41+
42+
const filters = [
43+
{
44+
filterName: 'SharePoint-only',
45+
value: [{ id: 'GuestType', value: 'SharePoint-only (email authenticated)' }],
46+
type: 'column',
47+
},
48+
{
49+
filterName: 'Orphaned B2B',
50+
value: [{ id: 'GuestType', value: 'Orphaned B2B (not in Entra)' }],
51+
type: 'column',
52+
},
53+
{
54+
filterName: 'Entra B2B',
55+
value: [{ id: 'GuestType', value: 'Entra B2B' }],
56+
type: 'column',
57+
},
58+
]
59+
60+
return (
61+
<CippTablePage
62+
title="SharePoint External Users"
63+
apiUrl="/api/ListSharePointExternalUsers"
64+
apiDataKey="Results"
65+
actions={actions}
66+
filters={filters}
67+
simpleColumns={[
68+
'DisplayName',
69+
'AcceptedAs',
70+
'GuestType',
71+
'InEntra',
72+
'Source',
73+
'Sites',
74+
'WhenCreated',
75+
'InvitedBy',
76+
]}
77+
/>
78+
)
79+
}
80+
81+
Page.getLayout = (page) => <DashboardLayout>{page}</DashboardLayout>
82+
83+
export default Page

src/pages/teams-share/sharepoint/index.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -795,13 +795,6 @@ const Page = () => {
795795
>
796796
Bulk Add Sites
797797
</Button>
798-
<Button
799-
component={Link}
800-
href="/teams-share/sharepoint/deleted-sites"
801-
startIcon={<RestoreFromTrash />}
802-
>
803-
Deleted Sites
804-
</Button>
805798
{reportDB.controls}
806799
</Stack>
807800
)

0 commit comments

Comments
 (0)