diff --git a/.devproxy/api-specs/sharepoint-admin.yaml b/.devproxy/api-specs/sharepoint-admin.yaml index e5cde5340aa..369f89568e4 100644 --- a/.devproxy/api-specs/sharepoint-admin.yaml +++ b/.devproxy/api-specs/sharepoint-admin.yaml @@ -62,6 +62,46 @@ paths: responses: 200: description: OK + /_api/SPO.Tenant/sites('{id}'): + get: + parameters: + - name: id + in: path + required: true + schema: + type: string + description: The site collection ID (GUID) + - name: $select + in: query + required: false + schema: + type: string + description: e.g. "$select=Url" to retrieve only the site URL + security: + - delegated: + - AllSites.FullControl + - application: + - Sites.FullControl.All + responses: + 200: + description: OK + /_api/web/lists/GetByTitle('{listTitle}')/RenderListDataAsStream: + post: + parameters: + - name: listTitle + in: path + required: true + schema: + type: string + description: The list title (e.g. DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS) + security: + - delegated: + - AllSites.FullControl + - application: + - Sites.FullControl.All + responses: + 200: + description: OK x-ms-generated-by: toolName: Dev Proxy toolVersion: 0.25.0 \ No newline at end of file diff --git a/docs/docs/cmd/spo/tenant/tenant-site-get.mdx b/docs/docs/cmd/spo/tenant/tenant-site-get.mdx new file mode 100644 index 00000000000..0aa835dcb1e --- /dev/null +++ b/docs/docs/cmd/spo/tenant/tenant-site-get.mdx @@ -0,0 +1,479 @@ +import Global from '/docs/cmd/_global.mdx'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# spo tenant site get + +Retrieves the tenant site information + +## Usage + +```sh +m365 spo tenant site get [options] +``` + +## Options + +```md definition-list +`-i, --id [id]` +: The ID of the site collection. Specify either `id`, `title`, or `url`, but not multiple. + +`-t, --title [title]` +: Title of the site collection. Specify either `id`, `title`, or `url`, but not multiple. + +`-u, --url [url]` +: The site URL of the site collection. Specify either `id`, `title`, or `url`, but not multiple. +``` + + + +## Permissions + + + + + | Resource | Permissions | + |------------|----------------------| + | SharePoint | AllSites.FullControl | + + + + + | Resource | Permissions | + |------------|-----------------------| + | SharePoint | Sites.FullControl.All | + + + + +## Examples + +Retrieve info about a site using its ID + +```sh +m365 spo tenant site get --id 3ae83bc5-1f27-45c1-9eee-1bd1e2ddce69 +``` + +Retrieve info about a site using its URL + +```sh +m365 spo tenant site get --url "https://contoso.sharepoint.com/sites/Marketing" +``` + +Retrieve info about a site using its Title + +```sh +m365 spo tenant site get --title Marketing +``` + +## Response + + + + + ```json + { + "AllowDownloadingNonWebViewableFiles": false, + "AllowEditing": true, + "AllowFileArchive": false, + "AllowSelfServiceUpgrade": true, + "AllowWebPropertyBagUpdateWhenDenyAddAndCustomizePagesIsEnabled": false, + "AnonymousLinkExpirationInDays": 0, + "ApplyToExistingDocumentLibraries": false, + "ApplyToNewDocumentLibraries": false, + "ArchivedBy": "", + "ArchivedFileDiskUsed": "0", + "ArchivedTime": "0001-01-01T00:00:00", + "ArchiveStatus": "NotArchived", + "AuthContextStrength": null, + "AuthenticationContextLimitedAccess": false, + "AuthenticationContextName": null, + "AverageResourceUsage": 0, + "BlockDownloadLinksFileType": 1, + "BlockDownloadMicrosoft365GroupIds": null, + "BlockDownloadPolicy": false, + "BlockDownloadPolicyFileTypeIds": null, + "BlockGuestsAsSiteAdmin": 0, + "BonusDiskQuota": "920", + "ClearGroupId": false, + "ClearRestrictedAccessControl": false, + "CommentsOnSitePagesDisabled": false, + "CompatibilityLevel": 15, + "ConditionalAccessPolicy": 0, + "CreatedTime": "2021-10-12T09:54:16.52", + "CurrentResourceUsage": 0, + "DefaultLinkPermission": 0, + "DefaultLinkToExistingAccess": false, + "DefaultLinkToExistingAccessReset": false, + "DefaultShareLinkRole": 0, + "DefaultShareLinkScope": -1, + "DefaultSharingLinkType": 0, + "DenyAddAndCustomizePages": 2, + "Description": "", + "DisableAppViews": 2, + "DisableCompanyWideSharingLinks": 2, + "DisableFlows": 2, + "DisableSiteBranding": false, + "EnableAutoExpirationVersionTrim": false, + "ExcludeBlockDownloadPolicySiteOwners": false, + "ExcludeBlockDownloadSharePointGroups": [], + "ExcludedBlockDownloadGroupIds": [], + "ExpireVersionsAfterDays": 0, + "ExternalUserExpirationInDays": 0, + "FileTypesForVersionExpiration": null, + "GroupId": "00000000-0000-0000-0000-000000000000", + "GroupOwnerLoginName": "c:0o.c|federateddirectoryclaimprovider|00000000-0000-0000-0000-000000000000_o", + "HasHolds": false, + "HidePeoplePreviewingFiles": false, + "HidePeopleWhoHaveListsOpen": false, + "HubSiteId": "af80c11f-0138-4d72-bb37-514542c3aabb", + "IBMode": "", + "IBSegments": [], + "IBSegmentsToAdd": null, + "IBSegmentsToRemove": null, + "InheritVersionPolicyFromTenant": true, + "IsAuthoritative": false, + "IsGroupOwnerSiteAdmin": false, + "IsHubSite": false, + "IsTeamsChannelConnected": false, + "IsTeamsConnected": false, + "LastContentModifiedDate": "2025-10-14T17:50:37.08", + "Lcid": "1033", + "LimitedAccessFileType": 1, + "ListsShowHeaderAndNavigation": false, + "LockIssue": null, + "LockReason": 0, + "LockState": "Unlock", + "LoopDefaultSharingLinkRole": 0, + "LoopDefaultSharingLinkScope": -1, + "MajorVersionLimit": 0, + "MajorWithMinorVersionsLimit": 0, + "MediaTranscription": 0, + "OverrideBlockUserInfoVisibility": 0, + "OverrideSharingCapability": false, + "OverrideTenantAnonymousLinkExpirationPolicy": false, + "OverrideTenantExternalUserExpirationPolicy": false, + "Owner": "john@contoso.onmicrosoft.com", + "OwnerEmail": "john@contoso.onmicrosoft.com", + "OwnerLoginName": "i:0#.f|membership|john@contoso.onmicrosoft.com", + "OwnerName": "john", + "PWAEnabled": 1, + "ReadOnlyAccessPolicy": false, + "ReadOnlyForBlockDownloadPolicy": false, + "ReadOnlyForUnmanagedDevices": false, + "RelatedGroupId": "00000000-0000-0000-0000-000000000000", + "RemoveVersionExpirationFileTypeOverride": null, + "RequestFilesLinkEnabled": false, + "RequestFilesLinkExpirationInDays": -1, + "RestrictContentOrgWideSearch": false, + "RestrictedAccessControl": false, + "RestrictedAccessControlGroups": [], + "RestrictedAccessControlGroupsToAdd": null, + "RestrictedAccessControlGroupsToRemove": null, + "RestrictedContentDiscoveryforCopilotAndAgents": false, + "RestrictedToRegion": 3, + "SandboxedCodeActivationCapability": 2, + "SensitivityLabel": "00000000-0000-0000-0000-000000000000", + "SensitivityLabel2": null, + "SetOwnerWithoutUpdatingSecondaryAdmin": false, + "SharingAllowedDomainList": "", + "SharingBlockedDomainList": "", + "SharingCapability": 0, + "SharingDomainRestrictionMode": 0, + "SharingLockDownCanBeCleared": true, + "SharingLockDownEnabled": false, + "ShowPeoplePickerSuggestionsForGuestUsers": false, + "SiteDefinedSharingCapability": 0, + "SiteId": "8f6fdeda-f6ff-4d39-8a8c-fe86565afefd", + "SocialBarOnSitePagesDisabled": false, + "Status": "Active", + "StorageMaximumLevel": "26214400", + "StorageQuotaType": null, + "StorageUsage": "3", + "StorageWarningLevel": "25574400", + "TeamsChannelType": 0, + "Template": "SITEPAGEPUBLISHING#0", + "TimeZoneId": 2, + "Title": "Marketing and Communications", + "TitleTranslations": null, + "Url": "https://contoso.sharepoint.com/sites/marketing", + "UserCodeMaximumLevel": 300, + "UserCodeWarningLevel": 200, + "VersionCount": "7", + "VersionPolicyFileTypeOverride": [], + "VersionSize": "0", + "WebsCount": 1 + } + ``` + + + + + ```text + AllowDownloadingNonWebViewableFiles : false + AllowEditing : true + AllowFileArchive : false + AllowSelfServiceUpgrade : true + AllowWebPropertyBagUpdateWhenDenyAddAndCustomizePagesIsEnabled: false + AnonymousLinkExpirationInDays : 0 + ApplyToExistingDocumentLibraries : false + ApplyToNewDocumentLibraries : false + ArchiveStatus : NotArchived + ArchivedBy : + ArchivedFileDiskUsed : 0 + ArchivedTime : 0001-01-01T00:00:00 + AuthContextStrength : null + AuthenticationContextLimitedAccess : false + AuthenticationContextName : null + AverageResourceUsage : 0 + BlockDownloadLinksFileType : 1 + BlockDownloadMicrosoft365GroupIds : null + BlockDownloadPolicy : false + BlockDownloadPolicyFileTypeIds : null + BlockGuestsAsSiteAdmin : 0 + BonusDiskQuota : 920 + ClearGroupId : false + ClearRestrictedAccessControl : false + CommentsOnSitePagesDisabled : false + CompatibilityLevel : 15 + ConditionalAccessPolicy : 0 + CreatedTime : 2021-10-12T09:54:16.52 + CurrentResourceUsage : 0 + DefaultLinkPermission : 0 + DefaultLinkToExistingAccess : false + DefaultLinkToExistingAccessReset : false + DefaultShareLinkRole : 0 + DefaultShareLinkScope : -1 + DefaultSharingLinkType : 0 + DenyAddAndCustomizePages : 2 + Description : + DisableAppViews : 2 + DisableCompanyWideSharingLinks : 2 + DisableFlows : 2 + DisableSiteBranding : false + EnableAutoExpirationVersionTrim : false + ExcludeBlockDownloadPolicySiteOwners : false + ExcludeBlockDownloadSharePointGroups : [] + ExcludedBlockDownloadGroupIds : [] + ExpireVersionsAfterDays : 0 + ExternalUserExpirationInDays : 0 + FileTypesForVersionExpiration : null + GroupId : 00000000-0000-0000-0000-000000000000 + GroupOwnerLoginName : c:0o.c|federateddirectoryclaimprovider|00000000-0000-0000-0000-000000000000_o + HasHolds : false + HidePeoplePreviewingFiles : false + HidePeopleWhoHaveListsOpen : false + HubSiteId : af80c11f-0138-4d72-bb37-514542c3aabb + IBMode : + IBSegments : [] + IBSegmentsToAdd : null + IBSegmentsToRemove : null + InheritVersionPolicyFromTenant : true + IsAuthoritative : false + IsGroupOwnerSiteAdmin : false + IsHubSite : false + IsTeamsChannelConnected : false + IsTeamsConnected : false + LastContentModifiedDate : 2025-10-14T17:50:37.08 + Lcid : 1033 + LimitedAccessFileType : 1 + ListsShowHeaderAndNavigation : false + LockIssue : null + LockReason : 0 + LockState : Unlock + LoopDefaultSharingLinkRole : 0 + LoopDefaultSharingLinkScope : -1 + MajorVersionLimit : 0 + MajorWithMinorVersionsLimit : 0 + MediaTranscription : 0 + OverrideBlockUserInfoVisibility : 0 + OverrideSharingCapability : false + OverrideTenantAnonymousLinkExpirationPolicy : false + OverrideTenantExternalUserExpirationPolicy : false + Owner : john@contoso.onmicrosoft.com + OwnerEmail : john@contoso.onmicrosoft.com + OwnerLoginName : i:0#.f|membership|john@contoso.onmicrosoft.com + OwnerName : john + PWAEnabled : 1 + ReadOnlyAccessPolicy : false + ReadOnlyForBlockDownloadPolicy : false + ReadOnlyForUnmanagedDevices : false + RelatedGroupId : 00000000-0000-0000-0000-000000000000 + RemoveVersionExpirationFileTypeOverride : null + RequestFilesLinkEnabled : false + RequestFilesLinkExpirationInDays : -1 + RestrictContentOrgWideSearch : false + RestrictedAccessControl : false + RestrictedAccessControlGroups : [] + RestrictedAccessControlGroupsToAdd : null + RestrictedAccessControlGroupsToRemove : null + RestrictedContentDiscoveryforCopilotAndAgents : false + RestrictedToRegion : 3 + SandboxedCodeActivationCapability : 2 + SensitivityLabel : 00000000-0000-0000-0000-000000000000 + SensitivityLabel2 : null + SetOwnerWithoutUpdatingSecondaryAdmin : false + SharingAllowedDomainList : + SharingBlockedDomainList : + SharingCapability : 0 + SharingDomainRestrictionMode : 0 + SharingLockDownCanBeCleared : true + SharingLockDownEnabled : false + ShowPeoplePickerSuggestionsForGuestUsers : false + SiteDefinedSharingCapability : 0 + SiteId : 8f6fdeda-f6ff-4d39-8a8c-fe86565afefd + SocialBarOnSitePagesDisabled : false + Status : Active + StorageMaximumLevel : 26214400 + StorageQuotaType : null + StorageUsage : 3 + StorageWarningLevel : 25574400 + TeamsChannelType : 0 + Template : SITEPAGEPUBLISHING#0 + TimeZoneId : 2 + Title : Marketing and Communications + TitleTranslations : null + Url : https://contoso.sharepoint.com/sites/marketing + UserCodeMaximumLevel : 300 + UserCodeWarningLevel : 200 + VersionCount : 7 + VersionPolicyFileTypeOverride : [] + VersionSize : 0 + WebsCount : 1 + ``` + + + + + ```csv + AllowDownloadingNonWebViewableFiles,AllowEditing,AllowFileArchive,AllowSelfServiceUpgrade,AllowWebPropertyBagUpdateWhenDenyAddAndCustomizePagesIsEnabled,AnonymousLinkExpirationInDays,ApplyToExistingDocumentLibraries,ApplyToNewDocumentLibraries,ArchivedBy,ArchivedFileDiskUsed,ArchivedTime,ArchiveStatus,AuthContextStrength,AuthenticationContextLimitedAccess,AuthenticationContextName,AverageResourceUsage,BlockDownloadLinksFileType,BlockDownloadMicrosoft365GroupIds,BlockDownloadPolicy,BlockDownloadPolicyFileTypeIds,BlockGuestsAsSiteAdmin,BonusDiskQuota,ClearGroupId,ClearRestrictedAccessControl,CommentsOnSitePagesDisabled,CompatibilityLevel,ConditionalAccessPolicy,CreatedTime,CurrentResourceUsage,DefaultLinkPermission,DefaultLinkToExistingAccess,DefaultLinkToExistingAccessReset,DefaultShareLinkRole,DefaultShareLinkScope,DefaultSharingLinkType,DenyAddAndCustomizePages,Description,DisableAppViews,DisableCompanyWideSharingLinks,DisableFlows,DisableSiteBranding,EnableAutoExpirationVersionTrim,ExcludeBlockDownloadPolicySiteOwners,ExpireVersionsAfterDays,ExternalUserExpirationInDays,FileTypesForVersionExpiration,GroupId,GroupOwnerLoginName,HasHolds,HidePeoplePreviewingFiles,HidePeopleWhoHaveListsOpen,HubSiteId,IBMode,IBSegmentsToAdd,IBSegmentsToRemove,InheritVersionPolicyFromTenant,IsAuthoritative,IsGroupOwnerSiteAdmin,IsHubSite,IsTeamsChannelConnected,IsTeamsConnected,LastContentModifiedDate,Lcid,LimitedAccessFileType,ListsShowHeaderAndNavigation,LockIssue,LockReason,LockState,LoopDefaultSharingLinkRole,LoopDefaultSharingLinkScope,MajorVersionLimit,MajorWithMinorVersionsLimit,MediaTranscription,OverrideBlockUserInfoVisibility,OverrideSharingCapability,OverrideTenantAnonymousLinkExpirationPolicy,OverrideTenantExternalUserExpirationPolicy,Owner,OwnerEmail,OwnerLoginName,OwnerName,PWAEnabled,ReadOnlyAccessPolicy,ReadOnlyForBlockDownloadPolicy,ReadOnlyForUnmanagedDevices,RelatedGroupId,RemoveVersionExpirationFileTypeOverride,RequestFilesLinkEnabled,RequestFilesLinkExpirationInDays,RestrictContentOrgWideSearch,RestrictedAccessControl,RestrictedAccessControlGroupsToAdd,RestrictedAccessControlGroupsToRemove,RestrictedContentDiscoveryforCopilotAndAgents,RestrictedToRegion,SandboxedCodeActivationCapability,SensitivityLabel,SensitivityLabel2,SetOwnerWithoutUpdatingSecondaryAdmin,SharingAllowedDomainList,SharingBlockedDomainList,SharingCapability,SharingDomainRestrictionMode,SharingLockDownCanBeCleared,SharingLockDownEnabled,ShowPeoplePickerSuggestionsForGuestUsers,SiteDefinedSharingCapability,SiteId,SocialBarOnSitePagesDisabled,Status,StorageMaximumLevel,StorageQuotaType,StorageUsage,StorageWarningLevel,TeamsChannelType,Template,TimeZoneId,Title,TitleTranslations,Url,UserCodeMaximumLevel,UserCodeWarningLevel,VersionCount,VersionSize,WebsCount + 0,1,0,1,0,0,0,0,,0,0001-01-01T00:00:00,NotArchived,,0,,0,1,,0,,0,920,0,0,0,15,0,2021-10-12T09:54:16.52,0,0,0,0,0,-1,0,2,,2,2,2,0,0,0,0,0,,00000000-0000-0000-0000-000000000000,c:0o.c|federateddirectoryclaimprovider|00000000-0000-0000-0000-000000000000_o,0,0,0,af80c11f-0138-4d72-bb37-514542c3aabb,,,,1,0,0,0,0,0,2025-10-14T17:50:37.08,1033,1,0,,0,Unlock,0,-1,0,0,0,0,0,0,0,john@contoso.onmicrosoft.com,john@contoso.onmicrosoft.com,i:0#.f|membership|john@contoso.onmicrosoft.com,john,1,0,0,0,00000000-0000-0000-0000-000000000000,,0,-1,0,0,,,0,3,2,00000000-0000-0000-0000-000000000000,,0,,,0,0,1,0,0,0,8f6fdeda-f6ff-4d39-8a8c-fe86565afefd,0,Active,26214400,,3,25574400,0,SITEPAGEPUBLISHING#0,2,Marketing and Communications,,https://contoso.sharepoint.com/sites/marketing,300,200,7,0,1 + ``` + + + + + ```md + # spo tenant site get --debug "false" --verbose "false" --id "8f6fdeda-f6ff-4d39-8a8c-fe86565afefd" + + Date: 10/14/2025 + + ## Marketing and Communications (https://contoso.sharepoint.com/sites/marketing) + + Property | Value + ---------|------- + AllowDownloadingNonWebViewableFiles | false + AllowEditing | true + AllowFileArchive | false + AllowSelfServiceUpgrade | true + AllowWebPropertyBagUpdateWhenDenyAddAndCustomizePagesIsEnabled | false + AnonymousLinkExpirationInDays | 0 + ApplyToExistingDocumentLibraries | false + ApplyToNewDocumentLibraries | false + ArchivedBy | + ArchivedFileDiskUsed | 0 + ArchivedTime | 0001-01-01T00:00:00 + ArchiveStatus | NotArchived + AuthenticationContextLimitedAccess | false + AverageResourceUsage | 0 + BlockDownloadLinksFileType | 1 + BlockDownloadPolicy | false + BlockGuestsAsSiteAdmin | 0 + BonusDiskQuota | 920 + ClearGroupId | false + ClearRestrictedAccessControl | false + CommentsOnSitePagesDisabled | false + CompatibilityLevel | 15 + ConditionalAccessPolicy | 0 + CreatedTime | 2021-10-12T09:54:16.52 + CurrentResourceUsage | 0 + DefaultLinkPermission | 0 + DefaultLinkToExistingAccess | false + DefaultLinkToExistingAccessReset | false + DefaultShareLinkRole | 0 + DefaultShareLinkScope | -1 + DefaultSharingLinkType | 0 + DenyAddAndCustomizePages | 2 + Description | + DisableAppViews | 2 + DisableCompanyWideSharingLinks | 2 + DisableFlows | 2 + DisableSiteBranding | false + EnableAutoExpirationVersionTrim | false + ExcludeBlockDownloadPolicySiteOwners | false + ExpireVersionsAfterDays | 0 + ExternalUserExpirationInDays | 0 + GroupId | 00000000-0000-0000-0000-000000000000 + GroupOwnerLoginName | c:0o.c\|federateddirectoryclaimprovider\|00000000-0000-0000-0000-000000000000\_o + HasHolds | false + HidePeoplePreviewingFiles | false + HidePeopleWhoHaveListsOpen | false + HubSiteId | af80c11f-0138-4d72-bb37-514542c3aabb + IBMode | + InheritVersionPolicyFromTenant | true + IsAuthoritative | false + IsGroupOwnerSiteAdmin | false + IsHubSite | false + IsTeamsChannelConnected | false + IsTeamsConnected | false + LastContentModifiedDate | 2025-10-14T17:50:37.08 + Lcid | 1033 + LimitedAccessFileType | 1 + ListsShowHeaderAndNavigation | false + LockReason | 0 + LockState | Unlock + LoopDefaultSharingLinkRole | 0 + LoopDefaultSharingLinkScope | -1 + MajorVersionLimit | 0 + MajorWithMinorVersionsLimit | 0 + MediaTranscription | 0 + OverrideBlockUserInfoVisibility | 0 + OverrideSharingCapability | false + OverrideTenantAnonymousLinkExpirationPolicy | false + OverrideTenantExternalUserExpirationPolicy | false + Owner | john@contoso.onmicrosoft.com + OwnerEmail | john@contoso.onmicrosoft.com + OwnerLoginName | i:0#.f\|membership\|john@contoso.onmicrosoft.com + OwnerName | john + PWAEnabled | 1 + ReadOnlyAccessPolicy | false + ReadOnlyForBlockDownloadPolicy | false + ReadOnlyForUnmanagedDevices | false + RelatedGroupId | 00000000-0000-0000-0000-000000000000 + RequestFilesLinkEnabled | false + RequestFilesLinkExpirationInDays | -1 + RestrictContentOrgWideSearch | false + RestrictedAccessControl | false + RestrictedContentDiscoveryforCopilotAndAgents | false + RestrictedToRegion | 3 + SandboxedCodeActivationCapability | 2 + SensitivityLabel | 00000000-0000-0000-0000-000000000000 + SetOwnerWithoutUpdatingSecondaryAdmin | false + SharingAllowedDomainList | + SharingBlockedDomainList | + SharingCapability | 0 + SharingDomainRestrictionMode | 0 + SharingLockDownCanBeCleared | true + SharingLockDownEnabled | false + ShowPeoplePickerSuggestionsForGuestUsers | false + SiteDefinedSharingCapability | 0 + SiteId | 8f6fdeda-f6ff-4d39-8a8c-fe86565afefd + SocialBarOnSitePagesDisabled | false + Status | Active + StorageMaximumLevel | 26214400 + StorageUsage | 3 + StorageWarningLevel | 25574400 + TeamsChannelType | 0 + Template | SITEPAGEPUBLISHING#0 + TimeZoneId | 2 + Title | Marketing and Communications + Url | https://contoso.sharepoint.com/sites/marketing + UserCodeMaximumLevel | 300 + UserCodeWarningLevel | 200 + VersionCount | 7 + VersionSize | 0 + WebsCount | 1 + ``` + + + diff --git a/docs/src/config/sidebars.ts b/docs/src/config/sidebars.ts index b6c437fbe6a..d57eea793bf 100644 --- a/docs/src/config/sidebars.ts +++ b/docs/src/config/sidebars.ts @@ -4029,6 +4029,11 @@ const sidebars: SidebarsConfig = { type: 'doc', label: 'tenant settings set', id: 'cmd/spo/tenant/tenant-settings-set' + }, + { + type: 'doc', + label: 'tenant site get', + id: 'cmd/spo/tenant/tenant-site-get' } ] }, diff --git a/src/m365/spo/commands.ts b/src/m365/spo/commands.ts index c7497aa11ec..1d37e591f1f 100644 --- a/src/m365/spo/commands.ts +++ b/src/m365/spo/commands.ts @@ -336,6 +336,7 @@ export default { TENANT_RECYCLEBINITEM_RESTORE: `${prefix} tenant recyclebinitem restore`, TENANT_SETTINGS_LIST: `${prefix} tenant settings list`, TENANT_SETTINGS_SET: `${prefix} tenant settings set`, + TENANT_SITE_GET: `${prefix} tenant site get`, TERM_ADD: `${prefix} term add`, TERM_GET: `${prefix} term get`, TERM_LIST: `${prefix} term list`, diff --git a/src/m365/spo/commands/tenant/tenant-site-get.spec.ts b/src/m365/spo/commands/tenant/tenant-site-get.spec.ts new file mode 100644 index 00000000000..8896c5759f9 --- /dev/null +++ b/src/m365/spo/commands/tenant/tenant-site-get.spec.ts @@ -0,0 +1,321 @@ +import assert from 'assert'; +import sinon from 'sinon'; +import auth from '../../../../Auth.js'; +import { cli } from '../../../../cli/cli.js'; +import { CommandInfo } from '../../../../cli/CommandInfo.js'; +import { Logger } from '../../../../cli/Logger.js'; +import { CommandError } from '../../../../Command.js'; +import request from '../../../../request.js'; +import { telemetry } from '../../../../telemetry.js'; +import { pid } from '../../../../utils/pid.js'; +import { session } from '../../../../utils/session.js'; +import { sinonUtil } from '../../../../utils/sinonUtil.js'; +import commands from '../../commands.js'; +import command from './tenant-site-get.js'; +import { spo, TenantSiteProperties } from '../../../../utils/spo.js'; +import { settingsNames } from '../../../../settingsNames.js'; + +describe(commands.TENANT_SITE_GET, () => { + const adminUrl = 'https://contoso-admin.sharepoint.com'; + const siteId = '3ae83bc5-1f27-45c1-9eee-1bd1e2ddce69'; + const siteUrl = 'https://contoso.sharepoint.com/sites/Marketing'; + + let log: any[]; + let logger: Logger; + let loggerLogSpy: sinon.SinonSpy; + let commandInfo: CommandInfo; + + const siteResponse: TenantSiteProperties = { + AllowDownloadingNonWebViewableFiles: false, + AllowEditing: true, + AllowFileArchive: false, + AllowSelfServiceUpgrade: true, + AllowWebPropertyBagUpdateWhenDenyAddAndCustomizePagesIsEnabled: false, + AnonymousLinkExpirationInDays: 0, + ApplyToExistingDocumentLibraries: false, + ApplyToNewDocumentLibraries: false, + ArchivedBy: "", + ArchivedFileDiskUsed: "0", + ArchivedTime: "0001-01-01T00:00:00", + ArchiveStatus: "NotArchived", + AuthContextStrength: null, + AuthenticationContextLimitedAccess: false, + AuthenticationContextName: null, + AverageResourceUsage: 0, + BlockDownloadLinksFileType: 1, + BlockDownloadMicrosoft365GroupIds: null, + BlockDownloadPolicy: false, + BlockDownloadPolicyFileTypeIds: null, + BlockGuestsAsSiteAdmin: 0, + BonusDiskQuota: "920", + ClearGroupId: false, + ClearRestrictedAccessControl: false, + CommentsOnSitePagesDisabled: false, + CompatibilityLevel: 15, + ConditionalAccessPolicy: 0, + CreatedTime: "2021-10-12T09:54:16.52", + CurrentResourceUsage: 0, + DefaultLinkPermission: 0, + DefaultLinkToExistingAccess: false, + DefaultLinkToExistingAccessReset: false, + DefaultShareLinkRole: 0, + DefaultShareLinkScope: -1, + DefaultSharingLinkType: 0, + DenyAddAndCustomizePages: 2, + Description: "", + DisableAppViews: 2, + DisableCompanyWideSharingLinks: 2, + DisableFlows: 2, + DisableSiteBranding: false, + EnableAutoExpirationVersionTrim: false, + ExcludeBlockDownloadPolicySiteOwners: false, + ExcludeBlockDownloadSharePointGroups: [], + ExcludedBlockDownloadGroupIds: [], + ExpireVersionsAfterDays: 0, + ExternalUserExpirationInDays: 0, + FileTypesForVersionExpiration: null, + GroupId: "00000000-0000-0000-0000-000000000000", + GroupOwnerLoginName: "c:0o.c|federateddirectoryclaimprovider|00000000-0000-0000-0000-000000000000_o", + HasHolds: false, + HidePeoplePreviewingFiles: false, + HidePeopleWhoHaveListsOpen: false, + HubSiteId: "af80c11f-0138-4d72-bb37-514542c3aabb", + IBMode: "", + IBSegments: [], + IBSegmentsToAdd: null, + IBSegmentsToRemove: null, + InheritVersionPolicyFromTenant: true, + IsAuthoritative: false, + IsGroupOwnerSiteAdmin: false, + IsHubSite: false, + IsTeamsChannelConnected: false, + IsTeamsConnected: false, + LastContentModifiedDate: "2025-10-03T00:20:28.62", + Lcid: "1033", + LimitedAccessFileType: 1, + ListsShowHeaderAndNavigation: false, + LockIssue: null, + LockReason: 0, + LockState: "Unlock", + LoopDefaultSharingLinkRole: 0, + LoopDefaultSharingLinkScope: -1, + MajorVersionLimit: 0, + MajorWithMinorVersionsLimit: 0, + MediaTranscription: 0, + OverrideBlockUserInfoVisibility: 0, + OverrideSharingCapability: false, + OverrideTenantAnonymousLinkExpirationPolicy: false, + OverrideTenantExternalUserExpirationPolicy: false, + Owner: "john@contoso.onmicrosoft.com", + OwnerEmail: "john@contoso.onmicrosoft.com", + OwnerLoginName: "i:0#.f|membership|john@contoso.onmicrosoft.com", + OwnerName: "john", + PWAEnabled: 1, + ReadOnlyAccessPolicy: false, + ReadOnlyForBlockDownloadPolicy: false, + ReadOnlyForUnmanagedDevices: false, + RelatedGroupId: "00000000-0000-0000-0000-000000000000", + RemoveVersionExpirationFileTypeOverride: null, + RequestFilesLinkEnabled: false, + RequestFilesLinkExpirationInDays: -1, + RestrictContentOrgWideSearch: false, + RestrictedAccessControl: false, + RestrictedAccessControlGroups: [], + RestrictedAccessControlGroupsToAdd: null, + RestrictedAccessControlGroupsToRemove: null, + RestrictedContentDiscoveryforCopilotAndAgents: false, + RestrictedToRegion: 3, + SandboxedCodeActivationCapability: 2, + SensitivityLabel: "00000000-0000-0000-0000-000000000000", + SensitivityLabel2: null, + SetOwnerWithoutUpdatingSecondaryAdmin: false, + SharingAllowedDomainList: "", + SharingBlockedDomainList: "", + SharingCapability: 0, + SharingDomainRestrictionMode: 0, + SharingLockDownCanBeCleared: true, + SharingLockDownEnabled: false, + ShowPeoplePickerSuggestionsForGuestUsers: false, + SiteDefinedSharingCapability: 0, + SiteId: "8f6fdeda-f6ff-4d39-8a8c-fe86565afefd", + SocialBarOnSitePagesDisabled: false, + Status: "Active", + StorageMaximumLevel: "26214400", + StorageQuotaType: null, + StorageUsage: "3", + StorageWarningLevel: "25574400", + TeamsChannelType: 0, + Template: "SITEPAGEPUBLISHING#0", + TimeZoneId: 2, + Title: "Marketing and Communications", + TitleTranslations: null, + Url: "https://contoso.sharepoint.com/sites/marketing", + UserCodeMaximumLevel: 300, + UserCodeWarningLevel: 200, + VersionCount: "7", + VersionPolicyFileTypeOverride: [], + VersionSize: "0", + WebsCount: 1 + }; + + before(() => { + sinon.stub(auth, 'restoreAuth').resolves(); + sinon.stub(telemetry, 'trackEvent').resolves(); + sinon.stub(pid, 'getProcessName').returns(''); + sinon.stub(session, 'getId').returns(''); + auth.connection.active = true; + commandInfo = cli.getCommandInfo(command); + sinon.stub(cli, 'getSettingWithDefaultValue').callsFake((settingName: string, defaultValue: any) => { + if (settingName === settingsNames.prompt) { + return false; + } + + return defaultValue; + }); + }); + + beforeEach(() => { + log = []; + logger = { + log: async (msg: string) => { + log.push(msg); + }, + logRaw: async (msg: string) => { + log.push(msg); + }, + logToStderr: async (msg: string) => { + log.push(msg); + } + }; + loggerLogSpy = sinon.spy(logger, 'log'); + sinon.stub(spo, 'getSpoAdminUrl').resolves(adminUrl); + }); + + afterEach(() => { + sinonUtil.restore([ + request.get, + request.post, + cli.handleMultipleResultsFound, + spo.getSpoAdminUrl, + spo.getSiteAdminPropertiesByUrl + ]); + }); + + after(() => { + sinon.restore(); + auth.connection.active = false; + }); + + it('has correct name', () => { + assert.strictEqual(command.name, commands.TENANT_SITE_GET); + }); + + it('has a description', () => { + assert.notStrictEqual(command.description, null); + }); + + it('retrieves site by id', async () => { + sinon.stub(request, 'get').callsFake(async (opts) => { + if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites('${siteId}')?$select=Url`) { + return { Url: siteUrl }; + } + throw 'Invalid request'; + }); + + sinon.stub(spo, 'getSiteAdminPropertiesByUrl').resolves(siteResponse); + + await command.action(logger, { options: { id: siteId, verbose: true } }); + assert(loggerLogSpy.calledWith(siteResponse)); + }); + + it('retrieves site by url', async () => { + sinon.stub(spo, 'getSiteAdminPropertiesByUrl').resolves(siteResponse); + + await command.action(logger, { options: { url: siteUrl, verbose: true } }); + assert(loggerLogSpy.calledWith(siteResponse)); + }); + + it('retrieves site by title (single result)', async () => { + sinon.stub(request, 'post').callsFake(async (opts) => { + if (opts.url === `${adminUrl}/_api/web/lists/GetByTitle('DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS')/RenderListDataAsStream`) { + return { Row: [{ Title: 'Marketing', SiteUrl: siteUrl, SiteId: `/Guid(${siteId})/` }] }; + } + throw 'Invalid request'; + }); + + sinon.stub(spo, 'getSiteAdminPropertiesByUrl').resolves(siteResponse); + + await command.action(logger, { options: { title: 'Marketing', verbose: true } }); + assert(loggerLogSpy.calledWith(siteResponse)); + }); + + it('retrieves site by title (multiple results prompts)', async () => { + sinon.stub(request, 'post').callsFake(async (opts) => { + if (opts.url === `${adminUrl}/_api/web/lists/GetByTitle('DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS')/RenderListDataAsStream`) { + return { + Row: [ + { Title: 'Marketing', SiteUrl: siteUrl, SiteId: `/Guid(${siteId})/` }, + { Title: 'Marketing', SiteUrl: 'https://contoso.sharepoint.com/sites/Marketing2', SiteId: '/Guid(53dec431-9d4f-415b-b12b-010259d5b4e1)/' } + ] + }; + } + throw 'Invalid request'; + }); + + sinon.stub(cli, 'handleMultipleResultsFound').resolves({ url: siteUrl } as any); + + sinon.stub(spo, 'getSiteAdminPropertiesByUrl').resolves(siteResponse); + + await command.action(logger, { options: { title: 'Marketing', verbose: true } }); + assert(loggerLogSpy.calledWith(siteResponse)); + }); + + it('handles error when specified site by title not found', async () => { + sinon.stub(request, 'post').callsFake(async (opts) => { + if (opts.url === `${adminUrl}/_api/web/lists/GetByTitle('DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS')/RenderListDataAsStream`) { + return { Row: [] }; + } + throw 'Invalid request'; + }); + + await assert.rejects(command.action(logger, { options: { title: 'Marketing', verbose: true } } as any), new CommandError("The specified site 'Marketing' does not exist.")); + }); + + it('fails validation when specifying none of id, title, url', async () => { + const commandOptionsSchema = commandInfo.command.getSchemaToParse()!; + const refined = commandInfo.command.getRefinedSchema!(commandOptionsSchema as any)!; + const actual = refined.safeParse({}); + assert.strictEqual(actual.success, false); + }); + + it('fails validation when specifying multiple of id, title, url', async () => { + const commandOptionsSchema = commandInfo.command.getSchemaToParse()!; + const refined = commandInfo.command.getRefinedSchema!(commandOptionsSchema as any)!; + const actual = refined.safeParse({ id: siteId, url: siteUrl }); + assert.strictEqual(actual.success, false); + }); + + it('handles OData error when site not found', async () => { + sinon.stub(request, 'get').callsFake(async (opts) => { + if (opts.url === `${adminUrl}/_api/SPO.Tenant/sites('${siteId}')?$select=Url`) { + const error = { + error: { + 'odata.error': { + code: '-2147024891, System.UnauthorizedAccessException', + message: { + lang: 'en-US', + value: 'Attempted to perform an unauthorized operation.' + } + } + } + }; + throw error; + } + throw 'Invalid request'; + }); + + await assert.rejects(command.action(logger, { options: { id: siteId, verbose: true } } as any), new CommandError('Attempted to perform an unauthorized operation.')); + }); +}); + + diff --git a/src/m365/spo/commands/tenant/tenant-site-get.ts b/src/m365/spo/commands/tenant/tenant-site-get.ts new file mode 100644 index 00000000000..06e6d4c6953 --- /dev/null +++ b/src/m365/spo/commands/tenant/tenant-site-get.ts @@ -0,0 +1,137 @@ +import { z } from 'zod'; +import { Logger } from '../../../../cli/Logger.js'; +import { globalOptionsZod } from '../../../../Command.js'; +import request, { CliRequestOptions } from '../../../../request.js'; +import { formatting } from '../../../../utils/formatting.js'; +import { spo } from '../../../../utils/spo.js'; +import { validation } from '../../../../utils/validation.js'; +import { zod } from '../../../../utils/zod.js'; +import SpoCommand from '../../../base/SpoCommand.js'; +import commands from '../../commands.js'; +import { cli } from '../../../../cli/cli.js'; + +const optionsSchema = globalOptionsZod + .extend({ + id: zod.alias('i', z.string().refine(id => validation.isValidGuid(id), { message: 'Specify a valid GUID' }).optional()), + title: zod.alias('t', z.string().optional()), + url: zod.alias('u', z.string().refine(url => validation.isValidSharePointUrl(url) === true, { + message: 'Specify a valid SharePoint site URL' + }).optional()) + }) + .strict(); +declare type Options = z.infer; + +interface CommandArgs { + options: Options; +} + +class SpoTenantSiteGetCommand extends SpoCommand { + public get name(): string { + return commands.TENANT_SITE_GET; + } + + public get description(): string { + return 'Retrieves the tenant site information'; + } + + public get schema(): z.ZodTypeAny | undefined { + return optionsSchema; + } + + public getRefinedSchema(schema: typeof optionsSchema): z.ZodEffects | undefined { + return schema.refine(o => [o.id, o.title, o.url].filter(v => v !== undefined).length === 1, { + message: `Specify exactly one of the following options: 'id', 'title', or 'url'.` + }); + } + + public async commandAction(logger: Logger, args: CommandArgs): Promise { + if (this.verbose) { + await logger.logToStderr(`Retrieving tenant site information for site '${args.options.url || args.options.id || args.options.title}'...`); + } + + try { + let siteUrl: string; + if (args.options.url) { + siteUrl = args.options.url; + } + else if (args.options.id) { + siteUrl = await this.getSiteUrlById(args.options.id, logger); + if (this.verbose) { + await logger.logToStderr(`Retrieved tenant site URL for site '${args.options.id}'...`); + } + } + else { + siteUrl = await this.getSiteUrlByTitle(args.options.title!, logger); + if (this.verbose) { + await logger.logToStderr(`Retrieved tenant site URL for site '${args.options.title}'...`); + } + } + const site = await spo.getSiteAdminPropertiesByUrl(siteUrl, false, logger, this.verbose); + await logger.log(site); + } + catch (err: any) { + this.handleRejectedODataJsonPromise(err); + } + } + + private async getSiteUrlById(id: string, logger: Logger): Promise { + if (this.verbose) { + await logger.logToStderr(`Retrieving tenant site URL for site '${id}'...`); + } + + const adminUrl: string = await spo.getSpoAdminUrl(logger, this.debug); + const requestOptions: CliRequestOptions = { + url: `${adminUrl}/_api/SPO.Tenant/sites('${id}')?$select=Url`, + headers: { + accept: 'application/json;odata=nometadata' + }, + responseType: 'json' + }; + + const res = await request.get<{ Url: string }>(requestOptions); + return res.Url; + } + + private async getSiteUrlByTitle(title: string, logger: Logger): Promise { + if (this.verbose) { + await logger.logToStderr(`Retrieving tenant site URL for site '${title}'...`); + } + + const adminUrl = await spo.getSpoAdminUrl(logger, this.debug); + const viewXml = `${formatting.escapeXml(title)}`; + const requestOptions: CliRequestOptions = { + url: `${adminUrl}/_api/web/lists/GetByTitle('DO_NOT_DELETE_SPLIST_TENANTADMIN_AGGREGATED_SITECOLLECTIONS')/RenderListDataAsStream`, + headers: { + accept: 'application/json;odata=nometadata' + }, + responseType: 'json', + data: { + parameters: { + ViewXml: viewXml, + DatesInUtc: true + } + } + }; + + const res = await request.post<{ Row: { Title: string; SiteUrl: string; SiteId: string }[] }>(requestOptions); + const rows = res.Row; + if (rows.length === 0) { + throw `The specified site '${title}' does not exist.`; + } + + if (rows.length > 1) { + const resultAsKeyValuePair = rows.reduce((acc, cur) => { + acc[cur.SiteUrl] = { url: cur.SiteUrl }; + return acc; + }, {} as any); + const selection = await cli.handleMultipleResultsFound<{ url: string }>(`Multiple sites with title '${title}' found.`, resultAsKeyValuePair); + return selection.url; + } + + return rows[0].SiteUrl; + } +} + +export default new SpoTenantSiteGetCommand(); + + diff --git a/src/utils/spo.ts b/src/utils/spo.ts index ebdc840a1a9..47843b54a47 100644 --- a/src/utils/spo.ts +++ b/src/utils/spo.ts @@ -140,14 +140,17 @@ interface CopyJobObjectInfo { // Wrapping this into a settings object so we can alter the values in tests const pollingInterval = 3_000; -interface TenantSiteProperties { +export interface TenantSiteProperties { AllowDownloadingNonWebViewableFiles: boolean; AllowEditing: boolean; + AllowFileArchive: boolean; AllowSelfServiceUpgrade: boolean; + AllowWebPropertyBagUpdateWhenDenyAddAndCustomizePagesIsEnabled: boolean; AnonymousLinkExpirationInDays: number; ApplyToExistingDocumentLibraries: boolean; ApplyToNewDocumentLibraries: boolean; ArchivedBy: string; + ArchivedFileDiskUsed: string; ArchivedTime: string; ArchiveStatus: string; AuthContextStrength: any; @@ -160,7 +163,9 @@ interface TenantSiteProperties { BlockDownloadPolicyFileTypeIds: any; BlockGuestsAsSiteAdmin: number; BonusDiskQuota: string; + ClearGroupId: boolean; ClearRestrictedAccessControl: boolean; + CreatedTime: string; CommentsOnSitePagesDisabled: boolean; CompatibilityLevel: number; ConditionalAccessPolicy: number; @@ -176,21 +181,26 @@ interface TenantSiteProperties { DisableAppViews: number; DisableCompanyWideSharingLinks: number; DisableFlows: number; + DisableSiteBranding: boolean; EnableAutoExpirationVersionTrim: boolean; ExcludeBlockDownloadPolicySiteOwners: boolean; ExcludeBlockDownloadSharePointGroups: any[]; ExcludedBlockDownloadGroupIds: any[]; ExpireVersionsAfterDays: number; ExternalUserExpirationInDays: number; + FileTypesForVersionExpiration: any; GroupId: string; - GroupOwnerLoginName: string; + GroupOwnerLoginName: string | null; HasHolds: boolean; + HidePeoplePreviewingFiles: boolean; + HidePeopleWhoHaveListsOpen: boolean; HubSiteId: string; IBMode: string; IBSegments: any[]; IBSegmentsToAdd: any; IBSegmentsToRemove: any; InheritVersionPolicyFromTenant: boolean; + IsAuthoritative: boolean; IsGroupOwnerSiteAdmin: boolean; IsHubSite: boolean; IsTeamsChannelConnected: boolean; @@ -220,6 +230,7 @@ interface TenantSiteProperties { ReadOnlyForBlockDownloadPolicy: boolean; ReadOnlyForUnmanagedDevices: boolean; RelatedGroupId: string; + RemoveVersionExpirationFileTypeOverride: any; RequestFilesLinkEnabled: boolean; RequestFilesLinkExpirationInDays: number; RestrictContentOrgWideSearch: boolean; @@ -227,6 +238,7 @@ interface TenantSiteProperties { RestrictedAccessControlGroups: any[]; RestrictedAccessControlGroupsToAdd: any; RestrictedAccessControlGroupsToRemove: any; + RestrictedContentDiscoveryforCopilotAndAgents: boolean; RestrictedToRegion: number; SandboxedCodeActivationCapability: number; SensitivityLabel: string; @@ -242,7 +254,7 @@ interface TenantSiteProperties { SiteDefinedSharingCapability: number; SiteId: string; SocialBarOnSitePagesDisabled: boolean; - Status: string; + Status: string | null; StorageMaximumLevel: string; StorageQuotaType: any; StorageUsage: string; @@ -251,10 +263,13 @@ interface TenantSiteProperties { Template: string; TimeZoneId: number; Title: string; - TitleTranslations: Array<{ LCID: number; Value: string }>; + TitleTranslations: Array<{ LCID: number; Value: string }> | null; Url: string; UserCodeMaximumLevel: number; UserCodeWarningLevel: number; + VersionCount: string; + VersionPolicyFileTypeOverride: any; + VersionSize: string; WebsCount: number; }