Skip to content

Commit

Permalink
Merge branch 'feature/tokenparser-optimizations' of https://github.co…
Browse files Browse the repository at this point in the history
  • Loading branch information
jansenbe committed Apr 11, 2024
2 parents ee8ac48 + cd0b171 commit 3b951f1
Show file tree
Hide file tree
Showing 9 changed files with 788 additions and 594 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.35.0" />
</ItemGroup>

<ItemGroup>
Expand Down
89 changes: 51 additions & 38 deletions src/lib/PnP.Framework/Extensions/ClientContextExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
using PnP.Framework;
using PnP.Framework.Diagnostics;
using PnP.Framework.Http;
using PnP.Framework.Provisioning.ObjectHandlers;
using PnP.Framework.Sites;
using PnP.Framework.Utilities;
using PnP.Framework.Utilities.Async;
using PnP.Framework.Utilities.Context;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
Expand All @@ -21,6 +12,14 @@
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using PnP.Framework;
using PnP.Framework.Diagnostics;
using PnP.Framework.Http;
using PnP.Framework.Provisioning.ObjectHandlers;
using PnP.Framework.Sites;
using PnP.Framework.Utilities;
using PnP.Framework.Utilities.Async;
using PnP.Framework.Utilities.Context;

namespace Microsoft.SharePoint.Client
{
Expand All @@ -29,10 +28,11 @@ namespace Microsoft.SharePoint.Client
/// </summary>
public static partial class ClientContextExtensions
{
private static readonly string userAgentFromConfig = null;
private static readonly string UserAgentFromConfig;
private static readonly Lazy<PropertyInfo> PendingRequestActionsProperty = new Lazy<PropertyInfo>(GetPendingRequestActionsProperty);

#pragma warning disable CS0169
private static ConcurrentDictionary<string, (string requestDigest, DateTime expiresOn)> requestDigestInfos = new ConcurrentDictionary<string, (string requestDigest, DateTime expiresOn)>();
private static readonly ConcurrentDictionary<string, (string requestDigest, DateTime expiresOn)> RequestDigestInfos = new ConcurrentDictionary<string, (string requestDigest, DateTime expiresOn)>();
#pragma warning restore CS0169

//private static bool hasAuthCookies;
Expand All @@ -45,15 +45,15 @@ static ClientContextExtensions()
{
try
{
ClientContextExtensions.userAgentFromConfig = ConfigurationManager.AppSettings["SharePointPnPUserAgent"];
UserAgentFromConfig = ConfigurationManager.AppSettings["SharePointPnPUserAgent"];
}
catch // throws exception if being called from a .NET Standard 2.0 application
{

}
if (string.IsNullOrWhiteSpace(ClientContextExtensions.userAgentFromConfig))

if (string.IsNullOrWhiteSpace(UserAgentFromConfig))
{
ClientContextExtensions.userAgentFromConfig = Environment.GetEnvironmentVariable("SharePointPnPUserAgent", EnvironmentVariableTarget.Process);
UserAgentFromConfig = Environment.GetEnvironmentVariable("SharePointPnPUserAgent", EnvironmentVariableTarget.Process);
}
}
#pragma warning restore CA1810
Expand Down Expand Up @@ -303,9 +303,9 @@ private static EventHandler<WebRequestEventArgs> AttachRequestUserAgent(string c
}
if (overrideUserAgent)
{
if (string.IsNullOrEmpty(customUserAgent) && !string.IsNullOrEmpty(ClientContextExtensions.userAgentFromConfig))
if (string.IsNullOrEmpty(customUserAgent) && !string.IsNullOrEmpty(UserAgentFromConfig))
{
customUserAgent = userAgentFromConfig;
customUserAgent = UserAgentFromConfig;
}
e.WebRequestExecutor.WebRequest.UserAgent = string.IsNullOrEmpty(customUserAgent) ? $"{PnPCoreUtilities.PnPCoreUserAgent}" : customUserAgent;
}
Expand Down Expand Up @@ -524,24 +524,32 @@ internal static ClientContext Clone(this ClientRuntimeContext clientContext, Cli
/// </summary>
/// <param name="clientContext">Client context to check the pending requests for</param>
/// <returns>The number of pending requests</returns>
/// <exception cref="NotSupportedException">The currently loaded version of CSOM is not supported.</exception>
public static int PendingRequestCount(this ClientRuntimeContext clientContext)
{
int count = 0;
if (!clientContext.HasPendingRequest)
{
return 0;
}

if (clientContext.HasPendingRequest)
PropertyInfo property = PendingRequestActionsProperty.Value;
if (property == null)
{
var result = clientContext.PendingRequest.GetType().GetProperty("Actions", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic);
if (result != null)
{
var propValue = result.GetValue(clientContext.PendingRequest);
if (propValue != null)
{
count = (propValue as List<ClientAction>).Count;
}
}
return 0;
}

return count;
object rawValue = property.GetValue(clientContext.PendingRequest);
switch (rawValue)
{
case ICollection<ClientAction> actions:
return actions.Count;

case null:
return 0;

default:
throw new NotSupportedException("The currently loaded version of CSOM is not supported.");
}
}

/// <summary>
Expand Down Expand Up @@ -789,20 +797,20 @@ public static async Task<string> GetRequestDigestAsync(this ClientContext contex
if (cookieContainer != null)
{
var hostUrl = context.Url;
if (requestDigestInfos.TryGetValue(hostUrl, out (string digestToken, DateTime expiresOn) requestDigestInfo))
if (RequestDigestInfos.TryGetValue(hostUrl, out (string digestToken, DateTime expiresOn) requestDigestInfo))
{
// We only have to add a request digest when running in dotnet core
if (DateTime.Now > requestDigestInfo.expiresOn)
{
requestDigestInfo = await GetRequestDigestInfoAsync(hostUrl, cookieContainer);
requestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
RequestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
}
}
else
{
// admin url maybe?
requestDigestInfo = await GetRequestDigestInfoAsync(hostUrl, cookieContainer);
requestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
RequestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
}
return requestDigestInfo.digestToken;
}
Expand Down Expand Up @@ -862,20 +870,20 @@ public static async Task<string> GetRequestDigestAsync(this ClientContext contex
public static async Task<string> GetRequestDigestAsync(this ClientContext context)
{
var hostUrl = context.Url;
if (requestDigestInfos.TryGetValue(hostUrl, out (string digestToken, DateTime expiresOn) requestDigestInfo))
if (RequestDigestInfos.TryGetValue(hostUrl, out (string digestToken, DateTime expiresOn) requestDigestInfo))
{
// We only have to add a request digest when running in dotnet core
if (DateTime.Now > requestDigestInfo.expiresOn)
{
requestDigestInfo = await GetRequestDigestInfoAsync(context);
requestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
RequestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
}
}
else
{
// admin url maybe?
requestDigestInfo = await GetRequestDigestInfoAsync(context);
requestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
RequestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
}
return requestDigestInfo.digestToken;
}
Expand Down Expand Up @@ -938,20 +946,20 @@ public static async Task<string> GetRequestDigestAsync(this ClientContext contex
internal static async Task<string> GetOnPremisesRequestDigestAsync(this ClientContext context)
{
var hostUrl = context.Url;
if (requestDigestInfos.TryGetValue(hostUrl, out (string digestToken, DateTime expiresOn) requestDigestInfo))
if (RequestDigestInfos.TryGetValue(hostUrl, out (string digestToken, DateTime expiresOn) requestDigestInfo))
{
// We only have to add a request digest when running in dotnet core
if (DateTime.Now > requestDigestInfo.expiresOn)
{
requestDigestInfo = await GetOnPremisesRequestDigestInfoAsync(context);
requestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
RequestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
}
}
else
{
// admin url maybe?
requestDigestInfo = await GetOnPremisesRequestDigestInfoAsync(context);
requestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
RequestDigestInfos.AddOrUpdate(hostUrl, requestDigestInfo, (key, oldValue) => requestDigestInfo);
}
return requestDigestInfo.digestToken;
}
Expand Down Expand Up @@ -1187,5 +1195,10 @@ internal static CookieContainer GetAuthenticationCookies(this ClientContext cont
}
return authCookiesContainer;
}

private static PropertyInfo GetPendingRequestActionsProperty()
{
return typeof(ClientRequest).GetProperty("Actions", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ public override TokenParser ProvisionObjects(Web web, ProvisioningTemplate templ
}
}

IEnumerable<AssociatedGroupToken> associatedGroupTokens = parser.Tokens.Where(t => t.GetType() == typeof(AssociatedGroupToken)).Cast<AssociatedGroupToken>();
IEnumerable<AssociatedGroupToken> associatedGroupTokens = parser.Tokens.OfType<AssociatedGroupToken>();
foreach (AssociatedGroupToken associatedGroupToken in associatedGroupTokens)
{
associatedGroupToken.ClearCache();
Expand Down
Loading

0 comments on commit 3b951f1

Please sign in to comment.