diff --git a/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00000.response.json b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00000.response.json new file mode 100644 index 0000000000..57f238e252 --- /dev/null +++ b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00000.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"b4d19ba0-a05f-6000-4f5e-2fd5bf30d1a0","SPClientServiceRequestDuration":"9","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022RegionalSettings\u0022:{\u0022TimeZone\u0022:{\u0022Description\u0022:\u0022(UTC-08:00) Pacific Time (US and Canada)\u0022,\u0022Id\u0022:13,\u0022Information\u0022:{\u0022Bias\u0022:480,\u0022DaylightBias\u0022:-60,\u0022StandardBias\u0022:0}},\u0022AdjustHijriDays\u0022:0,\u0022AlternateCalendarType\u0022:0,\u0022AM\u0022:\u0022AM\u0022,\u0022CalendarType\u0022:1,\u0022Collation\u0022:25,\u0022CollationLCID\u0022:2070,\u0022DateFormat\u0022:0,\u0022DateSeparator\u0022:\u0022/\u0022,\u0022DecimalSeparator\u0022:\u0022.\u0022,\u0022DigitGrouping\u0022:\u00223;0\u0022,\u0022FirstDayOfWeek\u0022:0,\u0022FirstWeekOfYear\u0022:0,\u0022IsEastAsia\u0022:false,\u0022IsRightToLeft\u0022:false,\u0022IsUIRightToLeft\u0022:false,\u0022ListSeparator\u0022:\u0022,\u0022,\u0022LocaleId\u0022:1033,\u0022NegativeSign\u0022:\u0022-\u0022,\u0022NegNumberMode\u0022:1,\u0022PM\u0022:\u0022PM\u0022,\u0022PositiveSign\u0022:\u0022\u0022,\u0022ShowWeeks\u0022:false,\u0022ThousandSeparator\u0022:\u0022,\u0022,\u0022Time24\u0022:false,\u0022TimeMarkerPosition\u0022:0,\u0022TimeSeparator\u0022:\u0022:\u0022,\u0022WorkDayEndHour\u0022:1020,\u0022WorkDays\u0022:62,\u0022WorkDayStartHour\u0022:480},\u0022Id\u0022:\u002272b351a9-34df-4337-9fb9-c20079fd2b9c\u0022,\u0022Url\u0022:\u0022https://nuborocks.sharepoint.com/sites/pnpcoresdktestgroup\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00001.response.json b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00001.response.json new file mode 100644 index 0000000000..8ec7a0ef7e --- /dev/null +++ b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00001.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"b4d19ba0-b085-6000-4f5e-28783cac69a0","SPClientServiceRequestDuration":"10","X-SharePointHealthScore":"2","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022GroupId\u0022:\u0022e4770f8b-cddd-4f62-9cc5-11777e538653\u0022,\u0022Id\u0022:\u0022157a9fac-e4d3-4a7c-ab7f-b90b29012a5c\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00002.response.json b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00002.response.json new file mode 100644 index 0000000000..9499eae0ed --- /dev/null +++ b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00002.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"b7d19ba0-0016-6000-4f5e-28c00fb1822a","SPClientServiceRequestDuration":"15","X-SharePointHealthScore":"0","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022Id\u0022:8,\u0022IsHiddenInUI\u0022:false,\u0022LoginName\u0022:\u0022c:0-.f|rolemanager|spo-grid-all-users/1840b34e-6fe7-4a56-9ad3-0b7b58c49dc7\u0022,\u0022Title\u0022:\u0022Everyone except external users\u0022,\u0022PrincipalType\u0022:4,\u0022Email\u0022:\u0022\u0022,\u0022Expiration\u0022:\u0022\u0022,\u0022IsEmailAuthenticationGuestUser\u0022:false,\u0022IsShareByEmailGuestUser\u0022:false,\u0022IsSiteAdmin\u0022:false,\u0022UserId\u0022:null,\u0022UserPrincipalName\u0022:null}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00003.response.json b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00003.response.json new file mode 100644 index 0000000000..25173749d5 --- /dev/null +++ b/src/sdk/PnP.Core.Test/SharePoint/MockData/WebTests/EnsuresEveryoneExceptExternalUsersTest-0-00003.response.json @@ -0,0 +1 @@ +{"IsSuccessStatusCode":true,"StatusCode":200,"Headers":{"SPRequestGuid":"45d09ba0-60cd-6000-4f5e-2437a59729df","SPClientServiceRequestDuration":"14","X-SharePointHealthScore":"1","X-SP-SERVERSTATE":"ReadOnly=0"},"Response":"{\u0022Id\u0022:9,\u0022IsHiddenInUI\u0022:false,\u0022LoginName\u0022:\u0022i:0#.f|membership|pla@nuborocks.onmicrosoft.com\u0022,\u0022Title\u0022:\u0022Patrick Lamber\u0022,\u0022PrincipalType\u0022:1,\u0022Email\u0022:\u0022pla@nuborocks.onmicrosoft.com\u0022,\u0022Expiration\u0022:\u0022\u0022,\u0022IsEmailAuthenticationGuestUser\u0022:false,\u0022IsShareByEmailGuestUser\u0022:false,\u0022IsSiteAdmin\u0022:false,\u0022UserId\u0022:{\u0022NameId\u0022:\u00221003200270f8c6bb\u0022,\u0022NameIdIssuer\u0022:\u0022urn:federation:microsoftonline\u0022},\u0022UserPrincipalName\u0022:\u0022pla@nuborocks.onmicrosoft.com\u0022}"} \ No newline at end of file diff --git a/src/sdk/PnP.Core.Test/SharePoint/WebTests.cs b/src/sdk/PnP.Core.Test/SharePoint/WebTests.cs index 388c373e99..f0abe9924f 100644 --- a/src/sdk/PnP.Core.Test/SharePoint/WebTests.cs +++ b/src/sdk/PnP.Core.Test/SharePoint/WebTests.cs @@ -784,7 +784,7 @@ public void TimeZoneMappingTest2(int sharePointTimeZone) { Assert.IsNotNull(Model.SharePoint.TimeZone.GetTimeZoneInfoFromSharePoint(sharePointTimeZone)); } - + [TestMethod] public async Task GetTimeZoneInfoTest() { @@ -793,7 +793,7 @@ public async Task GetTimeZoneInfoTest() { var timeZoneInfo = context.Web.RegionalSettings.TimeZone.GetTimeZoneInfo(); Assert.IsTrue(timeZoneInfo != null); - } + } } [TestMethod] @@ -842,7 +842,7 @@ public void TimeZoneConversionTests() utcDate = localDate.ToUniversalTime(); localWebTime = utcDate - UtcDelta(utcDate, -60, -60, 0, 3); Assert.IsTrue(localWebTime.Hour == 15); - + } private TimeSpan UtcDelta(DateTime dateTime, int bias, int daylightBias, int standardBias, int id) @@ -1010,6 +1010,20 @@ public async Task GetWebCurrentUserBatchTest() } } + [TestMethod] + public async Task EnsuresEveryoneExceptExternalUsersTest() + { + //TestCommon.Instance.Mocking = false; + using (var context = await TestCommon.Instance.GetContextAsync(TestCommon.TestSite)) + { + var ensuredUser = await context.Web.GetEveryoneExceptExternalUsersAsync(); + + Assert.IsTrue(ensuredUser.Requested); + Assert.IsTrue(ensuredUser is Model.Security.ISharePointUser); + Assert.IsTrue(ensuredUser.LoginName.StartsWith($"c:0-.f|rolemanager|spo-grid-all-users/")); + } + } + [TestMethod] public async Task EnsureUserTest() { @@ -1974,7 +1988,7 @@ public async Task DisablesAccessReviewOnWeb() { await context.Web.SetAccessRequestAsync(AccessRequestOption.Disabled); - context.Web.Load(p=> p.UseAccessRequestDefault, p=> p.RequestAccessEmail); + context.Web.Load(p => p.UseAccessRequestDefault, p => p.RequestAccessEmail); await context.ExecuteAsync(); Assert.IsFalse(context.Web.UseAccessRequestDefault); @@ -2211,7 +2225,7 @@ public async Task CheckIfUserHasPermissionsExceptionAsyncTest() #endregion #region Reindex tests - + [TestMethod] public async Task ReIndexNoScriptSiteTest() { diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Internal/Web.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Internal/Web.cs index 4dcc1c77a3..383345e877 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Internal/Web.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Internal/Web.cs @@ -726,6 +726,54 @@ public bool IsNoScriptSite() #endregion #region Users + + private async Task GetTenantIdAsync() + { + // in case telemetry is configured, return the tenant id from the globaloptions + if (this.PnPContext.GlobalOptions.AADTenantId != Guid.Empty) + return this.PnPContext.GlobalOptions.AADTenantId; + + await EnsurePropertiesAsync(p => p.Url).ConfigureAwait(false); + WebRequest request = WebRequest.Create(this.Url + "/_vti_bin/client.svc"); + request.Headers.Add("Authorization: Bearer "); + + try + { + await request.GetResponseAsync().ConfigureAwait(false); + } + catch (WebException e) + { + var bearerResponseHeader = e.Response.Headers["WWW-Authenticate"]; + + const string bearer = "Bearer realm=\""; + var bearerIndex = bearerResponseHeader.IndexOf(bearer, StringComparison.Ordinal); + + var realmIndex = bearerIndex + bearer.Length; + + if (bearerResponseHeader.Length >= realmIndex + 36) + { + if (Guid.TryParse(bearerResponseHeader.Substring(realmIndex, 36), out Guid realmGuid)) + { + return realmGuid; + } + } + } + return Guid.Empty; + } + + + public ISharePointUser GetEveryoneExceptExternalUsers() + { + return GetEveryoneExceptExternalUsersAsync().GetAwaiter().GetResult(); + } + + public async Task GetEveryoneExceptExternalUsersAsync() + { + var tenantId = await this.GetTenantIdAsync().ConfigureAwait(false); + var loginName = $"c:0-.f|rolemanager|spo-grid-all-users/{tenantId}"; + return await this.EnsureUserAsync(loginName).ConfigureAwait(false); + } + public ISharePointUser EnsureUser(string userPrincipalName) { return EnsureUserAsync(userPrincipalName).GetAwaiter().GetResult(); @@ -952,7 +1000,7 @@ public async Task> ValidateUsersAsync(IList userList) List> requests = new(); var batch = PnPContext.NewBatch(); - foreach(var user in userList) + foreach (var user in userList) { requests.Add(Tuple.Create(user, await RawRequestBatchAsync(batch, new ApiCall($"users/{user}", ApiType.Graph), HttpMethod.Get, "GetUser").ConfigureAwait(false))); } @@ -965,7 +1013,7 @@ public async Task> ValidateUsersAsync(IList userList) nonExistingUsers.Add(request.Item1); } } - + return nonExistingUsers; } @@ -979,7 +1027,7 @@ public async Task> ValidateAndEnsureUsersAsync(IList ensuredUsers = new(); - + var batch = PnPContext.NewBatch(); foreach (var user in userList) { @@ -1180,13 +1228,13 @@ public async Task SetAccessRequestAsync(AccessRequestOption operation, string em { targetMail = ""; } - + // Build body var useAccessRequest = new { useAccessRequestDefault = operation == AccessRequestOption.Enabled ? "true" : "false" }.AsExpando(); - + string useAccessRequestBody = JsonSerializer.Serialize(useAccessRequest, typeof(ExpandoObject), PnPConstants.JsonSerializer_IgnoreNullValues); var setUseAccessRequestDefaultAndUpdateRequest = new ApiCall($"_api/web/setUseaccessrequestdefaultandupdate", ApiType.SPORest, useAccessRequestBody); await RawRequestAsync(setUseAccessRequestDefaultAndUpdateRequest, HttpMethod.Post).ConfigureAwait(false); @@ -1196,7 +1244,7 @@ public async Task SetAccessRequestAsync(AccessRequestOption operation, string em __metadata = new { type = "SP.Web" }, RequestAccessEmail = targetMail }.AsExpando(); - + string updateRequestAccessMailBody = JsonSerializer.Serialize(updateRequestAccessMail, typeof(ExpandoObject), PnPConstants.JsonSerializer_IgnoreNullValues); var updateRequestAccessMailRequest = new ApiCall($"_api/web", ApiType.SPORest, updateRequestAccessMailBody); await RawRequestAsync(updateRequestAccessMailRequest, new HttpMethod("PATCH")).ConfigureAwait(false); diff --git a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs index 38bf2c2d37..9a3b18998b 100644 --- a/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs +++ b/src/sdk/PnP.Core/Model/SharePoint/Core/Public/IWeb.cs @@ -891,6 +891,18 @@ public interface IWeb : IDataModel, IDataModelGet, IDataModelLoad + /// Retrieves everyone except external users and ensures the user in the current web + /// + /// The ensured + public Task GetEveryoneExceptExternalUsersAsync(); + + /// + /// Retrieves everyone except external users and ensures the user in the current web + /// + /// The ensured + public ISharePointUser GetEveryoneExceptExternalUsers(); + /// /// Ensures the given users exists ///