Skip to content

Commit

Permalink
fix: old IDE support (#268)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShawkyZ authored May 31, 2024
1 parent 179e6bf commit ea39cf4
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 185 deletions.
1 change: 1 addition & 0 deletions Snyk.Code.Library/Snyk.Code.Library.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.Runtime.Caching" />
<Reference Include="System.Web" />
Expand Down
135 changes: 68 additions & 67 deletions Snyk.Common/Authentication/AuthenticationToken.cs
Original file line number Diff line number Diff line change
@@ -1,92 +1,93 @@
namespace Snyk.Common.Authentication;
using System;

using System;

public delegate string TokenRefresher();

/// <summary>
/// Util for AuthenticationToken strings.
/// </summary>
public class AuthenticationToken
namespace Snyk.Common.Authentication
{
public static readonly AuthenticationToken EmptyToken = new(AuthenticationType.Token, string.Empty);
public delegate string TokenRefresher();

public TokenRefresher TokenRefresher;
/// <summary>
/// Util for AuthenticationToken strings.
/// </summary>
public class AuthenticationToken
{
public static readonly AuthenticationToken EmptyToken = new(AuthenticationType.Token, string.Empty);

private string value;
public TokenRefresher TokenRefresher;

public AuthenticationToken(AuthenticationType type, string value)
{
this.value = value;
Type = type;
this.TokenRefresher = null;
}
private string value;

public AuthenticationType Type { get; }
public AuthenticationToken(AuthenticationType type, string value)
{
this.value = value;
Type = type;
this.TokenRefresher = null;
}

public override string ToString()
{
// if possible and required, update the token before using it
if (this.TokenRefresher != null && Type == AuthenticationType.OAuth)
public AuthenticationType Type { get; }

public override string ToString()
{
var oauthToken = OAuthToken.FromJson(this.value);
if (oauthToken != null)
// if possible and required, update the token before using it
if (this.TokenRefresher != null && Type == AuthenticationType.OAuth)
{
var expired = oauthToken.IsExpired();
if (expired)
var oauthToken = OAuthToken.FromJson(this.value);
if (oauthToken != null)
{
this.value = this.TokenRefresher();
var expired = oauthToken.IsExpired();
if (expired)
{
this.value = this.TokenRefresher();
}
}
}
}

return this.value;
}

public bool IsValid()
{
if (string.IsNullOrWhiteSpace(this.value))
{
return false;
return this.value;
}

switch (Type)
public bool IsValid()
{
case AuthenticationType.Token:
return Guid.TryParse(this.value, out _);
case AuthenticationType.OAuth:
if (string.IsNullOrWhiteSpace(this.value))
{
var tokenState = GetTokenState(this.value);
if (tokenState == OAuthTokenState.Expired)
{
this.value = this.TokenRefresher();
tokenState = GetTokenState(this.value);
}
return false;
}

switch (Type)
{
case AuthenticationType.Token:
return Guid.TryParse(this.value, out _);
case AuthenticationType.OAuth:
{
var tokenState = GetTokenState(this.value);
if (tokenState == OAuthTokenState.Expired)
{
this.value = this.TokenRefresher();
tokenState = GetTokenState(this.value);
}

return tokenState == OAuthTokenState.Valid;
return tokenState == OAuthTokenState.Valid;
}
default:
throw new ArgumentOutOfRangeException();
}
default:
throw new ArgumentOutOfRangeException();
}
}

private static OAuthTokenState GetTokenState(string value)
{
var oauthToken = OAuthToken.FromJson(value);
var expired = oauthToken?.IsExpired() == true;

return (oauthToken, expired) switch
private static OAuthTokenState GetTokenState(string value)
{
(null, _) => OAuthTokenState.Invalid,
(_, true) => OAuthTokenState.Expired,
(_, false) => OAuthTokenState.Valid
};
}
var oauthToken = OAuthToken.FromJson(value);
var expired = oauthToken?.IsExpired() == true;

private enum OAuthTokenState
{
Invalid,
Expired,
Valid
return (oauthToken, expired) switch
{
(null, _) => OAuthTokenState.Invalid,
(_, true) => OAuthTokenState.Expired,
(_, false) => OAuthTokenState.Valid
};
}

private enum OAuthTokenState
{
Invalid,
Expired,
Valid
}
}
}
59 changes: 28 additions & 31 deletions Snyk.Common/Authentication/OAuthToken.cs
Original file line number Diff line number Diff line change
@@ -1,43 +1,40 @@
namespace Snyk.Common.Authentication;

using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;

public class OAuthToken
namespace Snyk.Common.Authentication
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; }

[JsonPropertyName("token_type")]
public string TokenType { get; set; }
[JsonObject(NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
public class OAuthToken
{
public string AccessToken { get; set; }

[JsonPropertyName("refresh_token")]
public string RefreshToken { get; set; }
public string TokenType { get; set; }

[JsonPropertyName("expiry")]
public string Expiry { get; set; }
public string RefreshToken { get; set; }

public static OAuthToken FromJson(string token)
{
OAuthToken result = null;
public string Expiry { get; set; }

try
public static OAuthToken FromJson(string token)
{
result = JsonSerializer.Deserialize<OAuthToken>(token);
OAuthToken result = null;

try
{
result = JsonConvert.DeserializeObject<OAuthToken>(token);
}
catch (Exception)
{
// nothing
}

return result;
}
catch (Exception)

public bool IsExpired()
{
// nothing
var expiryDate = DateTime.Parse(Expiry).ToUniversalTime();
expiryDate = expiryDate.AddSeconds(10);
return expiryDate < DateTime.UtcNow;
}

return result;
}

public bool IsExpired()
{
var expiryDate = DateTime.Parse(Expiry).ToUniversalTime();
expiryDate = expiryDate.AddSeconds(10);
return expiryDate < DateTime.UtcNow;
}
}
92 changes: 46 additions & 46 deletions Snyk.Common/HttpClientFactory.cs
Original file line number Diff line number Diff line change
@@ -1,70 +1,70 @@
namespace Snyk.Common;

using System;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using global::Sentry;
using Snyk.Common.Authentication;

/// <summary>
/// Factory for <see cref="HttpClient"/>.
/// </summary>
public static class HttpClientFactory
namespace Snyk.Common
{
/// <summary>
/// Create new <see cref="HttpClient"/> by base URL and API token.
/// Factory for <see cref="HttpClient"/>.
/// </summary>
/// <param name="token">User API token.</param>
/// <param name="baseUrl">Base URL.</param>
/// <returns>New HttpClient instance.</returns>
public static HttpClient NewHttpClient(AuthenticationToken token, string baseUrl = null)
public static class HttpClientFactory
{
var httpClient = new HttpClient(new HttpClientHandler
/// <summary>
/// Create new <see cref="HttpClient"/> by base URL and API token.
/// </summary>
/// <param name="token">User API token.</param>
/// <param name="baseUrl">Base URL.</param>
/// <returns>New HttpClient instance.</returns>
public static HttpClient NewHttpClient(AuthenticationToken token, string baseUrl = null)
{
AutomaticDecompression = DecompressionMethods.GZip
});
var httpClient = new HttpClient(new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip
});

httpClient.DefaultRequestHeaders.ExpectContinue = false;
httpClient.DefaultRequestHeaders.ExpectContinue = false;

httpClient.Timeout = TimeSpan.FromMinutes(30);
httpClient.Timeout = TimeSpan.FromMinutes(30);

if (!string.IsNullOrEmpty(baseUrl))
{
httpClient.BaseAddress = new Uri(baseUrl);
}
if (!string.IsNullOrEmpty(baseUrl))
{
httpClient.BaseAddress = new Uri(baseUrl);
}

var authorizationString = "token " + token;
if (token.Type == AuthenticationType.OAuth)
{
var rawToken = token.ToString();
var oauthToken = OAuthToken.FromJson(rawToken);
var accessToken = oauthToken?.AccessToken;
authorizationString = "bearer " + accessToken;
}

httpClient.DefaultRequestHeaders.Add("Authorization", authorizationString);
var authorizationString = "token " + token;
if (token.Type == AuthenticationType.OAuth)
{
var rawToken = token.ToString();
var oauthToken = OAuthToken.FromJson(rawToken);
var accessToken = oauthToken?.AccessToken;
authorizationString = "bearer " + accessToken;
}

httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
httpClient.DefaultRequestHeaders.Add("Authorization", authorizationString);

return httpClient;
}
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));

public static HttpClient WithUserAgent(this HttpClient httpClient, string ideVersion, string pluginVersionString)
{
if (string.IsNullOrEmpty(ideVersion) || string.IsNullOrEmpty(pluginVersionString))
{
return httpClient;
}

var os = RuntimeInformation.OSDescription;
var arch = RuntimeInformation.ProcessArchitecture.ToString();

var header = $"VISUAL_STUDIO/{ideVersion} ({os};{arch}) VISUAL_STUDIO/{pluginVersionString} (VISUAL_STUDIO/{ideVersion})";
public static HttpClient WithUserAgent(this HttpClient httpClient, string ideVersion, string pluginVersionString)
{
if (string.IsNullOrEmpty(ideVersion) || string.IsNullOrEmpty(pluginVersionString))
{
return httpClient;
}

var os = RuntimeInformation.OSDescription;
var arch = RuntimeInformation.ProcessArchitecture.ToString();

httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(header);
return httpClient;
var header = $"VISUAL_STUDIO/{ideVersion} ({os};{arch}) VISUAL_STUDIO/{pluginVersionString} (VISUAL_STUDIO/{ideVersion})";

httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(header);
return httpClient;
}
}
}
7 changes: 1 addition & 6 deletions Snyk.Common/Snyk.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Numerics" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
Expand Down Expand Up @@ -132,12 +133,6 @@
<PackageReference Include="SerilogAnalyzer">
<Version>0.15.0</Version>
</PackageReference>
<PackageReference Include="System.Net.Http">
<Version>4.3.4</Version>
</PackageReference>
<PackageReference Include="System.Text.Json">
<Version>8.0.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
Loading

0 comments on commit ea39cf4

Please sign in to comment.