diff --git a/src/Sdk/Common/Common/Authentication/FederatedCredential.cs b/src/Sdk/Common/Common/Authentication/FederatedCredential.cs deleted file mode 100644 index 2a03c63bb..000000000 --- a/src/Sdk/Common/Common/Authentication/FederatedCredential.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// Provides a common implementation for federated credentials. - /// - [Serializable] - public abstract class FederatedCredential : IssuedTokenCredential - { - protected FederatedCredential(IssuedToken initialToken) - : base(initialToken) - { - } - - public override bool IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (webResponse == null) - { - return false; - } - - if (webResponse.StatusCode == HttpStatusCode.Found || - webResponse.StatusCode == HttpStatusCode.Redirect) - { - return webResponse.Headers.GetValues(HttpHeaders.TfsFedAuthRealm).Any(); - } - - return webResponse.StatusCode == HttpStatusCode.Unauthorized; - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/HttpRequestMessageWrapper.cs b/src/Sdk/Common/Common/Authentication/HttpRequestMessageWrapper.cs deleted file mode 100644 index ea0a25313..000000000 --- a/src/Sdk/Common/Common/Authentication/HttpRequestMessageWrapper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; - -namespace GitHub.Services.Common -{ - internal struct HttpRequestMessageWrapper : IHttpRequest, IHttpHeaders - { - public HttpRequestMessageWrapper(HttpRequestMessage request) - { - m_request = request; - } - - public IHttpHeaders Headers - { - get - { - return this; - } - } - - public Uri RequestUri - { - get - { - return m_request.RequestUri; - } - } - - public IDictionary Properties - { - get - { - return m_request.Properties; - } - } - - IEnumerable IHttpHeaders.GetValues(String name) - { - IEnumerable values; - if (!m_request.Headers.TryGetValues(name, out values)) - { - values = Enumerable.Empty(); - } - return values; - } - - void IHttpHeaders.SetValue( - String name, - String value) - { - m_request.Headers.Remove(name); - m_request.Headers.Add(name, value); - } - - Boolean IHttpHeaders.TryGetValues( - String name, - out IEnumerable values) - { - return m_request.Headers.TryGetValues(name, out values); - } - - private readonly HttpRequestMessage m_request; - } -} diff --git a/src/Sdk/Common/Common/Authentication/HttpResponseMessageWrapper.cs b/src/Sdk/Common/Common/Authentication/HttpResponseMessageWrapper.cs deleted file mode 100644 index 18e03b5b8..000000000 --- a/src/Sdk/Common/Common/Authentication/HttpResponseMessageWrapper.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; - -namespace GitHub.Services.Common -{ - internal struct HttpResponseMessageWrapper : IHttpResponse, IHttpHeaders - { - public HttpResponseMessageWrapper(HttpResponseMessage response) - { - m_response = response; - } - - public IHttpHeaders Headers - { - get - { - return this; - } - } - - public HttpStatusCode StatusCode - { - get - { - return m_response.StatusCode; - } - } - - IEnumerable IHttpHeaders.GetValues(String name) - { - IEnumerable values; - if (!m_response.Headers.TryGetValues(name, out values)) - { - values = Enumerable.Empty(); - } - return values; - } - - void IHttpHeaders.SetValue( - String name, - String value) - { - throw new NotSupportedException(); - } - - Boolean IHttpHeaders.TryGetValues( - String name, - out IEnumerable values) - { - return m_response.Headers.TryGetValues(name, out values); - } - - private readonly HttpResponseMessage m_response; - } -} diff --git a/src/Sdk/Common/Common/Authentication/IHttpHeaders.cs b/src/Sdk/Common/Common/Authentication/IHttpHeaders.cs deleted file mode 100644 index 8147c75fe..000000000 --- a/src/Sdk/Common/Common/Authentication/IHttpHeaders.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.Common -{ - public interface IHttpHeaders - { - IEnumerable GetValues(String name); - - void SetValue(String name, String value); - - Boolean TryGetValues(String name, out IEnumerable values); - } -} diff --git a/src/Sdk/Common/Common/Authentication/IHttpRequest.cs b/src/Sdk/Common/Common/Authentication/IHttpRequest.cs deleted file mode 100644 index 802d7275d..000000000 --- a/src/Sdk/Common/Common/Authentication/IHttpRequest.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.Common -{ - public interface IHttpRequest - { - IHttpHeaders Headers - { - get; - } - - Uri RequestUri - { - get; - } - - IDictionary Properties - { - get; - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/IHttpResponse.cs b/src/Sdk/Common/Common/Authentication/IHttpResponse.cs deleted file mode 100644 index 7bae00863..000000000 --- a/src/Sdk/Common/Common/Authentication/IHttpResponse.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Net; - -namespace GitHub.Services.Common -{ - public interface IHttpResponse - { - IHttpHeaders Headers - { - get; - } - - HttpStatusCode StatusCode - { - get; - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/IVssCredentialPrompt.cs b/src/Sdk/Common/Common/Authentication/IVssCredentialPrompt.cs deleted file mode 100644 index e93992250..000000000 --- a/src/Sdk/Common/Common/Authentication/IVssCredentialPrompt.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - /// - /// Provide an interface to get a new token for the credentials. - /// - public interface IVssCredentialPrompt - { - /// - /// Get a new token using the specified provider and the previously failed token. - /// - /// The provider for the token to be retrieved - /// The token which previously failed authentication, if available - /// The new token - Task GetTokenAsync(IssuedTokenProvider provider, IssuedToken failedToken); - - IDictionary Parameters { get; set; } - } - - public interface IVssCredentialPrompts : IVssCredentialPrompt - { - IVssCredentialPrompt FederatedPrompt - { - get; - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/IVssCredentialStorage.cs b/src/Sdk/Common/Common/Authentication/IVssCredentialStorage.cs deleted file mode 100644 index 7a1094637..000000000 --- a/src/Sdk/Common/Common/Authentication/IVssCredentialStorage.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace GitHub.Services.Common -{ - public interface IVssCredentialStorage - { - IssuedToken RetrieveToken( - Uri serverUrl, - VssCredentialsType credentialsType); - - void StoreToken( - Uri serverUrl, - IssuedToken token); - - void RemoveToken( - Uri serverUrl, - IssuedToken token); - - bool RemoveTokenValue( - Uri serverUrl, - IssuedToken token); - } -} diff --git a/src/Sdk/Common/Common/Authentication/IssuedToken.cs b/src/Sdk/Common/Common/Authentication/IssuedToken.cs deleted file mode 100644 index 23aa71676..000000000 --- a/src/Sdk/Common/Common/Authentication/IssuedToken.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// Provides a common base class for issued tokens. - /// - [Serializable] - public abstract class IssuedToken - { - internal IssuedToken() - { - } - - /// - /// Gets a value indicating whether or not this token has been successfully authenticated with the remote - /// server. - /// - public bool IsAuthenticated - { - get - { - return m_authenticated == 1; - } - } - - protected internal abstract VssCredentialsType CredentialType - { - get; - } - - /// - /// True if the token is retrieved from token storage. - /// - internal bool FromStorage - { - get; - set; - } - - /// - /// Metadata about the token in a collection of properties. - /// - /// - public IDictionary Properties - { - get; - set; - } - - /// - /// Id of the owner of the token. - /// - internal Guid UserId - { - get; - set; - } - - /// - /// Name of the owner of the token. - /// - internal string UserName - { - get; - set; - } - - /// - /// Invoked when the issued token has been validated by successfully authenticated with the remote server. - /// - internal bool Authenticated() - { - return Interlocked.CompareExchange(ref m_authenticated, 1, 0) == 0; - } - - /// - /// Get the value of the HttpHeaders.VssUserData response header and - /// populate the UserId and UserName properties. - /// - internal void GetUserData(IHttpResponse response) - { - IEnumerable headerValues; - if (response.Headers.TryGetValues(HttpHeaders.VssUserData, out headerValues)) - { - string userData = headerValues.FirstOrDefault(); - - if (!string.IsNullOrWhiteSpace(userData)) - { - string[] split = userData.Split(':'); - - if (split.Length >= 2) - { - UserId = Guid.Parse(split[0]); - UserName = split[1]; - } - } - } - } - - /// - /// Applies the token to the HTTP request message. - /// - /// The HTTP request message - internal abstract void ApplyTo(IHttpRequest request); - - private int m_authenticated; - } -} diff --git a/src/Sdk/Common/Common/Authentication/IssuedTokenCredential.cs b/src/Sdk/Common/Common/Authentication/IssuedTokenCredential.cs deleted file mode 100644 index 1bed7d720..000000000 --- a/src/Sdk/Common/Common/Authentication/IssuedTokenCredential.cs +++ /dev/null @@ -1,148 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - /// - /// Provides a common base class for issued token credentials. - /// - [Serializable] - public abstract class IssuedTokenCredential - { - protected IssuedTokenCredential(IssuedToken initialToken) - { - InitialToken = initialToken; - } - - public abstract VssCredentialsType CredentialType - { - get; - } - - /// - /// The initial token to use to authenticate if available. - /// - internal IssuedToken InitialToken - { - get; - set; - } - - /// - /// Gets or sets the synchronization context which should be used for UI prompts. - /// - internal TaskScheduler Scheduler - { - get - { - return m_scheduler; - } - set - { - m_scheduler = value; - } - } - - /// - /// The credentials prompt which is used for retrieving a new token. - /// - internal IVssCredentialPrompt Prompt - { - get - { - return m_prompt; - } - set - { - m_prompt = value; - } - } - - internal IVssCredentialStorage Storage - { - get - { - return m_storage; - } - set - { - m_storage = value; - } - } - - /// - /// The base url for the vssconnection to be used in the token storage key. - /// - internal Uri TokenStorageUrl { get; set; } - - /// - /// Creates a token provider suitable for handling the challenge presented in the response. - /// - /// The targeted server - /// The challenge response - /// The failed token - /// An issued token provider instance - internal IssuedTokenProvider CreateTokenProvider( - Uri serverUrl, - IHttpResponse response, - IssuedToken failedToken) - { - if (response != null && !IsAuthenticationChallenge(response)) - { - throw new InvalidOperationException(); - } - - if (InitialToken == null && Storage != null) - { - if (TokenStorageUrl == null) - { - throw new InvalidOperationException($"The {nameof(TokenStorageUrl)} property must have a value if the {nameof(Storage)} property is set on this instance of {GetType().Name}."); - } - InitialToken = Storage.RetrieveToken(TokenStorageUrl, CredentialType); - } - - IssuedTokenProvider provider = OnCreateTokenProvider(serverUrl, response); - if (provider != null) - { - provider.TokenStorageUrl = TokenStorageUrl; - } - - // If the initial token is the one which failed to authenticate, don't - // use it again and let the token provider get a new token. - if (provider != null) - { - if (InitialToken != null && !Object.ReferenceEquals(InitialToken, failedToken)) - { - provider.CurrentToken = InitialToken; - } - } - - return provider; - } - - internal virtual string GetAuthenticationChallenge(IHttpResponse webResponse) - { - IEnumerable values; - if (!webResponse.Headers.TryGetValues(Internal.HttpHeaders.WwwAuthenticate, out values)) - { - return String.Empty; - } - - return String.Join(", ", values); - } - - public abstract bool IsAuthenticationChallenge(IHttpResponse webResponse); - - protected abstract IssuedTokenProvider OnCreateTokenProvider(Uri serverUrl, IHttpResponse response); - - [NonSerialized] - private TaskScheduler m_scheduler; - - [NonSerialized] - private IVssCredentialPrompt m_prompt; - - [NonSerialized] - private IVssCredentialStorage m_storage; - } -} diff --git a/src/Sdk/Common/Common/Authentication/IssuedTokenProvider.cs b/src/Sdk/Common/Common/Authentication/IssuedTokenProvider.cs deleted file mode 100644 index 550bbcb5c..000000000 --- a/src/Sdk/Common/Common/Authentication/IssuedTokenProvider.cs +++ /dev/null @@ -1,545 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common.Diagnostics; - -namespace GitHub.Services.Common -{ - internal interface ISupportSignOut - { - void SignOut(Uri serverUrl, Uri replyToUrl, string identityProvider); - } - - /// - /// Provides a common base class for providers of the token authentication model. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public abstract class IssuedTokenProvider - { - private const double c_slowTokenAcquisitionTimeInSeconds = 2.0; - - protected IssuedTokenProvider( - IssuedTokenCredential credential, - Uri serverUrl, - Uri signInUrl) - { - ArgumentUtility.CheckForNull(credential, "credential"); - - this.SignInUrl = signInUrl; - this.Credential = credential; - this.ServerUrl = serverUrl; - - m_thisLock = new object(); - } - - /// - /// Gets the authentication scheme used to create this token provider. - /// - protected virtual String AuthenticationScheme - { - get - { - return String.Empty; - } - } - - /// - /// Gets the authentication parameter or parameters used to create this token provider. - /// - protected virtual String AuthenticationParameter - { - get - { - return String.Empty; - } - } - - /// - /// Gets the credential associated with the provider. - /// - protected internal IssuedTokenCredential Credential - { - get; - } - - internal VssCredentialsType CredentialType => this.Credential.CredentialType; - - /// - /// Gets the current token. - /// - public IssuedToken CurrentToken - { - get; - internal set; - } - - /// - /// Gets a value indicating whether or not a call to get token will require interactivity. - /// - public abstract bool GetTokenIsInteractive - { - get; - } - - /// - /// Gets a value indicating whether or not an ISynchronizeInvoke call is required. - /// - private Boolean InvokeRequired - { - get - { - return this.GetTokenIsInteractive && this.Credential.Scheduler != null; - } - } - - /// - /// Gets the sign-in URL for the token provider. - /// - public Uri SignInUrl { get; private set; } - - protected Uri ServerUrl { get; } - - /// - /// The base url for the vssconnection to be used in the token storage key. - /// - internal Uri TokenStorageUrl { get; set; } - - /// - /// Determines whether the specified web response is an authentication challenge. - /// - /// The web response - /// True if the web response is a challenge for token authentication; otherwise, false - protected internal virtual bool IsAuthenticationChallenge(IHttpResponse webResponse) - { - return this.Credential.IsAuthenticationChallenge(webResponse); - } - - /// - /// Formats the authentication challenge string which this token provider handles. - /// - /// A string representing the handled authentication challenge - internal string GetAuthenticationParameters() - { - if (string.IsNullOrEmpty(this.AuthenticationParameter)) - { - return this.AuthenticationScheme; - } - else - { - return string.Format(CultureInfo.InvariantCulture, this.AuthenticationScheme, this.AuthenticationParameter); - } - } - - /// - /// Validates the current token if the provided reference is the current token and it - /// has not been validated before. - /// - /// The token which should be validated - /// The web response which used the token - internal void ValidateToken( - IssuedToken token, - IHttpResponse webResponse) - { - if (token == null) - { - return; - } - - lock (m_thisLock) - { - IssuedToken tokenToValidate = OnValidatingToken(token, webResponse); - - if (tokenToValidate.IsAuthenticated) - { - return; - } - - try - { - // Perform validation which may include matching user information from the response - // with that from the stored connection. If user information mismatch, an exception - // will be thrown and the token will not be authenticated, which means if the same - // token is ever used again in a different request it will be revalidated and fail. - tokenToValidate.GetUserData(webResponse); - OnTokenValidated(tokenToValidate); - - // Set the token to be authenticated. - tokenToValidate.Authenticated(); - } - finally - { - // When the token fails validation, we null its reference from the token provider so it - // would not be used again by the consumers of both. Note that we only update the current - // token of the provider if it is the original token being validated, because we do not - // want to overwrite a different token. - if (object.ReferenceEquals(this.CurrentToken, token)) - { - this.CurrentToken = tokenToValidate.IsAuthenticated ? tokenToValidate : null; - } - } - } - } - - /// - /// Invalidates the current token if the provided reference is the current token. - /// - /// The token reference which should be invalidated - internal void InvalidateToken(IssuedToken token) - { - bool invalidated = false; - lock (m_thisLock) - { - if (token != null && object.ReferenceEquals(this.CurrentToken, token)) - { - this.CurrentToken = null; - invalidated = true; - } - } - - if (invalidated) - { - OnTokenInvalidated(token); - } - } - - /// - /// Retrieves a token for the credentials. - /// - /// The token which previously failed authentication, if available - /// The CancellationTokenthat will be assigned to the new task - /// A security token for the current credentials - public async Task GetTokenAsync( - IssuedToken failedToken, - CancellationToken cancellationToken) - { - IssuedToken currentToken = this.CurrentToken; - VssTraceActivity traceActivity = VssTraceActivity.Current; - Stopwatch aadAuthTokenTimer = Stopwatch.StartNew(); - try - { - VssHttpEventSource.Log.AuthenticationStart(traceActivity); - - if (currentToken != null) - { - VssHttpEventSource.Log.IssuedTokenRetrievedFromCache(traceActivity, this, currentToken); - return currentToken; - } - else - { - GetTokenOperation operation = null; - try - { - GetTokenOperation operationInProgress; - operation = CreateOperation(traceActivity, failedToken, cancellationToken, out operationInProgress); - if (operationInProgress == null) - { - return await operation.GetTokenAsync(traceActivity).ConfigureAwait(false); - } - else - { - return await operationInProgress.WaitForTokenAsync(traceActivity, cancellationToken).ConfigureAwait(false); - } - } - finally - { - lock (m_thisLock) - { - m_operations.Remove(operation); - } - - operation?.Dispose(); - } - } - } - finally - { - VssHttpEventSource.Log.AuthenticationStop(traceActivity); - - aadAuthTokenTimer.Stop(); - TimeSpan getTokenTime = aadAuthTokenTimer.Elapsed; - - if(getTokenTime.TotalSeconds >= c_slowTokenAcquisitionTimeInSeconds) - { - // It may seem strange to pass the string value of TotalSeconds into this method, but testing - // showed that ETW is persnickety when you register a method in an EventSource that doesn't - // use strings or integers as its parameters. It is easier to simply give the method a string - // than figure out to get ETW to reliably accept a double or TimeSpan. - VssHttpEventSource.Log.AuthorizationDelayed(getTokenTime.TotalSeconds.ToString()); - } - } - } - - /// - /// Retrieves a token for the credentials. - /// - /// The token which previously failed authentication, if available - /// The CancellationTokenthat will be assigned to the new task - /// A security token for the current credentials - protected virtual Task OnGetTokenAsync( - IssuedToken failedToken, - CancellationToken cancellationToken) - { - if (this.Credential.Prompt != null) - { - return this.Credential.Prompt.GetTokenAsync(this, failedToken); - } - else - { - return Task.FromResult(null); - } - } - - /// - /// Invoked when the current token is being validated. When overriden in a derived class, - /// validate and return the validated token. - /// - /// Is called inside a lock in ValidateToken - /// The token to validate - /// The web response which used the token - /// The validated token - protected virtual IssuedToken OnValidatingToken( - IssuedToken token, - IHttpResponse webResponse) - { - return token; - } - - protected virtual void OnTokenValidated(IssuedToken token) - { - // Store the validated token to the token storage if it is not originally from there. - if (!token.FromStorage && TokenStorageUrl != null) - { - Credential.Storage?.StoreToken(TokenStorageUrl, token); - } - - VssHttpEventSource.Log.IssuedTokenValidated(VssTraceActivity.Current, this, token); - } - - protected virtual void OnTokenInvalidated(IssuedToken token) - { - if (Credential.Storage != null && TokenStorageUrl != null) - { - Credential.Storage.RemoveTokenValue(TokenStorageUrl, token); - } - - VssHttpEventSource.Log.IssuedTokenInvalidated(VssTraceActivity.Current, this, token); - } - - private GetTokenOperation CreateOperation( - VssTraceActivity traceActivity, - IssuedToken failedToken, - CancellationToken cancellationToken, - out GetTokenOperation operationInProgress) - { - operationInProgress = null; - GetTokenOperation operation = null; - lock (m_thisLock) - { - if (m_operations == null) - { - m_operations = new List(); - } - - // Grab the main operation which is doing the work (if any) - if (m_operations.Count > 0) - { - operationInProgress = m_operations[0]; - - // Use the existing completion source when creating the new operation - operation = new GetTokenOperation(traceActivity, this, failedToken, cancellationToken, operationInProgress.CompletionSource); - } - else - { - operation = new GetTokenOperation(traceActivity, this, failedToken, cancellationToken); - } - - m_operations.Add(operation); - } - - return operation; - } - - private object m_thisLock; - private List m_operations; - - private class DisposableTaskCompletionSource : TaskCompletionSource, IDisposable - { - public DisposableTaskCompletionSource() - { - this.Task.ConfigureAwait(false).GetAwaiter().OnCompleted(() => { m_completed = true; }); - } - - ~DisposableTaskCompletionSource() - { - TraceErrorIfNotCompleted(); - } - - public void Dispose() - { - if (m_disposed) - { - return; - } - - TraceErrorIfNotCompleted(); - - m_disposed = true; - GC.SuppressFinalize(this); - } - - private void TraceErrorIfNotCompleted() - { - if (!m_completed) - { - VssHttpEventSource.Log.TokenSourceNotCompleted(); - } - } - - private Boolean m_disposed; - private Boolean m_completed; - } - - private sealed class GetTokenOperation : IDisposable - { - public GetTokenOperation( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken failedToken, - CancellationToken cancellationToken) - : this(activity, provider, failedToken, cancellationToken, new DisposableTaskCompletionSource(), true) - { - } - - public GetTokenOperation( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken failedToken, - CancellationToken cancellationToken, - DisposableTaskCompletionSource completionSource, - Boolean ownsCompletionSource = false) - { - this.Provider = provider; - this.ActivityId = activity?.Id ?? Guid.Empty; - this.FailedToken = failedToken; - this.CancellationToken = cancellationToken; - this.CompletionSource = completionSource; - this.OwnsCompletionSource = ownsCompletionSource; - } - - public Guid ActivityId { get; } - - public CancellationToken CancellationToken { get; } - - public DisposableTaskCompletionSource CompletionSource { get; } - - public Boolean OwnsCompletionSource { get; } - - private IssuedToken FailedToken { get; } - - private IssuedTokenProvider Provider { get; } - - public void Dispose() - { - if (this.OwnsCompletionSource) - { - this.CompletionSource?.Dispose(); - } - } - - public async Task GetTokenAsync(VssTraceActivity traceActivity) - { - IssuedToken token = null; - try - { - VssHttpEventSource.Log.IssuedTokenAcquiring(traceActivity, this.Provider); - if (this.Provider.InvokeRequired) - { - // Post to the UI thread using the scheduler. This may return a new task object which needs - // to be awaited, since once we get to the UI thread there may be nothing to do if someone else - // preempts us. - - // The cancellation token source is used to handle race conditions between scheduling and - // waiting for the UI task to begin execution. The callback is responsible for disposing of - // the token source, since the thought here is that the callback will run eventually as the - // typical reason for not starting execution within the timeout is due to a deadlock with - // the scheduler being used. - var timerTask = new TaskCompletionSource(); - var timeoutTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(3)); - timeoutTokenSource.Token.Register(() => timerTask.SetResult(null), false); - - var uiTask = Task.Factory.StartNew((state) => PostCallback(state, timeoutTokenSource), - this, - this.CancellationToken, - TaskCreationOptions.None, - this.Provider.Credential.Scheduler).Unwrap(); - - var completedTask = await Task.WhenAny(timerTask.Task, uiTask).ConfigureAwait(false); - if (completedTask == uiTask) - { - token = uiTask.Result; - } - } - else - { - token = await this.Provider.OnGetTokenAsync(this.FailedToken, this.CancellationToken).ConfigureAwait(false); - } - - CompletionSource.TrySetResult(token); - return token; - } - catch (Exception exception) - { - // Mark our completion source as failed so other waiters will get notified in all cases - CompletionSource.TrySetException(exception); - throw; - } - finally - { - this.Provider.CurrentToken = token ?? this.FailedToken; - VssHttpEventSource.Log.IssuedTokenAcquired(traceActivity, this.Provider, token); - } - } - - public async Task WaitForTokenAsync( - VssTraceActivity traceActivity, - CancellationToken cancellationToken) - { - IssuedToken token = null; - try - { - - VssHttpEventSource.Log.IssuedTokenWaitStart(traceActivity, this.Provider, this.ActivityId); - token = await Task.Factory.ContinueWhenAll(new Task[] { CompletionSource.Task }, (x) => CompletionSource.Task.Result, cancellationToken).ConfigureAwait(false); - } - finally - { - VssHttpEventSource.Log.IssuedTokenWaitStop(traceActivity, this.Provider, token); - } - - return token; - } - - private static Task PostCallback( - Object state, - CancellationTokenSource timeoutTokenSource) - { - // Make sure that we were not cancelled (timed out) before this callback is invoked. - using (timeoutTokenSource) - { - timeoutTokenSource.CancelAfter(-1); - if (timeoutTokenSource.IsCancellationRequested) - { - return Task.FromResult(null); - } - } - - GetTokenOperation thisPtr = (GetTokenOperation)state; - return thisPtr.Provider.OnGetTokenAsync(thisPtr.FailedToken, thisPtr.CancellationToken); - } - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssBasicCredential.cs b/src/Sdk/Common/Common/Authentication/VssBasicCredential.cs deleted file mode 100644 index eb984d19f..000000000 --- a/src/Sdk/Common/Common/Authentication/VssBasicCredential.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// Provides a credential for basic authentication against a Visual Studio Service. - /// - public sealed class VssBasicCredential : FederatedCredential - { - /// - /// Initializes a new VssBasicCredential instance with no token specified. - /// - public VssBasicCredential() - : this((VssBasicToken)null) - { - } - - /// - /// Initializes a new VssBasicCredential instance with the specified user name and password. - /// - /// The user name - /// The password - public VssBasicCredential( - string userName, - string password) - : this(new VssBasicToken(new NetworkCredential(userName, password))) - { - } - - /// - /// Initializes a new VssBasicCredential instance with the specified token. - /// - /// An optional token which, if present, should be used before obtaining a new token - public VssBasicCredential(ICredentials initialToken) - : this(new VssBasicToken(initialToken)) - { - } - - /// - /// Initializes a new VssBasicCredential instance with the specified token. - /// - /// An optional token which, if present, should be used before obtaining a new token - public VssBasicCredential(VssBasicToken initialToken) - : base(initialToken) - { - } - - public override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.Basic; - } - } - - public override bool IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (webResponse == null) - { - return false; - } - - if (webResponse.StatusCode != HttpStatusCode.Found && - webResponse.StatusCode != HttpStatusCode.Redirect && - webResponse.StatusCode != HttpStatusCode.Unauthorized) - { - return false; - } - - return webResponse.Headers.GetValues(HttpHeaders.WwwAuthenticate).Any(x => x.StartsWith("Basic", StringComparison.OrdinalIgnoreCase)); - } - - protected override IssuedTokenProvider OnCreateTokenProvider( - Uri serverUrl, - IHttpResponse response) - { - if (serverUrl.Scheme != "https") - { - String unsafeBasicAuthEnv = Environment.GetEnvironmentVariable("VSS_ALLOW_UNSAFE_BASICAUTH") ?? "false"; - if (!Boolean.TryParse(unsafeBasicAuthEnv, out Boolean unsafeBasicAuth) || !unsafeBasicAuth) - { - throw new InvalidOperationException(CommonResources.BasicAuthenticationRequiresSsl()); - } - } - - return new BasicAuthTokenProvider(this, serverUrl); - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssBasicToken.cs b/src/Sdk/Common/Common/Authentication/VssBasicToken.cs deleted file mode 100644 index ce4142bf2..000000000 --- a/src/Sdk/Common/Common/Authentication/VssBasicToken.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Globalization; -using System.Net; - -namespace GitHub.Services.Common -{ - /// - /// Provides a token for basic authentication of internet identities. - /// - public sealed class VssBasicToken : IssuedToken - { - /// - /// Initializes a new BasicAuthToken instance with the specified token value. - /// - /// The credentials which should be used for authentication - public VssBasicToken(ICredentials credentials) - { - m_credentials = credentials; - } - - internal ICredentials Credentials - { - get - { - return m_credentials; - } - } - - protected internal override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.Basic; - } - } - - internal override void ApplyTo(IHttpRequest request) - { - var basicCredential = m_credentials.GetCredential(request.RequestUri, "Basic"); - if (basicCredential != null) - { - request.Headers.SetValue(Internal.HttpHeaders.Authorization, "Basic " + FormatBasicAuthHeader(basicCredential)); - } - } - - private static String FormatBasicAuthHeader(NetworkCredential credential) - { - String authHeader = String.Empty; - if (!String.IsNullOrEmpty(credential.Domain)) - { - authHeader = String.Format(CultureInfo.InvariantCulture, "{0}\\{1}:{2}", credential.Domain, credential.UserName, credential.Password); - } - else - { - authHeader = String.Format(CultureInfo.InvariantCulture, "{0}:{1}", credential.UserName, credential.Password); - } - - return Convert.ToBase64String(VssHttpRequestSettings.Encoding.GetBytes(authHeader)); - } - - private readonly ICredentials m_credentials; - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssBasicTokenProvider.cs b/src/Sdk/Common/Common/Authentication/VssBasicTokenProvider.cs deleted file mode 100644 index 051699965..000000000 --- a/src/Sdk/Common/Common/Authentication/VssBasicTokenProvider.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Net; - -namespace GitHub.Services.Common -{ - internal sealed class BasicAuthTokenProvider : IssuedTokenProvider - { - public BasicAuthTokenProvider( - VssBasicCredential credential, - Uri serverUrl) - : base(credential, serverUrl, serverUrl) - { - } - - protected override String AuthenticationScheme - { - get - { - return "Basic"; - } - } - - public new VssBasicCredential Credential - { - get - { - return (VssBasicCredential)base.Credential; - } - } - - public override Boolean GetTokenIsInteractive - { - get - { - return base.CurrentToken == null; - } - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssCredentials.cs b/src/Sdk/Common/Common/Authentication/VssCredentials.cs deleted file mode 100644 index 92ffd5e5a..000000000 --- a/src/Sdk/Common/Common/Authentication/VssCredentials.cs +++ /dev/null @@ -1,611 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common.Diagnostics; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// The type of credentials supported natively by the framework - /// - public enum VssCredentialsType - { - Windows = 0, - Federated = 1, - Basic = 2, - ServiceIdentity = 3, - OAuth = 4, - S2S = 5, - Other = 6, - Aad = 7, - } - - /// - /// Provides the ability to control when to show or hide the credential prompt user interface. - /// - public enum CredentialPromptType - { - /// - /// Show the UI only if necessary to obtain credentials. - /// - PromptIfNeeded = 0, - - /// - /// Never show the UI, even if an error occurs. - /// - DoNotPrompt = 2, - } - - /// - /// Provides credentials to use when connecting to a Visual Studio Service. - /// - public class VssCredentials - { - /// - /// Initializes a new VssCredentials instance with default credentials. - /// - public VssCredentials() - : this(true) - { - } - - /// - /// Initializes a new VssCredentials instance with default credentials if specified. - /// - /// True to use default windows credentials; otherwise, false - public VssCredentials(bool useDefaultCredentials) - : this(new WindowsCredential(useDefaultCredentials)) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified windows credential. - /// - /// The windows credential to use for authentication - public VssCredentials(WindowsCredential windowsCredential) - : this(windowsCredential, null) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified windows credential. - /// - /// The windows credential to use for authentication - /// CredentialPromptType.PromptIfNeeded if interactive prompts are allowed, otherwise CredentialProptType.DoNotPrompt - public VssCredentials( - WindowsCredential windowsCredential, - CredentialPromptType promptType) - : this(windowsCredential, null, promptType) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified issued token credential and - /// default windows credential. - /// - /// The federated credential to use for authentication - public VssCredentials(FederatedCredential federatedCredential) - : this(new WindowsCredential(), federatedCredential) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified windows and issued token - /// credential. - /// - /// The windows credential to use for authentication - /// The federated credential to use for authentication - public VssCredentials( - WindowsCredential windowsCredential, - FederatedCredential federatedCredential) - : this(windowsCredential, federatedCredential, EnvironmentUserInteractive - ? CredentialPromptType.PromptIfNeeded : CredentialPromptType.DoNotPrompt) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified windows and issued token - /// credential. - /// - /// The windows credential to use for authentication - /// The federated credential to use for authentication - /// CredentialPromptType.PromptIfNeeded if interactive prompts are allowed, otherwise CredentialProptType.DoNotPrompt - public VssCredentials( - WindowsCredential windowsCredential, - FederatedCredential federatedCredential, - CredentialPromptType promptType) - : this(windowsCredential, federatedCredential, promptType, null) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified windows and issued token - /// credential. - /// - /// The windows credential to use for authentication - /// The federated credential to use for authentication - /// CredentialPromptType.PromptIfNeeded if interactive prompts are allowed; otherwise, CredentialProptType.DoNotPrompt - /// An optional TaskScheduler to ensure credentials prompting occurs on the UI thread - public VssCredentials( - WindowsCredential windowsCredential, - FederatedCredential federatedCredential, - CredentialPromptType promptType, - TaskScheduler scheduler) - : this(windowsCredential, federatedCredential, promptType, scheduler, null) - { - } - - /// - /// Initializes a new VssCredentials instance with the specified windows and issued token - /// credential. - /// - /// The windows credential to use for authentication - /// The federated credential to use for authentication - /// CredentialPromptType.PromptIfNeeded if interactive prompts are allowed; otherwise, CredentialProptType.DoNotPrompt - /// An optional TaskScheduler to ensure credentials prompting occurs on the UI thread - /// An optional IVssCredentialPrompt to perform prompting for credentials - public VssCredentials( - WindowsCredential windowsCredential, - FederatedCredential federatedCredential, - CredentialPromptType promptType, - TaskScheduler scheduler, - IVssCredentialPrompt credentialPrompt) - { - this.PromptType = promptType; - - if (promptType == CredentialPromptType.PromptIfNeeded && scheduler == null) - { - // If we use TaskScheduler.FromCurrentSynchronizationContext() here and this is executing under the UI - // thread, for example from an event handler in a WinForms applications, this TaskScheduler will capture - // the UI SyncrhonizationContext whose MaximumConcurrencyLevel is 1 and only has a single thread to - // execute queued work. Then, if the UI thread invokes one of our synchronous methods that are just - // wrappers that block until the asynchronous overload returns, and if the async Task queues work to - // this TaskScheduler, like GitHub.Services.CommonGetTokenOperation.GetTokenAsync does, - // this will produce an immediate deadlock. It is a much safer choice to use TaskScheduler.Default here - // as it uses the .NET Framework ThreadPool to execute queued work. - scheduler = TaskScheduler.Default; - } - - if (windowsCredential != null) - { - m_windowsCredential = windowsCredential; - m_windowsCredential.Scheduler = scheduler; - m_windowsCredential.Prompt = credentialPrompt; - } - - if (federatedCredential != null) - { - m_federatedCredential = federatedCredential; - m_federatedCredential.Scheduler = scheduler; - m_federatedCredential.Prompt = credentialPrompt; - } - - m_thisLock = new object(); - } - - /// - /// Implicitly converts a FederatedCredential instance into a VssCredentials instance. - /// - /// The federated credential instance - /// A new VssCredentials instance which wraps the specified credential - public static implicit operator VssCredentials(FederatedCredential credential) - { - return new VssCredentials(credential); - } - - /// - /// Implicitly converts a WindowsCredential instance into a VssCredentials instance. - /// - /// The windows credential instance - /// A new VssCredentials instance which wraps the specified credential - public static implicit operator VssCredentials(WindowsCredential credential) - { - return new VssCredentials(credential); - } - - /// - /// Gets or sets a value indicating whether or not interactive prompts are allowed. - /// - public CredentialPromptType PromptType - { - get - { - return m_promptType; - } - set - { - if (value == CredentialPromptType.PromptIfNeeded && !EnvironmentUserInteractive) - { - throw new ArgumentException(CommonResources.CannotPromptIfNonInteractive(), "PromptType"); - } - - m_promptType = value; - } - } - - /// - /// Gets or sets a value indicating the issued token credentials to use for authentication with the server. - /// - public FederatedCredential Federated - { - get - { - return m_federatedCredential; - } - } - - /// - /// Gets the windows credential to use for NTLM authentication with the server. - /// - public WindowsCredential Windows - { - get - { - return m_windowsCredential; - } - } - - /// - /// A pluggable credential store. - /// Simply assign a storage implementation to this property - /// and the VssCredentials will use it to store and retrieve tokens - /// during authentication. - /// - public IVssCredentialStorage Storage - { - get - { - return m_credentialStorage; - } - set - { - m_credentialStorage = value; - - if (m_windowsCredential != null) - { - m_windowsCredential.Storage = value; - } - - if (m_federatedCredential != null) - { - m_federatedCredential.Storage = value; - } - } - } - - /// - ///Attempts to find appropriate Access token for IDE user and add to prompt's parameter - /// Actual implementation in override. - /// - internal virtual bool TryGetValidAdalToken(IVssCredentialPrompt prompt) - { - return false; - } - - /// - /// Creates a token provider for the configured issued token credentials. - /// - /// The targeted server - /// The failed web response - /// The failed token - /// A provider for retrieving tokens for the configured credential - internal IssuedTokenProvider CreateTokenProvider( - Uri serverUrl, - IHttpResponse webResponse, - IssuedToken failedToken) - { - ArgumentUtility.CheckForNull(serverUrl, "serverUrl"); - - IssuedTokenProvider tokenProvider = null; - VssTraceActivity traceActivity = VssTraceActivity.Current; - lock (m_thisLock) - { - tokenProvider = m_currentProvider; - if (tokenProvider == null || !tokenProvider.IsAuthenticationChallenge(webResponse)) - { - // Prefer federated authentication over Windows authentication. - if (m_federatedCredential != null && m_federatedCredential.IsAuthenticationChallenge(webResponse)) - { - if (tokenProvider != null) - { - VssHttpEventSource.Log.IssuedTokenProviderRemoved(traceActivity, tokenProvider); - } - - // TODO: This needs to be refactored or renamed to be more generic ... - this.TryGetValidAdalToken(m_federatedCredential.Prompt); - - tokenProvider = m_federatedCredential.CreateTokenProvider(serverUrl, webResponse, failedToken); - - if (tokenProvider != null) - { - VssHttpEventSource.Log.IssuedTokenProviderCreated(traceActivity, tokenProvider); - } - } - else if (m_windowsCredential != null && m_windowsCredential.IsAuthenticationChallenge(webResponse)) - { - if (tokenProvider != null) - { - VssHttpEventSource.Log.IssuedTokenProviderRemoved(traceActivity, tokenProvider); - } - - tokenProvider = m_windowsCredential.CreateTokenProvider(serverUrl, webResponse, failedToken); - - if (tokenProvider != null) - { - VssHttpEventSource.Log.IssuedTokenProviderCreated(traceActivity, tokenProvider); - } - } - - m_currentProvider = tokenProvider; - } - - return tokenProvider; - } - } - - /// - /// Retrieves the token provider for the provided server URL if one has been created. - /// - /// The targeted server - /// Stores the active token provider, if one exists - /// True if a token provider was found, false otherwise - public bool TryGetTokenProvider( - Uri serverUrl, - out IssuedTokenProvider provider) - { - ArgumentUtility.CheckForNull(serverUrl, "serverUrl"); - - lock (m_thisLock) - { - // Ensure that we attempt to use the most appropriate authentication mechanism by default. - if (m_currentProvider == null) - { - if (m_federatedCredential != null) - { - m_currentProvider = m_federatedCredential.CreateTokenProvider(serverUrl, null, null); - } - - if (m_currentProvider == null && m_windowsCredential != null) - { - m_currentProvider = m_windowsCredential.CreateTokenProvider(serverUrl, null, null); - } - - if (m_currentProvider != null) - { - VssHttpEventSource.Log.IssuedTokenProviderCreated(VssTraceActivity.Current, m_currentProvider); - } - } - - provider = m_currentProvider; - } - - return provider != null; - } - - /// - /// Determines if the web response is an authentication redirect for issued token providers. - /// - /// The web response - /// True if this is an token authentication redirect, false otherwise - internal bool IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (webResponse == null) - { - return false; - } - - bool isChallenge = false; - if (m_windowsCredential != null) - { - isChallenge = m_windowsCredential.IsAuthenticationChallenge(webResponse); - } - - if (!isChallenge && m_federatedCredential != null) - { - isChallenge = m_federatedCredential.IsAuthenticationChallenge(webResponse); - } - - return isChallenge; - } - - internal void SignOut( - Uri serverUrl, - Uri serviceLocation, - string identityProvider) - { - // Remove the token in the storage and the current token provider. Note that we don't - // call InvalidateToken here because we want to remove the whole token not just its value - if ((m_currentProvider != null) && (m_currentProvider.CurrentToken != null)) - { - if (m_currentProvider.Credential.Storage != null && m_currentProvider.TokenStorageUrl != null) - { - m_currentProvider.Credential.Storage.RemoveToken(m_currentProvider.TokenStorageUrl, m_currentProvider.CurrentToken); - } - m_currentProvider.CurrentToken = null; - } - - // We need to make sure that the current provider actually supports the signout method - ISupportSignOut tokenProviderWithSignOut = m_currentProvider as ISupportSignOut; - if (tokenProviderWithSignOut == null) - { - return; - } - - // Replace the parameters from the service location - if (serviceLocation != null) - { - string serviceLocationUri = serviceLocation.AbsoluteUri; - serviceLocationUri = serviceLocationUri.Replace("{mode}", "SignOut"); - serviceLocationUri = serviceLocationUri.Replace("{redirectUrl}", serverUrl.AbsoluteUri); - serviceLocation = new Uri(serviceLocationUri); - } - - // Now actually signout of the token provider - tokenProviderWithSignOut.SignOut(serviceLocation, serverUrl, identityProvider); - } - -#if !NETSTANDARD - /// - /// Loads stored credentials for the specified server if found. If no credentials are found in the windows - /// credential store for the specified server and options then default credentials are returned. - /// - /// The server location - /// A value indicating whether or not an exact or partial match of the server is required - /// A credentials object populated with stored credentials for the server if found - public static VssCredentials LoadCachedCredentials( - Uri serverUrl, - bool requireExactMatch) - { - return LoadCachedCredentials(null, serverUrl, requireExactMatch); - } - - /// - /// Loads stored credentials for the specified server if found. If no credentials are found for the specified server and options then default credentials are returned. - /// This overload assumes that the credentials are to be stored under the TFS server's registry root - /// - /// An optional application name for isolated credential storage in the registry - /// The server location - /// A value indicating whether or not an exact or partial match of the server is required - /// A credentials object populated with stored credentials for the server if found - [EditorBrowsable(EditorBrowsableState.Never)] - public static VssCredentials LoadCachedCredentials( - string featureRegistryKeyword, - Uri serverUrl, - bool requireExactMatch) - { - ArgumentUtility.CheckForNull(serverUrl, "serverUrl"); - - bool uriKnownToCachedProvider = false; - VssCredentials cred = LoadCachedCredentialsFromRegisteredProviders(serverUrl, out uriKnownToCachedProvider); - - // If one of the registered credential providers had the target URI in its cache but failed to return a valid credential it means - // we should have had a cred but something went wrong (user canceled, user failed, auth source unavailable, etc.). In that case - // we Do Not want to carry on with the fallback to the VS registry/windows store credential caches. Even if that worked to get a - // credential it would put the user in a bad state (having an active, authenticated connection with an unexpected credential type). - if (cred == null && !uriKnownToCachedProvider) - { - WindowsCredential windowsCredential = null; - FederatedCredential federatedCredential = null; - CredentialsCacheManager credentialsCacheManager = new CredentialsCacheManager(); - TfsCredentialCacheEntry cacheEntry = credentialsCacheManager.GetCredentials(featureRegistryKeyword, serverUrl, requireExactMatch, null); - if (cacheEntry != null) - { - if (cacheEntry.NonInteractive) - { - switch (cacheEntry.Type) - { - case CachedCredentialsType.ServiceIdentity: - VssServiceIdentityToken initialToken = null; - string initialTokenValue = ReadAuthorizationToken(cacheEntry.Attributes); - if (!string.IsNullOrEmpty(initialTokenValue)) - { - initialToken = new VssServiceIdentityToken(initialTokenValue); - } - - // Initialize the issued token credential using the stored token if it exists - federatedCredential = new VssServiceIdentityCredential(cacheEntry.Credentials.UserName, - cacheEntry.Credentials.Password, - initialToken); - break; - - case CachedCredentialsType.Windows: - windowsCredential = new WindowsCredential(cacheEntry.Credentials); - break; - } - } - } - - cred = new VssCredentials(windowsCredential ?? new WindowsCredential(true), federatedCredential, CredentialPromptType.DoNotPrompt); - } - - return cred ?? new VssCredentials(new WindowsCredential(true), null, CredentialPromptType.DoNotPrompt); - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static VssCredentials LoadCachedCredentialsFromRegisteredProviders(Uri serverUri, out bool knownUri) - { - LoadRegisteredCachedVssCredentialProviders(); - bool uriKnownByAnyProvider = false; - VssCredentials cred = null; - foreach (var pair in m_loadedCachedVssCredentialProviders) - { - bool uriKnownToProvider = false; - cred = pair.Value?.GetCachedCredentials(serverUri, out uriKnownToProvider); - if (cred != null || uriKnownToProvider) - { - uriKnownByAnyProvider |= uriKnownToProvider; - break; - } - } - knownUri = uriKnownByAnyProvider; - return cred; - } - - private static void LoadRegisteredCachedVssCredentialProviders() - { - CredentialsProviderRegistryHelper.LoadCachedVssCredentialProviders(ref m_loadedCachedVssCredentialProviders); - } - private static ConcurrentDictionary m_loadedCachedVssCredentialProviders = new ConcurrentDictionary(); -#endif - - [EditorBrowsable(EditorBrowsableState.Never)] - public static void WriteAuthorizationToken( - string token, - IDictionary attributes) - { - int i = 0; - for (int j = 0; j < token.Length; i++, j += 128) - { - attributes["AuthTokenSegment" + i] = token.Substring(j, Math.Min(128, token.Length - j)); - } - - attributes["AuthTokenSegmentCount"] = i.ToString(CultureInfo.InvariantCulture); - } - - protected static string ReadAuthorizationToken(IDictionary attributes) - { - string authTokenCountValue; - if (attributes.TryGetValue("AuthTokenSegmentCount", out authTokenCountValue)) - { - int authTokenCount = int.Parse(authTokenCountValue, CultureInfo.InvariantCulture); - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < authTokenCount; i++) - { - string segmentName = "AuthTokenSegment" + i; - - string segmentValue; - if (attributes.TryGetValue(segmentName, out segmentValue)) - { - sb.Append(segmentValue); - } - } - - return sb.ToString(); - } - - return string.Empty; - } - - protected static bool EnvironmentUserInteractive - { - get - { - return Environment.UserInteractive; - } - } - - private object m_thisLock; - private CredentialPromptType m_promptType; - private IssuedTokenProvider m_currentProvider; - protected WindowsCredential m_windowsCredential; - protected FederatedCredential m_federatedCredential; - private IVssCredentialStorage m_credentialStorage; - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssServiceIdentityCredential.cs b/src/Sdk/Common/Common/Authentication/VssServiceIdentityCredential.cs deleted file mode 100644 index 8b22a5616..000000000 --- a/src/Sdk/Common/Common/Authentication/VssServiceIdentityCredential.cs +++ /dev/null @@ -1,164 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; - -namespace GitHub.Services.Common -{ - /// - /// Provides federated authentication as a service identity with a Visual Studio Service. - /// - [Serializable] - public sealed class VssServiceIdentityCredential : FederatedCredential - { - /// - /// Initializes a new VssServiceIdentityCredential instance with the specified user name and password. - /// - /// The user name - /// The password - public VssServiceIdentityCredential( - string userName, - string password) - : this(userName, password, null) - { - } - - /// - /// Initializes a new VssServiceIdentityCredential instance with the specified user name and password. The - /// provided token, if not null, will be used before attempting authentication with the credentials. - /// - /// The user name - /// The password - /// An optional token which, if present, should be used before obtaining a new token - public VssServiceIdentityCredential( - string userName, - string password, - VssServiceIdentityToken initialToken) - : this(userName, password, initialToken, null) - { - } - - /// - /// Initializes a new VssServiceIdentityCredential instance with the specified access token. - /// - /// A token which may be used for authorization as the desired service identity - public VssServiceIdentityCredential(VssServiceIdentityToken token) - : this(null, null, token, null) - { - } - - /// - /// Initializes a new VssServiceIdentityCredential instance with the specified user name and password. The - /// provided token, if not null, will be used before attempting authentication with the credentials. - /// - /// The user name - /// The password - /// An optional token which, if present, should be used before obtaining a new token - /// An optional HttpMessageHandler which if passed will be passed along to the TokenProvider when executing OnCreateTokenProvider - public VssServiceIdentityCredential( - string userName, - string password, - VssServiceIdentityToken initialToken, - DelegatingHandler innerHandler) - : base(initialToken) - { - m_userName = userName; - m_password = password; - m_innerHandler = innerHandler; - } - - public override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.ServiceIdentity; - } - } - - /// - /// Gets the user name. - /// - public String UserName - { - get - { - return m_userName; - } - } - - /// - /// Gets the password. - /// - internal String Password - { - get - { - return m_password; - } - } - - public override bool IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (webResponse == null) - { - return false; - } - - if (webResponse.StatusCode == HttpStatusCode.Found || - webResponse.StatusCode == HttpStatusCode.Redirect || - webResponse.StatusCode == HttpStatusCode.Unauthorized) - { - var authRealm = webResponse.Headers.GetValues(Internal.HttpHeaders.TfsFedAuthRealm).FirstOrDefault(); - var authIssuer = webResponse.Headers.GetValues(Internal.HttpHeaders.TfsFedAuthIssuer).FirstOrDefault(); - var wwwAuthenticate = webResponse.Headers.GetValues(Internal.HttpHeaders.WwwAuthenticate); - if (!String.IsNullOrEmpty(authIssuer) && !String.IsNullOrEmpty(authRealm)) - { - return webResponse.StatusCode != HttpStatusCode.Unauthorized || wwwAuthenticate.Any(x => x.StartsWith("TFS-Federated", StringComparison.OrdinalIgnoreCase)); - } - } - - return false; - } - - internal override string GetAuthenticationChallenge(IHttpResponse webResponse) - { - var authRealm = webResponse.Headers.GetValues(Internal.HttpHeaders.TfsFedAuthRealm).FirstOrDefault(); - var authIssuer = webResponse.Headers.GetValues(Internal.HttpHeaders.TfsFedAuthIssuer).FirstOrDefault(); - return string.Format(CultureInfo.InvariantCulture, "TFS-Federated realm={0}, issuer={1}", authRealm, authIssuer); - } - - /// - /// Creates a provider for retrieving security tokens for the provided credentials. - /// - /// An issued token provider for the current credential - protected override IssuedTokenProvider OnCreateTokenProvider( - Uri serverUrl, - IHttpResponse response) - { - // The response is only null when attempting to determine the most appropriate token provider to - // use for the connection. The only way we should do anything here is if we have an initial token - // since that means we can present something without making a server call. - if (response == null && base.InitialToken == null) - { - return null; - } - - Uri signInUrl = null; - String realm = string.Empty; - if (response != null) - { - realm = response.Headers.GetValues(Internal.HttpHeaders.TfsFedAuthRealm).FirstOrDefault(); - signInUrl = new Uri(new Uri(response.Headers.GetValues(Internal.HttpHeaders.TfsFedAuthIssuer).FirstOrDefault()).GetLeftPart(UriPartial.Authority)); - } - - return new VssServiceIdentityTokenProvider(this, serverUrl, signInUrl, realm, m_innerHandler); - } - - private readonly String m_userName; - private readonly String m_password; - - [NonSerialized] - private readonly DelegatingHandler m_innerHandler = null; - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssServiceIdentityToken.cs b/src/Sdk/Common/Common/Authentication/VssServiceIdentityToken.cs deleted file mode 100644 index 8d102d06b..000000000 --- a/src/Sdk/Common/Common/Authentication/VssServiceIdentityToken.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// Provides simple web token used for OAuth authentication. - /// - [Serializable] - public sealed class VssServiceIdentityToken : IssuedToken - { - /// - /// Initializes a new VssServiceIdentityToken instance with the specified token value. - /// - /// The token value as a string - public VssServiceIdentityToken(string token) - { - ArgumentUtility.CheckStringForNullOrEmpty(token, "token"); - - m_token = token; - //.ValidFrom = DateTime.UtcNow; - - // Read out the expiration time for the ValidTo field if we can find it - Dictionary nameValues; - if (TryGetNameValues(token, out nameValues)) - { - string expiresOnValue; - if (nameValues.TryGetValue(c_expiresName, out expiresOnValue)) - { - // The time is represented as standard epoch - // base.ValidTo = s_epoch.AddSeconds(Convert.ToUInt64(expiresOnValue, CultureInfo.CurrentCulture)); - } - } - } - - public String Token - { - get - { - return m_token; - } - } - - protected internal override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.ServiceIdentity; - } - } - - internal override void ApplyTo(IHttpRequest request) - { - request.Headers.SetValue(Internal.HttpHeaders.Authorization, "WRAP access_token=\"" + m_token + "\""); - } - - internal static VssServiceIdentityToken ExtractToken(string responseValue) - { - // Extract the actual token string - string token = UriUtility.UrlDecode(responseValue - .Split('&') - .Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase)) - .Split('=')[1], VssHttpRequestSettings.Encoding); - - return new VssServiceIdentityToken(token); - } - - internal static bool TryGetNameValues( - string token, - out Dictionary tokenValues) - { - tokenValues = null; - - if (string.IsNullOrEmpty(token)) - { - return false; - } - - tokenValues = - token - .Split('&') - .Aggregate( - new Dictionary(), - (dict, rawNameValue) => - { - if (rawNameValue == string.Empty) - { - return dict; - } - - string[] nameValue = rawNameValue.Split('='); - - if (nameValue.Length != 2) - { - return dict; - } - - if (dict.ContainsKey(nameValue[0]) == true) - { - return dict; - } - - dict.Add(UriUtility.UrlDecode(nameValue[0]), UriUtility.UrlDecode(nameValue[1])); - return dict; - }); - return true; - } - - private string m_token; - private const string c_expiresName = "ExpiresOn"; - } -} diff --git a/src/Sdk/Common/Common/Authentication/VssServiceIdentityTokenProvider.cs b/src/Sdk/Common/Common/Authentication/VssServiceIdentityTokenProvider.cs deleted file mode 100644 index 2748afdc7..000000000 --- a/src/Sdk/Common/Common/Authentication/VssServiceIdentityTokenProvider.cs +++ /dev/null @@ -1,201 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common.Diagnostics; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - internal sealed class VssServiceIdentityTokenProvider : IssuedTokenProvider - { - public VssServiceIdentityTokenProvider( - VssServiceIdentityCredential credential, - Uri serverUrl, - Uri signInUrl, - string realm, - DelegatingHandler innerHandler) - : this(credential, serverUrl, signInUrl, realm) - { - m_innerHandler = innerHandler; - } - - public VssServiceIdentityTokenProvider( - VssServiceIdentityCredential credential, - Uri serverUrl, - Uri signInUrl, - string realm) - : base(credential, serverUrl, signInUrl) - { - Realm = realm; - } - - protected override string AuthenticationParameter - { - get - { - if (string.IsNullOrEmpty(this.Realm) && this.SignInUrl == null) - { - return string.Empty; - } - else - { - return string.Format(CultureInfo.InvariantCulture, "issuer=\"{0}\", realm=\"{1}\"", this.SignInUrl, this.Realm); - } - } - } - - protected override String AuthenticationScheme - { - get - { - return "TFS-Federated"; - } - } - - /// - /// Gets the simple web token credential from which this provider was created. - /// - public new VssServiceIdentityCredential Credential - { - get - { - return (VssServiceIdentityCredential)base.Credential; - } - } - - /// - /// Gets a value indicating whether or not a call to get token will require interactivity. - /// - public override Boolean GetTokenIsInteractive - { - get - { - return false; - } - } - - /// - /// Gets the realm for the token provider. - /// - public String Realm - { - get; - } - - protected internal override bool IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (!base.IsAuthenticationChallenge(webResponse)) - { - return false; - } - - // This means we were proactively constructed without any connection information. In this case - // we return false to ensure that a new provider is reconstructed with all appropriate configuration - // to retrieve a new token. - if (this.SignInUrl == null) - { - return false; - } - - string authRealm = webResponse.Headers.GetValues(HttpHeaders.TfsFedAuthRealm).FirstOrDefault(); - string authIssuer = webResponse.Headers.GetValues(HttpHeaders.TfsFedAuthIssuer).FirstOrDefault(); - Uri signInUrl = new Uri(new Uri(authIssuer).GetLeftPart(UriPartial.Authority), UriKind.Absolute); - - // Make sure that the values match our stored values. This way if the values change we will be thrown - // away and a new instance with correct values will be constructed. - return this.Realm.Equals(authRealm, StringComparison.OrdinalIgnoreCase) && - Uri.Compare(this.SignInUrl, signInUrl, UriComponents.AbsoluteUri, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) == 0; - } - - /// - /// Issues a request to synchronously retrieve a token for the associated credential. - /// - /// - /// - /// - protected override async Task OnGetTokenAsync( - IssuedToken failedToken, - CancellationToken cancellationToken) - { - if (string.IsNullOrEmpty(this.Credential.UserName) || - string.IsNullOrEmpty(this.Credential.Password)) - { - return null; - } - - VssTraceActivity traceActivity = VssTraceActivity.Current; - using (HttpClient client = new HttpClient(CreateMessageHandler(), false)) - { - client.BaseAddress = this.SignInUrl; - - KeyValuePair[] values = new KeyValuePair[] - { - new KeyValuePair("wrap_name", this.Credential.UserName), - new KeyValuePair("wrap_password", this.Credential.Password), - new KeyValuePair("wrap_scope", this.Realm), - }; - - Uri url = new Uri("WRAPv0.9/", UriKind.Relative); - FormUrlEncodedContent content = new FormUrlEncodedContent(values); - using (HttpResponseMessage response = await client.PostAsync(url, content, cancellationToken).ConfigureAwait(false)) - { - string responseValue = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - if (response.IsSuccessStatusCode) - { - return VssServiceIdentityToken.ExtractToken(responseValue); - } - else - { - VssHttpEventSource.Log.AuthenticationError(traceActivity, this, responseValue); - return null; - } - } - } - } - - private HttpMessageHandler CreateMessageHandler() - { - var retryOptions = new VssHttpRetryOptions() - { - RetryableStatusCodes = - { - VssNetworkHelper.TooManyRequests, - HttpStatusCode.InternalServerError, - }, - }; - - HttpMessageHandler innerHandler; - - if (m_innerHandler != null) - { - if (m_innerHandler.InnerHandler == null) - { - m_innerHandler.InnerHandler = new HttpClientHandler(); - } - - innerHandler = m_innerHandler; - } - else - { - innerHandler = new HttpClientHandler(); - } - - // Inherit proxy setting from VssHttpMessageHandler - var httpClientHandler = innerHandler as HttpClientHandler; - if (httpClientHandler != null && VssHttpMessageHandler.DefaultWebProxy != null) - { - httpClientHandler.Proxy = VssHttpMessageHandler.DefaultWebProxy; - httpClientHandler.UseProxy = true; - } - - return new VssHttpRetryMessageHandler(retryOptions, innerHandler); - } - - private DelegatingHandler m_innerHandler = null; - } -} diff --git a/src/Sdk/Common/Common/Authentication/WindowsCredential.cs b/src/Sdk/Common/Common/Authentication/WindowsCredential.cs deleted file mode 100644 index e42bec581..000000000 --- a/src/Sdk/Common/Common/Authentication/WindowsCredential.cs +++ /dev/null @@ -1,137 +0,0 @@ -using System; -using System.Linq; -using System.Net; - -namespace GitHub.Services.Common -{ - /// - /// Provides a credential for windows authentication against a Visual Studio Service. - /// - public sealed class WindowsCredential : IssuedTokenCredential - { - /// - /// Initializes a new WindowsCredential instance using a default user interface provider implementation - /// and the default network credentials. - /// - public WindowsCredential() - : this(true) - { - } - - /// - /// Initializes a new WindowsCredential instance using a default user interface provider implementation - /// and the default network credentials, if specified. - /// - /// True if the default credentials should be used; otherwise, false - public WindowsCredential(bool useDefaultCredentials) - : this(useDefaultCredentials ? CredentialCache.DefaultCredentials : null) - { - UseDefaultCredentials = useDefaultCredentials; - } - - /// - /// Initializes a new WindowsCredential instance using a default user interface provider implementation - /// and the specified network credentials. - /// - /// The windows credentials which should be used for authentication - public WindowsCredential(ICredentials credentials) - : this(null) - { - m_credentials = credentials; - UseDefaultCredentials = credentials == CredentialCache.DefaultCredentials; - } - - /// - /// Initializes a new WindowsCredential instance using the specified initial token. - /// - /// An optional token which, if present, should be used before obtaining a new token - public WindowsCredential(WindowsToken initialToken) - : base(initialToken) - { - } - - /// - /// Gets the credentials associated with this windows credential. - /// - public ICredentials Credentials - { - get - { - return m_credentials; - } - set - { - m_credentials = value; - UseDefaultCredentials = Credentials == CredentialCache.DefaultCredentials; - } - } - - public override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.Windows; - } - } - - /// - /// Gets a value indicating what value was passed to WindowsCredential(bool useDefaultCredentials) constructor - /// - public Boolean UseDefaultCredentials - { - get; - private set; - } - - public override Boolean IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (webResponse == null) - { - return false; - } - - if (webResponse.StatusCode == HttpStatusCode.Unauthorized && - webResponse.Headers.GetValues(Internal.HttpHeaders.WwwAuthenticate).Any(x => AuthenticationSchemeValid(x))) - { - return true; - } - - if (webResponse.StatusCode == HttpStatusCode.ProxyAuthenticationRequired && - webResponse.Headers.GetValues(Internal.HttpHeaders.ProxyAuthenticate).Any(x => AuthenticationSchemeValid(x))) - { - return true; - } - - return false; - } - - protected override IssuedTokenProvider OnCreateTokenProvider( - Uri serverUrl, - IHttpResponse response) - { - // If we have no idea what kind of credentials we are supposed to be using, don't play a windows token on - // the first request. - if (response == null) - { - return null; - } - - if (m_credentials != null) - { - this.InitialToken = new WindowsToken(m_credentials); - } - - return new WindowsTokenProvider(this, serverUrl); - } - - private static Boolean AuthenticationSchemeValid(String authenticateHeader) - { - return authenticateHeader.StartsWith("Basic", StringComparison.OrdinalIgnoreCase) || - authenticateHeader.StartsWith("Digest", StringComparison.OrdinalIgnoreCase) || - authenticateHeader.StartsWith("Negotiate", StringComparison.OrdinalIgnoreCase) || - authenticateHeader.StartsWith("Ntlm", StringComparison.OrdinalIgnoreCase); - } - - private ICredentials m_credentials; - } -} diff --git a/src/Sdk/Common/Common/Authentication/WindowsToken.cs b/src/Sdk/Common/Common/Authentication/WindowsToken.cs deleted file mode 100644 index 70d79eba3..000000000 --- a/src/Sdk/Common/Common/Authentication/WindowsToken.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Net; - -namespace GitHub.Services.Common -{ - public sealed class WindowsToken : IssuedToken, ICredentials - { - internal WindowsToken(ICredentials credentials) - { - this.Credentials = credentials; - } - - public ICredentials Credentials - { - get; - } - - protected internal override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.Windows; - } - } - - internal override void ApplyTo(IHttpRequest request) - { - // Special-cased by the caller because we implement ICredentials - throw new InvalidOperationException(); - } - - NetworkCredential ICredentials.GetCredential( - Uri uri, - String authType) - { - return this.Credentials?.GetCredential(uri, authType); - } - } -} diff --git a/src/Sdk/Common/Common/Authentication/WindowsTokenProvider.cs b/src/Sdk/Common/Common/Authentication/WindowsTokenProvider.cs deleted file mode 100644 index 4725de22b..000000000 --- a/src/Sdk/Common/Common/Authentication/WindowsTokenProvider.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Globalization; -using System.Net; - -namespace GitHub.Services.Common -{ - internal sealed class WindowsTokenProvider : IssuedTokenProvider - { - public WindowsTokenProvider( - WindowsCredential credential, - Uri serverUrl) - : base(credential, serverUrl, serverUrl) - { - } - - protected override String AuthenticationScheme - { - get - { - return String.Format(CultureInfo.InvariantCulture, "{0} {1} {2} {3}", AuthenticationSchemes.Negotiate, AuthenticationSchemes.Ntlm, AuthenticationSchemes.Digest, AuthenticationSchemes.Basic); - } - } - - public new WindowsCredential Credential - { - get - { - return (WindowsCredential)base.Credential; - } - } - - public override Boolean GetTokenIsInteractive - { - get - { - return base.CurrentToken == null; - } - } - } -} diff --git a/src/Sdk/Common/Common/ClientStorage/IVssClientStorage.cs b/src/Sdk/Common/Common/ClientStorage/IVssClientStorage.cs deleted file mode 100644 index d3529b910..000000000 --- a/src/Sdk/Common/Common/ClientStorage/IVssClientStorage.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; - -namespace GitHub.Services.Common.ClientStorage -{ - /// - /// An interface for accessing client data stored locally. - /// - [EditorBrowsable(EditorBrowsableState.Never)] // for internal use - public interface IVssClientStorage : IVssClientStorageReader, IVssClientStorageWriter - { - /// - /// Much like the System.IO.Path.Combine method, this method puts together path segments into a path using - /// the appropriate path delimiter. - /// - /// - /// - string PathKeyCombine(params string[] paths); - - /// - /// The path segment delimiter used by this storage mechanism. - /// - char PathSeparator { get; } - } - - /// - /// An interface for reading from local data storage - /// - public interface IVssClientStorageReader - { - /// - /// Reads one entry from the storage. - /// - /// The type to return. - /// This is the path key for the data to retrieve. - /// Returns the value stored at the given path as type T - T ReadEntry(string path); - - /// - /// Reads one entry from the storage. If the entry does not exist or can not be converted to type T, the default value provided will be returned. - /// When T is not a simple type, and there is extra logic to determine the default value, the pattern: ReadEntry<T>(path) && GetDefault(); is - /// preferred, so that method to retrieve the default is not evaluated unless the entry does not exist. - /// - /// The type to return. - /// This is the path key for the data to retrieve. - /// The value to return if the key does not exist or the value can not be converted to type T - /// - T ReadEntry(string path, T defaultValue); - - /// - /// Returns all entries under the path provided whose values can be converted to T. If path = "root\mydata", then this will return all entries where path begins with "root\mydata\". - /// - /// The type for the entries to return. - /// The path pointing to the branch of entries to return. - /// - IDictionary ReadEntries(string path); - } - - /// - /// An interface for writing to local data storage - /// - public interface IVssClientStorageWriter - { - /// - /// Write one entry into the local data storage. - /// - /// This is the key for the data to store. Providing a path allows data to be accessed hierarchicaly. - /// The value to store at the specified path. Setting his to NULL will remove the entry. - void WriteEntry(string path, object value); - - /// - /// Writes a set of entries to the writer, which provides efficiency benefits over writing each entry individually. - /// It also ensures that the either all of the entries are written or in the case of an error, no entries are written. - /// Setting a value to NULL, will remove the entry. - /// - /// - void WriteEntries(IEnumerable> entries); - } -} diff --git a/src/Sdk/Common/Common/ClientStorage/VssFileStorage.cs b/src/Sdk/Common/Common/ClientStorage/VssFileStorage.cs deleted file mode 100644 index 95d6dc1cf..000000000 --- a/src/Sdk/Common/Common/ClientStorage/VssFileStorage.cs +++ /dev/null @@ -1,623 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common.Internal; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.Common.ClientStorage -{ - /// - /// Class providing access to local file storage, so data can persist across processes. - /// - [EditorBrowsable(EditorBrowsableState.Never)] // for internal use - public class VssFileStorage : IVssClientStorage, IDisposable - { - private readonly string m_filePath; - private readonly VssFileStorageReader m_reader; - private readonly IVssClientStorageWriter m_writer; - - private const char c_defaultPathSeparator = '\\'; - private const bool c_defaultIgnoreCaseInPaths = false; - - /// - /// The separator to use between the path segments of the storage keys. - /// - public char PathSeparator { get; } - - /// - /// The StringComparer used to compare keys in the dictionary. - /// - public StringComparer PathComparer { get; } - - /// - /// This constructor should remain private. Use the factory method GetVssLocalFileStorage to ensure we only have one instance per file, - /// which will reduce contention. - /// - /// This file path to store the settings. - /// The separator to use between the path segments of the storage keys. - /// If true the dictionary will use the OrdinalIgnoreCase StringComparer to compare keys. - private VssFileStorage(string filePath, char pathSeparatorForKeys = c_defaultPathSeparator, bool ignoreCaseInPaths = c_defaultIgnoreCaseInPaths) // This constructor should remain private. - { - PathSeparator = pathSeparatorForKeys; - PathComparer = GetAppropriateStringComparer(ignoreCaseInPaths); - m_filePath = filePath; - m_reader = new VssFileStorageReader(m_filePath, pathSeparatorForKeys, PathComparer); - m_writer = new VssFileStorageWriter(m_filePath, pathSeparatorForKeys, PathComparer); - } - - public T ReadEntry(string path) - { - return m_reader.ReadEntry(path); - } - - public T ReadEntry(string path, T defaultValue) - { - return m_reader.ReadEntry(path, defaultValue); - } - - public IDictionary ReadEntries(string pathPrefix) - { - return m_reader.ReadEntries(pathPrefix); - } - - public void WriteEntries(IEnumerable> entries) - { - m_writer.WriteEntries(entries); - m_reader.NotifyChanged(); - } - - public void WriteEntry(string key, object value) - { - m_writer.WriteEntry(key, value); - m_reader.NotifyChanged(); - } - - public void Dispose() - { - m_reader.Dispose(); - } - - public string PathKeyCombine(params string[] paths) - { - StringBuilder combinedPath = new StringBuilder(); - foreach(string segment in paths) - { - if (segment != null) - { - string trimmedSegment = segment.TrimEnd(PathSeparator); - if (trimmedSegment.Length > 0) - { - if (combinedPath.Length > 0) - { - combinedPath.Append(PathSeparator); - } - combinedPath.Append(trimmedSegment); - } - } - } - return combinedPath.ToString(); - } - - private static ConcurrentDictionary s_storages = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - - /// - /// Factory method to get a VssFileStorage instance ensuring that we don't have two instances for the same file. - /// - /// The full path to the storage file. Ensure that the path used is in an appropriately secure location for the data you are storing. - /// The separator to use between the path segments of the storage keys. - /// If true the dictionary will use the OrdinalIgnoreCase StringComparer to compare keys. - /// - public static IVssClientStorage GetVssLocalFileStorage(string fullPath, char pathSeparatorForKeys = c_defaultPathSeparator, bool ignoreCaseInPaths = c_defaultIgnoreCaseInPaths) - { - string normalizedFullPath = Path.GetFullPath(fullPath); - VssFileStorage storage = s_storages.GetOrAdd(normalizedFullPath, (key) => new VssFileStorage(key, pathSeparatorForKeys, ignoreCaseInPaths)); - - // we need to throw on mismatch if the cache contains a conflicting instance - if (storage.PathSeparator != pathSeparatorForKeys) - { - throw new ArgumentException(CommonResources.ConflictingPathSeparatorForVssFileStorage(pathSeparatorForKeys, normalizedFullPath, storage.PathSeparator)); - } - - StringComparer pathComparer = GetAppropriateStringComparer(ignoreCaseInPaths); - { - if (storage.PathComparer != pathComparer) - { - string caseSensitive = "Ordinal"; - string caseInsensitive = "OrdinalIgnoreCase"; - string requested = ignoreCaseInPaths ? caseInsensitive : caseSensitive; - string previous = ignoreCaseInPaths ? caseSensitive : caseInsensitive; - throw new ArgumentException(CommonResources.ConflictingStringComparerForVssFileStorage(requested, normalizedFullPath, previous)); - } - } - -#if DEBUG - Debug.Assert(fullPath.Equals(storage.m_filePath), string.Format("The same storage file is being referenced with different casing. This will cause issues when running in cross patform environments where the file system may be case sensitive. {0} != {1}", storage.m_filePath, normalizedFullPath)); -#endif - return storage; - } - - private static StringComparer GetAppropriateStringComparer(bool ignoreCase) - { - return ignoreCase ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; - } - - /// - /// Gets an instance of a VssLocalFileStorage under the current user directory. - /// - /// This pathSuffix will be combined at the end of the current user data directory for VSS to make a full path. Something like: "%localappdata%\Microsoft\VisualStudio Services\[pathSuffix]" - /// Adds the current product version as a path segment. ...\Microsoft\VisualStudio Services\v[GeneratedVersionInfo.ProductVersion]\[pathSuffix]" - /// The separator to use between the path segments of the storage keys. - /// If true the dictionary will use the OrdinalIgnoreCase StringComparer to compare keys. - /// - public static IVssClientStorage GetCurrentUserVssFileStorage(string pathSuffix, bool storeByVssVersion, char pathSeparatorForKeys = c_defaultPathSeparator, bool ignoreCaseInPaths = c_defaultIgnoreCaseInPaths) - { - return GetVssLocalFileStorage(Path.Combine(storeByVssVersion ? ClientSettingsDirectoryByVersion : ClientSettingsDirectory, pathSuffix), pathSeparatorForKeys, ignoreCaseInPaths); - } - - /// - /// Directory containing the client settings files. - /// - /// This will look something like this: - /// C:\Users\[user]\AppData\Local\Microsoft\VisualStudio Services\v[GeneratedVersionInfo.ProductVersion] - /// - internal static string ClientSettingsDirectoryByVersion - { - get - { - // We purposely do not cache this value. This value needs to change if - // Windows Impersonation is being used. - return Path.Combine(ClientSettingsDirectory, "v" + GeneratedVersionInfo.ProductVersion); - } - } - - /// - /// Directory containing the client settings files. - /// - /// This will look something like this: - /// C:\Users\[user]\AppData\Local\Microsoft\VisualStudio Services - /// - internal static string ClientSettingsDirectory - { - get - { - // We purposely do not cache this value. This value needs to change if - // Windows Impersonation is being used. - - // Check to see if we can find the user's local application data directory. - string subDir = "Microsoft\\VisualStudio Services"; - string path = Environment.GetEnvironmentVariable("localappdata"); - SafeGetFolderPath(Environment.SpecialFolder.LocalApplicationData); - if (string.IsNullOrEmpty(path)) - { - // If the user has never logged onto this box they will not have a local application data directory. - // Check to see if they have a roaming network directory that moves with them. - path = SafeGetFolderPath(Environment.SpecialFolder.ApplicationData); - if (string.IsNullOrEmpty(path)) - { - // The user does not have a roaming network directory either. Just place the cache in the - // common area. - // If we are using the common dir, we might not have access to create a folder under "Microsoft" - // so we just create a top level folder. - path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); - subDir = "Microsoft VisualStudio Services"; - } - } - - Debug.Assert(path != null, "folder path cannot be null"); - return Path.Combine(path, subDir); - } - } - - /// - /// Gets folder path and returns null in case the special folder in question doesn't exist (useful when the user has never logged on, which makes - /// GetFolderPath throw) - /// - /// Folder to retrieve - /// Path if available, null othewise - private static string SafeGetFolderPath(Environment.SpecialFolder specialFolder) - { - try - { - return Environment.GetFolderPath(specialFolder); - } - catch (ArgumentException) - { - return null; - } - } - - private class VssFileStorageReader : VssLocalFile, IVssClientStorageReader, IDisposable - { - private readonly string m_path; - private Dictionary m_settings; - - private readonly FileSystemWatcher m_watcher; - private readonly ReaderWriterLockSlim m_lock; - private long m_completedRefreshId; - private long m_outstandingRefreshId; - - public VssFileStorageReader(string fullPath, char pathSeparator, StringComparer comparer) - : base(fullPath, pathSeparator, comparer) - { - m_path = fullPath; - m_lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - m_completedRefreshId = 0; - m_outstandingRefreshId = 1; - - // Set up the file system watcher - { - string directoryToWatch = Path.GetDirectoryName(m_path); - - if (!Directory.Exists(directoryToWatch)) - { - Directory.CreateDirectory(directoryToWatch); - } - - m_watcher = new FileSystemWatcher(directoryToWatch, Path.GetFileName(m_path)); - m_watcher.IncludeSubdirectories = false; - m_watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime; - m_watcher.Changed += OnCacheFileChanged; - m_watcher.EnableRaisingEvents = true; - } - } - - public T ReadEntry(string path) - { - return ReadEntry(path, default(T)); - } - - public T ReadEntry(string path, T defaultValue) - { - path = NormalizePath(path); - RefreshIfNeeded(); - - Dictionary settings = m_settings; // use a pointer to m_settings, incase m_settings gets set to a new instance during the operation - JRaw value; - if (settings.TryGetValue(path, out value) && value != null) - { - return JsonConvert.DeserializeObject(value.ToString()); - } - return defaultValue; - } - - public IDictionary ReadEntries(string pathPrefix) - { - string prefix = NormalizePath(pathPrefix, true); - RefreshIfNeeded(); - Dictionary settings = m_settings; // use a pointer to m_settings, incase m_settings gets set to a new instance during the operation - Dictionary matchingEntries = new Dictionary(); - foreach (KeyValuePair kvp in settings.Where(kvp => kvp.Key == prefix || kvp.Key.StartsWith(prefix + PathSeparator))) - { - try - { - matchingEntries[kvp.Key] = JsonConvert.DeserializeObject(kvp.Value.ToString()); - } - catch (JsonSerializationException) { } - catch (JsonReaderException) { } - } - return matchingEntries; - } - - private void OnCacheFileChanged(object sender, FileSystemEventArgs e) - { - NotifyChanged(); - } - - public void Dispose() - { - m_watcher.Dispose(); - } - - public void NotifyChanged() - { - using (new ReadLockScope(m_lock)) - { - Interlocked.Increment(ref m_outstandingRefreshId); - } - } - - private void RefreshIfNeeded() - { - long requestedRefreshId; - - using (new ReadLockScope(m_lock)) - { - requestedRefreshId = Interlocked.Read(ref m_outstandingRefreshId); - - if (m_completedRefreshId >= requestedRefreshId) - { - return; - } - } - - Dictionary newSettings; - using (GetNewMutexScope()) - { - if (m_completedRefreshId >= requestedRefreshId) - { - return; - } - newSettings = LoadFile(); - } - - using (new ReadLockScope(m_lock)) - { - if (m_completedRefreshId >= requestedRefreshId) - { - return; - } - } - - using (new WriteLockScope(m_lock)) - { - if (m_completedRefreshId >= requestedRefreshId) - { - return; - } - - m_completedRefreshId = requestedRefreshId; - m_settings = newSettings; - } - } - - private struct ReadLockScope : IDisposable - { - public ReadLockScope(ReaderWriterLockSlim @lock) - { - m_lock = @lock; - - m_lock.EnterReadLock(); - } - - public void Dispose() - { - m_lock.ExitReadLock(); - } - - private readonly ReaderWriterLockSlim m_lock; - } - - private struct WriteLockScope : IDisposable - { - public WriteLockScope(ReaderWriterLockSlim @lock) - { - m_lock = @lock; - m_lock.EnterWriteLock(); - } - - public void Dispose() - { - m_lock.ExitWriteLock(); - } - - private readonly ReaderWriterLockSlim m_lock; - } - } - - private class VssFileStorageWriter : VssLocalFile, IVssClientStorageWriter - { - public VssFileStorageWriter(string fullPath, char pathSeparator, StringComparer comparer) - : base(fullPath, pathSeparator, comparer) - { - } - - public void WriteEntries(IEnumerable> entries) - { - if (entries.Any()) - { - using (GetNewMutexScope()) - { - bool changesMade = false; - Dictionary originalSettings = LoadFile(); - Dictionary newSettings = new Dictionary(PathComparer); - if (originalSettings.Any()) - { - originalSettings.Copy(newSettings); - } - foreach (KeyValuePair kvp in entries) - { - string path = NormalizePath(kvp.Key); - if (kvp.Value != null) - { - JRaw jRawValue = new JRaw(JsonConvert.SerializeObject(kvp.Value)); - if (!newSettings.ContainsKey(path) || !newSettings[path].Equals(jRawValue)) - { - newSettings[path] = jRawValue; - changesMade = true; - } - } - else - { - if (newSettings.Remove(path)) - { - changesMade = true; - } - } - } - if (changesMade) - { - SaveFile(originalSettings, newSettings); - } - } - } - } - - public void WriteEntry(string path, object value) - { - WriteEntries(new KeyValuePair[] { new KeyValuePair(path, value) }); - } - } - - private class VssLocalFile - { - private readonly string m_filePath; - private readonly string m_bckUpFilePath; - private readonly string m_emptyPathSegment; - - public VssLocalFile(string filePath, char pathSeparator, StringComparer comparer) - { - m_filePath = filePath; - PathComparer = comparer; - PathSeparator = pathSeparator; - m_emptyPathSegment = new string(pathSeparator, 2); - FileInfo fileInfo = new FileInfo(m_filePath); - m_bckUpFilePath = Path.Combine(fileInfo.Directory.FullName, "~" + fileInfo.Name); - } - - protected char PathSeparator { get; } - - protected string NormalizePath(string path, bool allowRootPath = false) - { - if (string.IsNullOrEmpty(path) || path[0] != PathSeparator || path.IndexOf(m_emptyPathSegment, StringComparison.Ordinal) >= 0 || (!allowRootPath && path.Length == 1)) - { - throw new ArgumentException(CommonResources.InvalidClientStoragePath(path, PathSeparator), "path"); - } - if (path[path.Length - 1] == PathSeparator) - { - path = path.Substring(0, path.Length - 1); - } - return path; - } - - protected StringComparer PathComparer { get; } - - protected Dictionary LoadFile() - { - Dictionary settings = null; - if (File.Exists(m_filePath)) - { - settings = LoadFile(m_filePath); - } - if ((settings == null || !settings.Any()) && File.Exists(m_bckUpFilePath)) - { - settings = LoadFile(m_bckUpFilePath); - } - return settings ?? new Dictionary(PathComparer); - } - - private Dictionary LoadFile(string path) - { - Dictionary settings = new Dictionary(PathComparer); - try - { - string fileContent; - using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) - { - using (var sr = new StreamReader(fs, Encoding.UTF8)) - { - fileContent = sr.ReadToEnd(); - } - } - IReadOnlyDictionary loadedSettings = JsonConvert.DeserializeObject>(fileContent); - if (loadedSettings != null) - { - // Replay the settings into our dictionary one by one so that our uniqueness constraint - // isn't violated based on the StringComparer for this instance. - foreach (KeyValuePair setting in loadedSettings) - { - settings[setting.Key] = setting.Value; - } - } - } - catch (DirectoryNotFoundException) { } - catch (FileNotFoundException) { } - catch (JsonReaderException) { } - catch (JsonSerializationException) { } - catch (InvalidCastException) { } - - return settings; - } - - protected void SaveFile(IDictionary originalSettings, IDictionary newSettings) - { - string newContent = JValue.Parse(JsonConvert.SerializeObject(newSettings)).ToString(Formatting.Indented); - if (originalSettings.Any()) - { - // during testing, creating this backup provided reliability in the event of aborted threads, and - // crashed processes. With this, I was not able to simulate a case where corruption happens, but there is no - // 100% gaurantee against corruption. - string originalContent = JValue.Parse(JsonConvert.SerializeObject(originalSettings)).ToString(Formatting.Indented); - SaveFile(m_bckUpFilePath, originalContent); - } - SaveFile(m_filePath, newContent); - if (File.Exists(m_bckUpFilePath)) - { - File.Delete(m_bckUpFilePath); - } - } - - private void SaveFile(string path, string content) - { - bool success = false; - int tries = 0; - int retryDelayMilliseconds = 10; - const int maxNumberOfRetries = 6; - do - { - try - { - using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Delete)) - { - using (var sw = new StreamWriter(fs, Encoding.UTF8)) - { - sw.Write(content); - } - } - success = true; - } - catch (IOException) - { - if (++tries > maxNumberOfRetries) - { - throw; - } - Task.Delay(retryDelayMilliseconds).Wait(); - retryDelayMilliseconds *= 2; - } - } - while (!success); - } - - protected MutexScope GetNewMutexScope() - { - return new MutexScope(m_filePath.Replace(Path.DirectorySeparatorChar, '_')); - } - - protected struct MutexScope : IDisposable - { - public MutexScope(string name) - { - m_mutex = new Mutex(false, name); - - try - { - if (!m_mutex.WaitOne(s_mutexTimeout)) - { - throw new TimeoutException(); - } - } - catch (AbandonedMutexException) - { - // If this is thrown, then we hold the mutex. - } - } - - public void Dispose() - { - m_mutex.ReleaseMutex(); - } - - private readonly Mutex m_mutex; - private static readonly TimeSpan s_mutexTimeout = TimeSpan.FromSeconds(10); - } - } - } -} diff --git a/src/Sdk/Common/Common/Diagnostics/HttpRequestMessageExtensions.cs b/src/Sdk/Common/Common/Diagnostics/HttpRequestMessageExtensions.cs deleted file mode 100644 index 30279a5c6..000000000 --- a/src/Sdk/Common/Common/Diagnostics/HttpRequestMessageExtensions.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.ComponentModel; -using System.Net.Http; - -namespace GitHub.Services.Common.Diagnostics -{ - [EditorBrowsable(EditorBrowsableState.Never)] - internal static class HttpRequestMessageExtensions - { - public static VssHttpMethod GetHttpMethod(this HttpRequestMessage message) - { - String methodName = message.Method.Method; - VssHttpMethod httpMethod = VssHttpMethod.UNKNOWN; - if (!Enum.TryParse(methodName, true, out httpMethod)) - { - httpMethod = VssHttpMethod.UNKNOWN; - } - return httpMethod; - } - - public static VssTraceActivity GetActivity(this HttpRequestMessage message) - { - Object traceActivity; - if (!message.Properties.TryGetValue(VssTraceActivity.PropertyName, out traceActivity)) - { - return VssTraceActivity.Empty; - } - return (VssTraceActivity)traceActivity; - } - } -} diff --git a/src/Sdk/Common/Common/Diagnostics/VssHttpEventSource.cs b/src/Sdk/Common/Common/Diagnostics/VssHttpEventSource.cs deleted file mode 100644 index ee267cd60..000000000 --- a/src/Sdk/Common/Common/Diagnostics/VssHttpEventSource.cs +++ /dev/null @@ -1,1173 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.Tracing; -using System.Globalization; -using System.Net; -using System.Net.Http; -using System.Net.Sockets; -#if !NETSTANDARD -using System.Diagnostics.Eventing; -#endif - -namespace GitHub.Services.Common.Diagnostics -{ - [EventSource(Name = VssEventSources.Http)] - internal sealed class VssHttpEventSource : EventSource - { - public static class Tasks - { - public const EventTask HttpRequest = (EventTask)1; - public const EventTask Authentication = (EventTask)2; - public const EventTask HttpOperation = (EventTask)3; - } - - public static class Keywords - { - public const EventKeywords Authentication = (EventKeywords)0x0000000000000001; - public const EventKeywords HttpOperation = (EventKeywords)0x0000000000000002; - } - - /// - /// Gets the singleton event source used for logging. - /// - internal static VssHttpEventSource Log - { - get - { - return m_log.Value; - } - } - - [NonEvent] - public void AuthenticationStart(VssTraceActivity activity) - { - if (IsEnabled()) - { - SetActivityId(activity); - AuthenticationStart(); - } - } - - [NonEvent] - public void AuthenticationStop(VssTraceActivity activity) - { - if (IsEnabled()) - { - SetActivityId(activity); - AuthenticationStop(); - } - } - - [NonEvent] - public void AuthenticationError( - VssTraceActivity activity, - IssuedTokenProvider provider, - String message) - { - if (IsEnabled(EventLevel.Error, Keywords.Authentication)) - { - SetActivityId(activity); - WriteMessageEvent(provider.CredentialType, provider.GetHashCode(), message, this.AuthenticationError); - } - } - - [NonEvent] - public void AuthenticationError( - VssTraceActivity activity, - IssuedTokenProvider provider, - Exception exception) - { - if (IsEnabled(EventLevel.Error, Keywords.Authentication)) - { - if (exception is AggregateException) - { - exception = ((AggregateException)exception).Flatten().InnerException; - } - - AuthenticationError(activity, provider, exception.ToString()); - } - } - - [NonEvent] - public void HttpOperationStart( - VssTraceActivity activity, - String area, - String operation) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpOperationStart(area, operation); - } - } - - [NonEvent] - public void HttpOperationStop( - VssTraceActivity activity, - String area, - String operation) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpOperationStop(area, operation); - } - } - - [NonEvent] - public void HttpRequestStart( - VssTraceActivity activity, - HttpRequestMessage request) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestStart(request.GetHttpMethod(), request.RequestUri.AbsoluteUri); - } - } - - [NonEvent] - public Exception HttpRequestFailed( - VssTraceActivity activity, - HttpRequestMessage request, - Exception exception) - { - if (IsEnabled()) - { - HttpRequestFailed(activity, request, exception.ToString()); - } - return exception; - } - - [NonEvent] - public void HttpRequestFailed( - VssTraceActivity activity, - HttpRequestMessage request, - String message) - { - if (IsEnabled()) - { - SetActivityId(activity); - WriteMessageEvent(request.GetHttpMethod(), request.RequestUri.AbsoluteUri, message, this.HttpRequestFailed); - } - } - - [NonEvent] - public void HttpRequestFailed( - VssTraceActivity activity, - HttpRequestMessage request, - HttpStatusCode statusCode, - string afdRefInfo) - { - if (IsEnabled()) - { - SetActivityId(activity); - CultureInfo cultureInfo = CultureInfo.InstalledUICulture; - String message = String.Format(cultureInfo, "HTTP Status: {0}", statusCode); - - if (!string.IsNullOrEmpty(afdRefInfo)) - { - message += $", AFD Ref: {afdRefInfo}"; - } - - WriteMessageEvent(request.GetHttpMethod(), request.RequestUri.AbsoluteUri, message, this.HttpRequestFailed); - } - } - - [NonEvent] - public void HttpRequestUnauthorized( - VssTraceActivity activity, - HttpRequestMessage request, - String message) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestUnauthorized(request.GetHttpMethod(), request.RequestUri.AbsoluteUri, message); - } - } - - [NonEvent] - public void HttpRequestSucceeded( - VssTraceActivity activity, - HttpResponseMessage response) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestSucceeded(response.RequestMessage.GetHttpMethod(), response.RequestMessage.RequestUri.AbsoluteUri, (Int32)response.StatusCode); - } - } - - [NonEvent] - public void HttpRequestRetrying( - VssTraceActivity activity, - HttpRequestMessage request, - Int32 attempt, - TimeSpan backoffDuration, - HttpStatusCode? httpStatusCode, - WebExceptionStatus? webExceptionStatus, - SocketError? socketErrorCode, - WinHttpErrorCode? winHttpErrorCode, - CurlErrorCode? curlErrorCode, - string afdRefInfo) - { - if (IsEnabled()) - { - String reason = ""; - if (httpStatusCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "HTTP Status: {0}", httpStatusCode.Value); - } - else if (webExceptionStatus != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "Web Exception Status: {0}", webExceptionStatus.Value); - } - else if (socketErrorCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "Socket Error: {0}", socketErrorCode.Value); - } - else if (winHttpErrorCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "WinHttp Error: {0}", winHttpErrorCode); - } - else if (curlErrorCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "Curl Error: {0}", curlErrorCode); - } - - if (!string.IsNullOrEmpty(afdRefInfo)) - { - reason += $", AFD Ref: {afdRefInfo}"; - } - - SetActivityId(activity); - HttpRequestRetrying(request.GetHttpMethod(), request.RequestUri.AbsoluteUri, attempt, reason, backoffDuration.TotalSeconds); - } - } - - [NonEvent] - public void HttpRequestFailedMaxAttempts( - VssTraceActivity activity, - HttpRequestMessage request, - Int32 attempt, - HttpStatusCode? httpStatusCode, - WebExceptionStatus? webExceptionStatus, - SocketError? socketErrorCode, - WinHttpErrorCode? winHttpErrorCode, - CurlErrorCode? curlErrorCode, - string afdRefInfo) - { - if (IsEnabled()) - { - String reason = ""; - if (httpStatusCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "HTTP Status: {0}", httpStatusCode.Value); - } - else if (webExceptionStatus != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "Web Exception Status: {0}", webExceptionStatus.Value); - } - else if (socketErrorCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "Socket Error: {0}", socketErrorCode.Value); - } - else if (winHttpErrorCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "WinHttp Error: {0}", winHttpErrorCode); - } - else if (curlErrorCode != null) - { - reason = String.Format(CultureInfo.InvariantCulture, "Curl Error: {0}", curlErrorCode); - } - - if (!string.IsNullOrEmpty(afdRefInfo)) - { - reason += $", AFD Ref: {afdRefInfo}"; - } - - SetActivityId(activity); - HttpRequestFailedMaxAttempts(request.GetHttpMethod(), request.RequestUri.AbsoluteUri, attempt, reason); - } - } - - [NonEvent] - public void HttpRequestSucceededWithRetry( - VssTraceActivity activity, - HttpResponseMessage response, - Int32 attempt) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestSucceededWithRetry(response.RequestMessage.GetHttpMethod(), response.RequestMessage.RequestUri.AbsoluteUri, attempt); - } - } - - [NonEvent] - public void HttpRequestCancelled( - VssTraceActivity activity, - HttpRequestMessage request) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestCancelled(request.GetHttpMethod(), request.RequestUri.AbsoluteUri); - } - } - - [NonEvent] - public void HttpRequestTimedOut( - VssTraceActivity activity, - HttpRequestMessage request, - TimeSpan timeout) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestTimedOut(request.GetHttpMethod(), request.RequestUri.AbsoluteUri, (Int32)timeout.TotalSeconds); - } - } - - [NonEvent] - public void HttpRequestStop( - VssTraceActivity activity, - HttpResponseMessage response) - { - if (IsEnabled()) - { - SetActivityId(activity); - HttpRequestStop(response.RequestMessage.GetHttpMethod(), response.RequestMessage.RequestUri.AbsoluteUri, (Int32)response.StatusCode); - } - } - - [NonEvent] - public void AuthenticationFailed( - VssTraceActivity activity, - HttpResponseMessage response) - { - if (IsEnabled()) - { - SetActivityId(activity); - WriteMessageEvent((Int32)response.StatusCode, response.Headers.ToString(), this.AuthenticationFailed); - } - } - - [NonEvent] - public void IssuedTokenProviderCreated( - VssTraceActivity activity, - IssuedTokenProvider provider) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenProviderCreated(provider.CredentialType, provider.GetHashCode(), provider.GetAuthenticationParameters()); - } - } - - [NonEvent] - public void IssuedTokenProviderRemoved( - VssTraceActivity activity, - IssuedTokenProvider provider) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenProviderRemoved(provider.CredentialType, provider.GetHashCode(), provider.GetAuthenticationParameters()); - } - } - - [NonEvent] - internal void IssuedTokenProviderNotFound(VssTraceActivity activity) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenProviderNotFound(); - } - } - - [NonEvent] - internal void IssuedTokenProviderPromptRequired( - VssTraceActivity activity, - IssuedTokenProvider provider) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenProviderPromptRequired(provider.CredentialType, provider.GetHashCode()); - } - } - - [NonEvent] - public void IssuedTokenAcquiring( - VssTraceActivity activity, - IssuedTokenProvider provider) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenAcquiring(provider.CredentialType, provider.GetHashCode()); - } - } - - [NonEvent] - public void IssuedTokenWaitStart( - VssTraceActivity activity, - IssuedTokenProvider provider, - Guid waitForActivityId) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - SetActivityId(activity); - IssuedTokenWaitStart(provider.CredentialType, provider.GetHashCode(), waitForActivityId); - } - } - - [NonEvent] - public void IssuedTokenWaitStop( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken token) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - SetActivityId(activity); - IssuedTokenWaitStop(provider.CredentialType, provider.GetHashCode(), token != null ? token.GetHashCode() : 0); - } - } - - [NonEvent] - public void IssuedTokenAcquired( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken token) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenAcquired(provider.CredentialType, provider.GetHashCode(), token != null ? token.GetHashCode() : 0); - } - } - - [NonEvent] - public void IssuedTokenInvalidated( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken token) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenInvalidated(provider.CredentialType, provider.GetHashCode(), token.GetHashCode()); - } - } - - [NonEvent] - public void IssuedTokenValidated( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken token) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenValidated(provider.CredentialType, provider.GetHashCode(), token.GetHashCode()); - } - } - - [NonEvent] - public void IssuedTokenRetrievedFromCache( - VssTraceActivity activity, - IssuedTokenProvider provider, - IssuedToken token) - { - if (IsEnabled()) - { - SetActivityId(activity); - IssuedTokenRetrievedFromCache(provider.CredentialType, provider.GetHashCode(), token.GetHashCode()); - } - } - - [Event(1, Level = EventLevel.Verbose, Task = Tasks.HttpRequest, Opcode = EventOpcode.Start, Message = "Started {0} request to {1}")] - private void HttpRequestStart( - VssHttpMethod method, - String url) - { - if (IsEnabled()) - { - WriteEvent(1, (Int32)method, url); - } - } - - [Event(2, Level = EventLevel.Error, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "{0} request to {1} failed. {2}")] - private void HttpRequestFailed( - VssHttpMethod method, - String url, - String message) - { - if (IsEnabled()) - { - WriteEvent(2, (Int32)method, url, message); - } - } - - [Event(3, Level = EventLevel.Informational, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "{0} request to {1} succeeded with status code {2}")] - private void HttpRequestSucceeded( - VssHttpMethod method, - String url, - Int32 statusCode) - { - if (IsEnabled()) - { - WriteEvent(3, (Int32)method, url, statusCode); - } - } - - [Event(4, Level = EventLevel.Warning, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "Attempt {2} of {0} request to {1} failed ({3}). The operation will be retried in {4} seconds.")] - private void HttpRequestRetrying( - VssHttpMethod method, - String url, - Int32 attempt, - String reason, - Double backoffDurationInSeconds) - { - if (IsEnabled()) - { - WriteEvent(4, (Int32)method, url, attempt, reason, backoffDurationInSeconds); - } - } - - [Event(5, Level = EventLevel.Error, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "Attempt {2} of {0} request to {1} failed ({3}). The maximum number of attempts has been reached.")] - private void HttpRequestFailedMaxAttempts( - VssHttpMethod method, - String url, - Int32 attempt, - String reason) - { - if (IsEnabled()) - { - WriteEvent(5, (Int32)method, url, attempt, reason); - } - } - - [Event(6, Level = EventLevel.Verbose, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "Attempt {2} of {0} request to {1} succeeded.")] - private void HttpRequestSucceededWithRetry( - VssHttpMethod method, - String url, - Int32 attempt) - { - if (IsEnabled()) - { - WriteEvent(6, (Int32)method, url, attempt); - } - } - - [Event(7, Level = EventLevel.Warning, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "{0} request to {1} has been cancelled.")] - private void HttpRequestCancelled( - VssHttpMethod method, - String url) - { - if (IsEnabled()) - { - WriteEvent(7, (Int32)method, url); - } - } - - [Event(8, Level = EventLevel.Warning, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "{0} request to {1} timed out after {2} seconds.")] - private void HttpRequestTimedOut( - VssHttpMethod method, - String url, - Int32 timeoutInSeconds) - { - if (IsEnabled()) - { - WriteEvent(8, (Int32)method, url, timeoutInSeconds); - } - } - - [Event(9, Level = EventLevel.Error, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "{0} request to {1} is not authorized. Details: {2}")] - private void HttpRequestUnauthorized( - VssHttpMethod method, - String url, - String message) - { - if (IsEnabled()) - { - WriteEvent(9, (Int32)method, url, message); - } - } - - [Event(10, Keywords = Keywords.Authentication, Level = EventLevel.Warning, Task = Tasks.HttpRequest, Message = "Authentication failed with status code {0}.%n{1}")] - private void AuthenticationFailed( - Int32 statusCode, - String headers) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(10, statusCode, headers); - } - } - - [Event(11, Keywords = Keywords.Authentication, Level = EventLevel.Informational, Task = Tasks.HttpRequest, Message = "Authentication successful using {0} credentials")] - private void AuthenticationSucceeded(VssCredentialsType credentialsType) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(11, (Int32)credentialsType); - } - } - - [Event(12, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Opcode = EventOpcode.Start, Message = "Started authentication")] - private void AuthenticationStart() - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(12); - } - } - - [Event(13, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "Created {0} issued token provider instance {1} ({2})")] - private void IssuedTokenProviderCreated( - VssCredentialsType credentialsType, - Int32 providerId, - String parameters) - { - if (IsEnabled()) - { - WriteEvent(13, (Int32)credentialsType, providerId, parameters); - } - } - - [Event(14, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "Removed {0} issued token provider instance {1} ({2})")] - private void IssuedTokenProviderRemoved( - VssCredentialsType credentialsType, - Int32 providerId, - String parameters) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(14, (Int32)credentialsType, providerId, parameters); - } - } - - [Event(15, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "{0} issued token provider instance {1} is acquiring a token")] - private void IssuedTokenAcquiring( - VssCredentialsType credentialsType, - Int32 providerId) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(15, (Int32)credentialsType, providerId); - } - } - - [Event(16, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Opcode = EventOpcode.Suspend, Message = "{0} issued token provider instance {1} is waiting for issued token from activity {2}")] - private void IssuedTokenWaitStart( - VssCredentialsType credentialsType, - Int32 providerId, - Guid waitForActivityId) - { - WriteEvent(16, (Int32)credentialsType, providerId, waitForActivityId); - } - - [Event(17, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Opcode = EventOpcode.Resume, Message = "{0} issued token provider instance {1} received token instance {2}")] - private void IssuedTokenWaitStop( - VssCredentialsType credentialsType, - Int32 providerId, - Int32 issuedTokenId) - { - WriteEvent(17, (Int32)credentialsType, providerId, issuedTokenId); - } - - [Event(18, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "{0} issued token provider instance {1} acquired new token instance {2}")] - private void IssuedTokenAcquired( - VssCredentialsType credentialsType, - Int32 providerId, - Int32 issuedTokenId) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(18, (Int32)credentialsType, providerId, issuedTokenId); - } - } - - [Event(20, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "{0} issued token provider instance {1} invalidated token instance {2}")] - private void IssuedTokenInvalidated( - VssCredentialsType credentialsType, - Int32 providerId, - Int32 issuedTokenId) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(20, (Int32)credentialsType, providerId, issuedTokenId); - } - } - - [Event(21, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "{0} issued token provider instance {1} validated token instance {2}")] - private void IssuedTokenValidated( - VssCredentialsType credentialsType, - Int32 providerId, - Int32 issuedTokenId) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(21, (Int32)credentialsType, providerId, issuedTokenId); - } - } - - [Event(22, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Message = "{0} issued token provider instance {1} retrieved token instance {2}")] - private void IssuedTokenRetrievedFromCache( - VssCredentialsType credentialsType, - Int32 providerId, - Int32 issuedTokenId) - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(22, (Int32)credentialsType, providerId, issuedTokenId); - } - } - - [Event(23, Keywords = Keywords.Authentication, Level = EventLevel.Verbose, Task = Tasks.Authentication, Opcode = EventOpcode.Stop, Message = "Finished authentication")] - private void AuthenticationStop() - { - if (IsEnabled(EventLevel.Verbose, Keywords.Authentication)) - { - WriteEvent(23); - } - } - - [Event(24, Level = EventLevel.Verbose, Task = Tasks.HttpRequest, Opcode = EventOpcode.Stop, Message = "Finished {0} request to {1} with status code {2}")] - private void HttpRequestStop( - VssHttpMethod method, - String url, - Int32 statusCode) - { - if (IsEnabled()) - { - WriteEvent(24, (Int32)method, url, statusCode); - } - } - - [Event(25, Keywords = Keywords.HttpOperation, Level = EventLevel.Informational, Task = Tasks.HttpOperation, Opcode = EventOpcode.Start, Message = "Starting operation {0}.{1}")] - private void HttpOperationStart( - String area, - String operation) - { - if (IsEnabled(EventLevel.Informational, Keywords.HttpOperation)) - { - WriteEvent(25, area, operation); - } - } - - [Event(26, Keywords = Keywords.HttpOperation, Level = EventLevel.Informational, Task = Tasks.HttpOperation, Opcode = EventOpcode.Stop, Message = "Finished operation {0}.{1}")] - private void HttpOperationStop( - String area, - String operation) - { - if (IsEnabled(EventLevel.Informational, Keywords.HttpOperation)) - { - WriteEvent(26, area, operation); - } - } - - [Event(27, Keywords = Keywords.Authentication, Level = EventLevel.Error, Task = Tasks.Authentication, Opcode = EventOpcode.Info, Message = "{0} issued token provider instance {1} failed to retrieve a token.%nReason: {2}")] - private void AuthenticationError( - VssCredentialsType credentialsType, - Int32 providerId, - String message) - { - if (IsEnabled(EventLevel.Error, Keywords.Authentication)) - { - WriteEvent(27, (Int32)credentialsType, providerId, message); - } - } - - [Event(28, Keywords = Keywords.Authentication, Level = EventLevel.Warning, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "No issued token provider found which can handle the authentication challenge")] - private void IssuedTokenProviderNotFound() - { - if (IsEnabled(EventLevel.Warning, Keywords.Authentication)) - { - WriteEvent(28); - } - } - - [Event(29, Keywords = Keywords.Authentication, Level = EventLevel.Warning, Task = Tasks.HttpRequest, Opcode = EventOpcode.Info, Message = "{0} issued token provider instance {1} requires an interactive prompt which is not allowed by the current settings")] - private void IssuedTokenProviderPromptRequired( - VssCredentialsType credentialsType, - Int32 providerId) - { - if (IsEnabled(EventLevel.Warning, Keywords.Authentication)) - { - WriteEvent(29, (Int32)credentialsType, providerId); - } - } - - [Event(30, Keywords = Keywords.HttpOperation, Level = EventLevel.Critical, Task = Tasks.HttpOperation, Opcode = EventOpcode.Info, Message = "A task completion source was not properly completed during authentication")] - public void TokenSourceNotCompleted() - { - if (IsEnabled(EventLevel.Critical, Keywords.HttpOperation)) - { - WriteEvent(30); - } - } - - [Event(31, Keywords = Keywords.Authentication, Level = EventLevel.Warning, Task = Tasks.Authentication, Opcode = EventOpcode.Info, Message = "Retrieving an AAD auth token took a long time ({0} seconds)")] - public void AuthorizationDelayed(string timespan) - { - if(IsEnabled(EventLevel.Warning, Keywords.Authentication)) - { - WriteEvent(31, timespan); - } - } - - [Event(32, Keywords = Keywords.Authentication, Level = EventLevel.Informational, Task = Tasks.Authentication, Opcode = EventOpcode.Info, Message = "AAD Correlation ID for this token request: {0}")] - public void AADCorrelationID(string aadCorrelationId) - { - if (IsEnabled(EventLevel.Informational, Keywords.Authentication)) - { - WriteEvent(32, aadCorrelationId); - } - } - - /// - /// Sets the activity ID of the current thread. - /// - /// The trace activity which should be active on the calling thread - [NonEvent] - private void SetActivityId(VssTraceActivity activity) - { -#if !NETSTANDARD - if (activity != null) - { - Guid activityId = activity.Id; - EventProvider.SetActivityId(ref activityId); - } -#endif - } - - [NonEvent] - private static IList SplitMessage(String message) - { - List list = new List(); - if (message.Length > 30000) - { - int num = 0; - do - { - Int32 num2 = (message.Length - num > 30000) ? 30000 : (message.Length - num); - list.Add(message.Substring(num, num2)); - num += num2; - } - while (message.Length > num); - } - else - { - list.Add(message); - } - return list; - } - - [NonEvent] - private void WriteMessageEvent( - Int32 param0, - String message, - Action writeEvent) - { - writeEvent(param0, message); -#if !NETSTANDARD - if (EventProvider.GetLastWriteEventError() == EventProvider.WriteEventErrorCode.EventTooBig) - { - foreach (String messagePart in SplitMessage(message)) - { - writeEvent(param0, messagePart); - } - } -#endif - } - - [NonEvent] - private void WriteMessageEvent( - VssCredentialsType param0, - Int32 param1, - String message, - Action writeEvent) - { - writeEvent(param0, param1, message); -#if !NETSTANDARD - if (EventProvider.GetLastWriteEventError() == EventProvider.WriteEventErrorCode.EventTooBig) - { - foreach (String messagePart in SplitMessage(message)) - { - writeEvent(param0, param1, messagePart); - } - } -#endif - } - - [NonEvent] - private void WriteMessageEvent( - VssHttpMethod param0, - String param1, - String message, - Action writeEvent) - { - writeEvent(param0, param1, message); -#if !NETSTANDARD - if (EventProvider.GetLastWriteEventError() == EventProvider.WriteEventErrorCode.EventTooBig) - { - foreach (String messagePart in SplitMessage(message)) - { - writeEvent(param0, param1, messagePart); - } - } -#endif - } - - [NonEvent] -#if !NETSTANDARD - private unsafe void WriteEvent( -#else - private new unsafe void WriteEvent( -#endif - Int32 eventId, - Int32 param0, - String param1) - { - param1 = param1 ?? String.Empty; - - Int32 eventDataCount = 2; - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = (Int32)(param1.Length + 1) * sizeof(Char); - - fixed (Char* a1 = param1) - { - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)a1; - base.WriteEventCore(eventId, eventDataCount, eventData); - } - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - String param1, - String param2) - { - param1 = param1 ?? String.Empty; - param2 = param2 ?? String.Empty; - - Int32 eventDataCount = 3; - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = (Int32)(param1.Length + 1) * sizeof(Char); - eventData[2].Size = (Int32)(param2.Length + 1) * sizeof(Char); - - fixed (Char* a1 = param1, a2 = param2) - { - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)a1; - eventData[2].DataPointer = (IntPtr)a2; - base.WriteEventCore(eventId, eventDataCount, eventData); - } - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - Int32 param1, - Guid param2) - { - Int32 eventDataCount = 3; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = sizeof(Int32); - eventData[2].Size = sizeof(Guid); - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)(¶m1); - eventData[2].DataPointer = (IntPtr)(¶m2); - base.WriteEventCore(eventId, eventDataCount, eventData); - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - Int32 param1, - String param2) - { - param2 = param2 ?? String.Empty; - - Int32 eventDataCount = 3; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = sizeof(Int32); - eventData[2].Size = (Int32)(param2.Length + 1) * sizeof(Char); - fixed (Char* a2 = param2) - { - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)(¶m1); - eventData[2].DataPointer = (IntPtr)a2; - base.WriteEventCore(eventId, eventDataCount, eventData); - } - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - String param1, - Int32 param2) - { - param1 = param1 ?? String.Empty; - - Int32 eventDataCount = 3; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = (Int32)(param1.Length + 1) * sizeof(Char); - eventData[2].Size = sizeof(Int32); - fixed (Char* a1 = param1) - { - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)a1; - eventData[2].DataPointer = (IntPtr)(¶m2); - base.WriteEventCore(eventId, eventDataCount, eventData); - } - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - Int32 param1, - Int32 param2, - Guid param3) - { - Int32 eventDataCount = 4; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = sizeof(Int32); - eventData[2].Size = sizeof(Int32); - eventData[3].Size = sizeof(Guid); - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)(¶m1); - eventData[2].DataPointer = (IntPtr)(¶m2); - eventData[3].DataPointer = (IntPtr)(¶m3); - base.WriteEventCore(eventId, eventDataCount, eventData); - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - Int32 param1, - Guid param2, - Guid param3) - { - Int32 eventDataCount = 4; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = sizeof(Int32); - eventData[2].Size = sizeof(Guid); - eventData[3].Size = sizeof(Guid); - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)(¶m1); - eventData[2].DataPointer = (IntPtr)(¶m2); - eventData[3].DataPointer = (IntPtr)(¶m3); - base.WriteEventCore(eventId, eventDataCount, eventData); - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - String param1, - Int32 param2, - String param3) - { - param1 = param1 ?? String.Empty; - param3 = param3 ?? String.Empty; - - Int32 eventDataCount = 4; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = (Int32)(param1.Length + 1) * sizeof(Char); - eventData[2].Size = sizeof(Int32); - eventData[3].Size = (Int32)(param3.Length + 1) * sizeof(Char); - fixed (Char* a1 = param1, a3 = param3) - { - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)a1; - eventData[2].DataPointer = (IntPtr)(¶m2); - eventData[3].DataPointer = (IntPtr)a3; - base.WriteEventCore(eventId, eventDataCount, eventData); - } - } - - [NonEvent] - private unsafe void WriteEvent( - Int32 eventId, - Int32 param0, - String param1, - Int32 param2, - String param3, - Double param4) - { - param1 = param1 ?? String.Empty; - param3 = param3 ?? String.Empty; - - Int32 eventDataCount = 5; - - Byte* userData = stackalloc Byte[sizeof(EventData) * eventDataCount]; - EventData* eventData = (EventData*)userData; - - eventData[0].Size = sizeof(Int32); - eventData[1].Size = (Int32)(param1.Length + 1) * sizeof(Char); - eventData[2].Size = sizeof(Int32); - eventData[3].Size = (Int32)(param3.Length + 1) * sizeof(Char); - eventData[4].Size = sizeof(Double); - fixed (Char* a1 = param1, a3 = param3) - { - eventData[0].DataPointer = (IntPtr)(¶m0); - eventData[1].DataPointer = (IntPtr)a1; - eventData[2].DataPointer = (IntPtr)(¶m2); - eventData[3].DataPointer = (IntPtr)a3; - eventData[4].DataPointer = (IntPtr)(¶m4); - base.WriteEventCore(eventId, eventDataCount, eventData); - } - } - - private static Lazy m_log = new Lazy(() => new VssHttpEventSource()); - } - - public static class VssEventSources - { - public const String Http = "Microsoft-VSS-Http"; - } -} diff --git a/src/Sdk/Common/Common/Diagnostics/VssHttpMethod.cs b/src/Sdk/Common/Common/Diagnostics/VssHttpMethod.cs deleted file mode 100644 index 03f3fac1e..000000000 --- a/src/Sdk/Common/Common/Diagnostics/VssHttpMethod.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace GitHub.Services.Common.Diagnostics -{ - internal enum VssHttpMethod - { - UNKNOWN, - DELETE, - HEAD, - GET, - OPTIONS, - PATCH, - POST, - PUT, - } -} diff --git a/src/Sdk/Common/Common/Diagnostics/VssTraceActivity.cs b/src/Sdk/Common/Common/Diagnostics/VssTraceActivity.cs deleted file mode 100644 index b222f1a2f..000000000 --- a/src/Sdk/Common/Common/Diagnostics/VssTraceActivity.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Diagnostics; -#if !NETSTANDARD -using System.Runtime.Remoting.Messaging; -#endif -using System.Runtime.Serialization; - -namespace GitHub.Services.Common.Diagnostics -{ - /// - /// Represents a trace activity for correlating diagnostic traces together. - /// - [DataContract] - [Serializable] - public sealed class VssTraceActivity - { - private VssTraceActivity() - { - } - - private VssTraceActivity(Guid activityId) - { - this.Id = activityId; - } - - /// - /// Gets the unique identifier for the trace activity. - /// - [DataMember] - public Guid Id - { - get; - private set; - } - - /// - /// Gets the current trace activity if one is set on the current thread; otherwise, null. - /// - public static VssTraceActivity Current - { -#if !NETSTANDARD - get - { - return CallContext.LogicalGetData(VssTraceActivity.PropertyName) as VssTraceActivity; - } - private set - { - CallContext.LogicalSetData(VssTraceActivity.PropertyName, value); - } -#else - get - { - return null; - } - set { } -#endif - } - - /// - /// Gets the empty trace activity. - /// - public static VssTraceActivity Empty - { - get - { - return s_empty.Value; - } - } - - /// - /// Creates a disposable trace scope in which the current trace activity is activated for trace correlation. - /// The call context state for is updated within the scope to reference - /// the activated activity. - /// - /// A trace scope for correlating multiple traces together - public IDisposable EnterCorrelationScope() - { - return new CorrelationScope(this); - } - - /// - /// Gets the current activity or, if no activity is active on the current thread, creates a new activity for - /// trace correlation. - /// - /// The current trace activity or a new trace activity - public static VssTraceActivity GetOrCreate() - { - if (VssTraceActivity.Current != null) - { - return VssTraceActivity.Current; - } - else if (Trace.CorrelationManager.ActivityId == Guid.Empty) - { - return new VssTraceActivity(Guid.NewGuid()); - } - else - { - return new VssTraceActivity(Trace.CorrelationManager.ActivityId); - } - } - - /// - /// Creates a new trace activity optionally using the provided identifier. - /// - /// The activity identifier or none to have one generated - /// A new trace activity instance - public static VssTraceActivity New(Guid activityId = default(Guid)) - { - return new VssTraceActivity(activityId == default(Guid) ? Guid.NewGuid() : activityId); - } - - /// - /// Gets the property name used to cache this object on extensible objects. - /// - public const String PropertyName = "MS.VSS.Diagnostics.TraceActivity"; - private static Lazy s_empty = new Lazy(() => new VssTraceActivity(Guid.Empty)); - - private sealed class CorrelationScope : IDisposable - { - public CorrelationScope(VssTraceActivity activity) - { - m_previousActivity = VssTraceActivity.Current; - if (m_previousActivity == null || m_previousActivity.Id != activity.Id) - { - m_swap = true; - VssTraceActivity.Current = activity; - } - } - - public void Dispose() - { - if (m_swap) - { - try - { - m_swap = false; - } - finally - { - // Perform in a finally block to ensure consistency between the two variables - VssTraceActivity.Current = m_previousActivity; - } - } - } - - private Boolean m_swap; - private VssTraceActivity m_previousActivity; - } - } -} diff --git a/src/Sdk/Common/Common/ExceptionMappingAttribute.cs b/src/Sdk/Common/Common/ExceptionMappingAttribute.cs deleted file mode 100644 index 6c64e5828..000000000 --- a/src/Sdk/Common/Common/ExceptionMappingAttribute.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.ComponentModel; - -namespace GitHub.Services.Common -{ - /// - /// Matches Exception Types to back compatible TypeName and TypeKey for the specified range - /// of REST Api versions. This allows the current server to send back compatible typename - /// and type key json when talking to older clients. It also allows current clients to translate - /// exceptions returned from older servers to a current client's exception type. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class ExceptionMappingAttribute : Attribute - { - /// - /// Matches Exception Types to back compatible TypeName and TypeKey for the specified range - /// of REST Api versions. This allows the current server to send back compatible typename - /// and type key json when talking to older clients. It also allows current clients to translate - /// exceptions returned from older servers to a current client's exception type. - /// - /// The inclusive minimum REST Api version for this mapping. - /// The exclusive maximum REST Api version for this mapping. - /// The original typekey to be returned by the server when processing requests within the REST Api range specified. - /// The original typeName to be returned by the server when processing requests within the REST Api range specified. - public ExceptionMappingAttribute(string minApiVersion, string exclusiveMaxApiVersion, string typeKey, string typeName) - { - MinApiVersion = new Version(minApiVersion); - ExclusiveMaxApiVersion = new Version(exclusiveMaxApiVersion); - TypeKey = typeKey; - TypeName = typeName; - } - - /// - /// The inclusive minimum REST Api version for this mapping. - /// - public Version MinApiVersion { get; private set; } - - /// - /// The exclusive maximum REST Api version for this mapping. - /// - public Version ExclusiveMaxApiVersion { get; private set; } - - /// - /// The original typekey to be returned by the server when processing requests within the REST Api range specified. - /// - public string TypeKey { get; private set; } - - /// - /// The original typeName to be returned by the server when processing requests within the REST Api range specified. - /// - public string TypeName { get; private set; } - } -} diff --git a/src/Sdk/Common/Common/Exceptions/AuthenticationExceptions.cs b/src/Sdk/Common/Common/Exceptions/AuthenticationExceptions.cs deleted file mode 100644 index 48e85fa3b..000000000 --- a/src/Sdk/Common/Common/Exceptions/AuthenticationExceptions.cs +++ /dev/null @@ -1,58 +0,0 @@ -using GitHub.Services.Common.Internal; -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; - -namespace GitHub.Services.Common -{ - [Serializable] - [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] - [ExceptionMapping("0.0", "3.0", "VssAuthenticationException", "GitHub.Services.Common.VssAuthenticationException, GitHub.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssAuthenticationException : VssException - { - public VssAuthenticationException() - { - } - - public VssAuthenticationException(String message) - : base(message) - { - } - - public VssAuthenticationException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected VssAuthenticationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] - [ExceptionMapping("0.0", "3.0", "VssUnauthorizedException", "GitHub.Services.Common.VssUnauthorizedException, GitHub.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssUnauthorizedException : VssException - { - public VssUnauthorizedException() - : this(CommonResources.VssUnauthorizedUnknownServer()) - { - } - - public VssUnauthorizedException(String message) - : base(message) - { - } - - public VssUnauthorizedException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected VssUnauthorizedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Sdk/Common/Common/Exceptions/CommonExceptions.cs b/src/Sdk/Common/Common/Exceptions/CommonExceptions.cs deleted file mode 100644 index 7960517a0..000000000 --- a/src/Sdk/Common/Common/Exceptions/CommonExceptions.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; - -namespace GitHub.Services.Common -{ - /// - /// Thrown when a config file fails to load - /// - /// Initializes an exception from serialized data - /// - /// object holding the serialized data - /// context info about the source or destination - protected VssServiceException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - /// - /// Gets the type name and key for serialization of this exception. - /// If not provided, the serializer will provide default values. - /// - public virtual void GetTypeNameAndKey(Version restApiVersion, out String typeName, out String typeKey) - { - GetTypeNameAndKeyForExceptionType(GetType(), restApiVersion, out typeName, out typeKey); - } - } -} diff --git a/src/Sdk/Common/Common/Exceptions/PropertyExceptions.cs b/src/Sdk/Common/Common/Exceptions/PropertyExceptions.cs deleted file mode 100644 index 34c97b73a..000000000 --- a/src/Sdk/Common/Common/Exceptions/PropertyExceptions.cs +++ /dev/null @@ -1,63 +0,0 @@ -using GitHub.Services.Common.Internal; -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; -using System.Security; - -namespace GitHub.Services.Common -{ - /// - /// Thrown when validating user input. Similar to ArgumentException but doesn't require the property to be an input parameter. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssPropertyValidationException", "GitHub.Services.Common.VssPropertyValidationException, GitHub.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssPropertyValidationException : VssServiceException - { - public VssPropertyValidationException(String propertyName, String message) - : base(message) - { - PropertyName = propertyName; - } - - public VssPropertyValidationException(String propertyName, String message, Exception innerException) - : base(message, innerException) - { - PropertyName = propertyName; - } - - protected VssPropertyValidationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - PropertyName = info.GetString("PropertyName"); - } - - public String PropertyName { get; set; } - - [SecurityCritical] - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - info.AddValue("PropertyName", PropertyName); - } - } - - /// - /// PropertyTypeNotSupportedException - this is thrown when a type is DBNull or an Object type other than a Byte array. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "PropertyTypeNotSupportedException", "GitHub.Services.Common.PropertyTypeNotSupportedException, GitHub.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class PropertyTypeNotSupportedException : VssPropertyValidationException - { - public PropertyTypeNotSupportedException(String propertyName, Type type) - : base(propertyName, CommonResources.VssUnsupportedPropertyValueType(propertyName, type.FullName)) - { - } - - protected PropertyTypeNotSupportedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Sdk/Common/Common/GenerateConstantAttributes.cs b/src/Sdk/Common/Common/GenerateConstantAttributes.cs deleted file mode 100644 index a976d6cdd..000000000 --- a/src/Sdk/Common/Common/GenerateConstantAttributes.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Microsoft Confidential -// Copyright (c) Microsoft Corporation. All rights reserved. - -using System; -using System.ComponentModel; - -namespace GitHub.Services.Common -{ - /// - /// Base class for constant generation. Allows types/fields to be generated - /// with an alternate name. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public abstract class GenerateConstantAttributeBase : Attribute - { - protected GenerateConstantAttributeBase(string alternateName = null) - { - AlternateName = alternateName; - } - - public string AlternateName { get; private set; } - } - - /// - /// Can be applied to a const/readonly-static field of a class/enum/struct, but is - /// only used when the containing type has the 'GenerateSpecificConstants' attribute applied. - /// This allows the developer to specify exactly what constants to include out of the containing type. - /// - [AttributeUsage(AttributeTargets.Field)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class GenerateConstantAttribute : GenerateConstantAttributeBase - { - public GenerateConstantAttribute(string alternateName = null) - : base(alternateName) - { - } - } - - /// - /// Applied to any enum/class/struct. Causes the constants generator to create javascript constants - /// for all const/readonly-static fields contained by the type. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class GenerateAllConstantsAttribute : GenerateConstantAttribute - { - public GenerateAllConstantsAttribute(string alternateName = null) - : base(alternateName) - { - } - } - - /// - /// Applied to any enum/class/struct. Causes the constants generator to create javascript constants at runtime - /// for the type for any member constants/enumerated values that are tagged with the 'GenerateConstant' attribute. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class GenerateSpecificConstantsAttribute : GenerateConstantAttribute - { - public GenerateSpecificConstantsAttribute(string alternateName = null) - : base(alternateName) - { - } - } - - /// - /// Applied to a class that represents a data model which is serialized to javascript. - /// This attribute controls how TypeScript interfaces are generated for the class that - /// this is applied to. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class GenerateInterfaceAttribute : GenerateConstantAttributeBase - { - public GenerateInterfaceAttribute() - : this(true) - { - } - - public GenerateInterfaceAttribute(string alternateName) - : base(alternateName) - { - GenerateInterface = true; - } - - public GenerateInterfaceAttribute(bool generateInterface) - : base() - { - GenerateInterface = generateInterface; - } - - /// - /// Whether or not to generate a typescript interface for this type - /// - public bool GenerateInterface { get; set; } - } -} diff --git a/src/Sdk/Common/Common/IVssClientCertificateManager.cs b/src/Sdk/Common/Common/IVssClientCertificateManager.cs deleted file mode 100644 index feb32580c..000000000 --- a/src/Sdk/Common/Common/IVssClientCertificateManager.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Security.Cryptography.X509Certificates; - -namespace GitHub.Services.Common -{ - /// - /// An interface to allow custom implementations to - /// gather client certificates when necessary. - /// - public interface IVssClientCertificateManager - { - X509Certificate2Collection ClientCertificates { get; } - } -} diff --git a/src/Sdk/Common/Common/IVssHttpRetryInfo.cs b/src/Sdk/Common/Common/IVssHttpRetryInfo.cs deleted file mode 100644 index 4272ca722..000000000 --- a/src/Sdk/Common/Common/IVssHttpRetryInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - public interface IVssHttpRetryInfo - { - void InitialAttempt(HttpRequestMessage request); - - void Retry(TimeSpan sleep); - - void Reset(); - } -} diff --git a/src/Sdk/Common/Common/Performance/PerformanceTimerConstants.cs b/src/Sdk/Common/Common/Performance/PerformanceTimerConstants.cs deleted file mode 100644 index 6ee1fde3f..000000000 --- a/src/Sdk/Common/Common/Performance/PerformanceTimerConstants.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -namespace GitHub.Services.Common -{ - public static class PerformanceTimerConstants - { - public const string Header = "X-VSS-PerfData"; - public const string PerfTimingKey = "PerformanceTimings"; - - [Obsolete] - public const string Aad = "AAD"; // Previous timer, broken into Token and Graph below - - public const string AadToken = "AadToken"; - public const string AadGraph = "AadGraph"; - public const string BlobStorage = "BlobStorage"; - public const string FinalSqlCommand = "FinalSQLCommand"; - public const string Redis = "Redis"; - public const string ServiceBus = "ServiceBus"; - public const string Sql = "SQL"; - public const string SqlReadOnly = "SQLReadOnly"; - public const string SqlRetries = "SQLRetries"; - public const string TableStorage = "TableStorage"; - public const string VssClient = "VssClient"; - public const string DocumentDB = "DocumentDB"; - } -} diff --git a/src/Sdk/Common/Common/Performance/PerformanceTimingGroup.cs b/src/Sdk/Common/Common/Performance/PerformanceTimingGroup.cs deleted file mode 100644 index 3c8795706..000000000 --- a/src/Sdk/Common/Common/Performance/PerformanceTimingGroup.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.Common -{ - /// - /// A set of performance timings all keyed off of the same string - /// - [DataContract] - public class PerformanceTimingGroup - { - public PerformanceTimingGroup() - { - this.Timings = new List(); - } - - /// - /// Overall duration of all entries in this group in ticks - /// - [DataMember(EmitDefaultValue = false)] - public long ElapsedTicks { get; set; } - - /// - /// The total number of timing entries associated with this group - /// - [DataMember(EmitDefaultValue = false)] - public int Count { get; set; } - - /// - /// A list of timing entries in this group. Only the first few entries in each group are collected. - /// - [DataMember] - public List Timings { get; private set; } - } - - /// - /// A single timing consisting of a duration and start time - /// - [DataContract] - public struct PerformanceTimingEntry - { - /// - /// Duration of the entry in ticks - /// - [DataMember] - public long ElapsedTicks { get; set; } - - /// - /// Offset from Server Request Context start time in microseconds - /// - [DataMember] - public long StartOffset { get; set; } - - /// - /// Properties to distinguish timings within the same group or to provide data to send with telemetry - /// - [DataMember(EmitDefaultValue = false)] - public IDictionary Properties { get; set; } - } -} diff --git a/src/Sdk/Common/Common/TaskCancellationExtensions.cs b/src/Sdk/Common/Common/TaskCancellationExtensions.cs deleted file mode 100644 index 9b9c0767f..000000000 --- a/src/Sdk/Common/Common/TaskCancellationExtensions.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Globalization; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - public static class TaskCancellationExtensions - { - private struct Void { } - - /// - /// Some APIs (e.g. HttpClient) don't honor cancellation tokens. This wrapper adds an extra layer of cancellation checking. - /// - public static Task EnforceCancellation( - this Task task, - CancellationToken cancellationToken, - Func makeMessage = null, - [CallerFilePath] string file = "", - [CallerMemberName] string member = "", - [CallerLineNumber] int line = -1) - { - Func> task2 = async () => - { - await task.ConfigureAwait(false); - return new Void(); - }; - - return task2().EnforceCancellation(cancellationToken, makeMessage, file, member, line); - } - - /// - /// Some APIs (e.g. HttpClient) don't honor cancellation tokens. This wrapper adds an extra layer of cancellation checking. - /// - public static async Task EnforceCancellation( - this Task task, - CancellationToken cancellationToken, - Func makeMessage = null, - [CallerFilePath] string file = "", - [CallerMemberName] string member = "", - [CallerLineNumber] int line = -1) - { - ArgumentUtility.CheckForNull(task, nameof(task)); - - // IsCompleted will return true when the task is in one of the three final states: RanToCompletion, Faulted, or Canceled. - if (task.IsCompleted) - { - return await task; - } - - var cancellationTcs = new TaskCompletionSource(RUN_CONTINUATIONS_ASYNCHRONOUSLY); - using (cancellationToken.Register(() => cancellationTcs.SetResult(false))) - { - var completedTask = await Task.WhenAny(task, cancellationTcs.Task).ConfigureAwait(false); - if (completedTask == task) - { - return await task; - } - } - - // Even if our actual task actually did honor the cancellation token, there's still a race that our WaitForCancellation - // task may have handled the cancellation more quickly. - if (!cancellationToken.IsCancellationRequested) - { - throw new InvalidOperationException("Task ended but cancellation token is not marked for cancellation."); - } - - // However, we'd ideally like to throw the cancellation exception from the original task if we can. - // Thus, we'll give that task a few seconds to coallesce (e.g. write to a log) before we give up on it. - int seconds = 3; - var lastChanceTcs = new TaskCompletionSource(RUN_CONTINUATIONS_ASYNCHRONOUSLY); - using (var lastChanceTimer = new CancellationTokenSource(TimeSpan.FromSeconds(seconds))) - using (lastChanceTimer.Token.Register(() => lastChanceTcs.SetResult(false))) - { - var completedTask = await Task.WhenAny(task, lastChanceTcs.Task).ConfigureAwait(false); - if (completedTask == task) - { - return await task; - } - } - - // At this point, we've given up on waiting for this task. - ObserveExceptionIfNeeded(task); - - string errorString = $"Task in function {member} at {file}:{line} was still active {seconds} seconds after operation was cancelled."; - if (makeMessage != null) - { - errorString += $" {makeMessage()}"; - } - - throw new OperationCanceledException(errorString, cancellationToken); - } - - private static void ObserveExceptionIfNeeded(Task task) - { - task.ContinueWith(t => t.Exception, TaskContinuationOptions.OnlyOnFaulted); - } - - /// - /// This is a flag exposed by TaskCreationOptions and TaskContinuationOptions but it's not in .Net 4.5 - /// In Azure we have latest .Net loaded which will consume this flag. - /// Client environments using earlier .Net would ignore it. - /// - private const int RUN_CONTINUATIONS_ASYNCHRONOUSLY = 0x40; - } -} diff --git a/src/Sdk/Common/Common/Utility/ArgumentUtility.cs b/src/Sdk/Common/Common/Utility/ArgumentUtility.cs deleted file mode 100644 index 555006393..000000000 --- a/src/Sdk/Common/Common/Utility/ArgumentUtility.cs +++ /dev/null @@ -1,1248 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public static class ArgumentUtility - { - /// - /// Throw an exception if the object is null. - /// - /// the object to check - /// the variable or parameter name to display - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForNull(Object var, String varName) - { - CheckForNull(var, varName, null); - } - - /// - /// Throw an exception if the object is null. - /// - /// the object to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForNull(Object var, String varName, String expectedServiceArea) - { - if (var == null) - { - throw new ArgumentNullException(varName).Expected(expectedServiceArea); - } - } - - /// - /// Throw an exception if a string is null or empty. - /// - /// string to check - /// the variable or parameter name to display - public static void CheckStringForNullOrEmpty(String stringVar, String stringVarName) - { - CheckStringForNullOrEmpty(stringVar, stringVarName, null); - } - - /// - /// Throw an exception if a string is null or empty. - /// - /// string to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForNullOrEmpty(String stringVar, String stringVarName, String expectedServiceArea) - { - CheckStringForNullOrEmpty(stringVar, stringVarName, false, expectedServiceArea); - } - - public static void CheckForNonnegativeInt(int var, String varName) - { - CheckForNonnegativeInt(var, varName, null); - } - - public static void CheckForNonnegativeInt(int var, String varName, String expectedServiceArea) - { - if (var < 0) - { - throw new ArgumentOutOfRangeException(varName).Expected(expectedServiceArea); - } - } - - /// - /// Throws and exception if an integer is less than 1 - /// - /// integer to check - /// the variable or parameter name to display - public static void CheckForNonPositiveInt(int var, String varName) - { - CheckForNonPositiveInt(var, varName, null); - } - - /// - /// Throws and exception if an integer is less than 1 - /// - /// integer to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckForNonPositiveInt(int var, String varName, String expectedServiceArea) - { - if (var <= 0) - { - throw new ArgumentOutOfRangeException(varName).Expected(expectedServiceArea); - } - } - - /// - /// Throw an exception if a string is null or empty. - /// - /// string to check - /// the variable or parameter name to display - /// If true, will trim the string after it is determined not to be null - public static void CheckStringForNullOrEmpty(String stringVar, String stringVarName, bool trim) - { - CheckStringForNullOrEmpty(stringVar, stringVarName, trim, null); - } - - /// - /// Throw an exception if a string is null or empty. - /// - /// string to check - /// the variable or parameter name to display - /// If true, will trim the string after it is determined not to be null - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForNullOrEmpty(String stringVar, String stringVarName, bool trim, String expectedServiceArea) - { - CheckForNull(stringVar, stringVarName, expectedServiceArea); - if (trim == true) - { - stringVar = stringVar.Trim(); - } - if (stringVar.Length == 0) - { - throw new ArgumentException(CommonResources.EmptyStringNotAllowed(), stringVarName).Expected(expectedServiceArea); - } - } - - /// - /// Throw an exception if a string is null, too short, or too long. - /// - /// string to check - /// the variable or parameter name to display - /// Maximum allowed string length - /// Minimum allowed string length - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringLength( - string stringVar, - string stringVarName, - int maxLength, - int minLength = 0, - string expectedServiceArea = null) - { - CheckForNull(stringVar, stringVarName, expectedServiceArea); - - if (stringVar.Length < minLength || stringVar.Length > maxLength) - { - throw new ArgumentException( - CommonResources.StringLengthNotAllowed(stringVarName, minLength, maxLength), - stringVarName) - .Expected(expectedServiceArea); - } - } - - /// - /// Check a Collection for the Max Length - /// - /// enumerable to check - /// the variable or parameter name to display - /// Max allowed Length - public static void CheckCollectionForMaxLength(ICollection collection, string collectionName, int maxLength) - { - if (collection?.Count > maxLength) - { - throw new ArgumentException(CommonResources.CollectionSizeLimitExceeded(collectionName, maxLength)); - } - } - - /// - /// Throw an exception if IEnumerable is null or empty. - /// - /// enumerable to check - /// the variable or parameter name to display - public static void CheckEnumerableForNullOrEmpty(IEnumerable enumerable, String enumerableName) - { - CheckEnumerableForNullOrEmpty(enumerable, enumerableName, null); - } - - /// - /// Throw an exception if IEnumerable is null or empty. - /// - /// enumerable to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckEnumerableForNullOrEmpty(IEnumerable enumerable, String enumerableName, String expectedServiceArea) - { - CheckForNull(enumerable, enumerableName, expectedServiceArea); - - IEnumerator enumerator = enumerable.GetEnumerator(); - if (!enumerator.MoveNext()) - { - throw new ArgumentException(CommonResources.EmptyCollectionNotAllowed(), enumerableName).Expected(expectedServiceArea); - } - } - - /// - /// Throw an exception if IEnumerable contains a null element. - /// - /// enumerable to check - /// the variable or parameter name to display - public static void CheckEnumerableForNullElement(IEnumerable enumerable, String enumerableName) - { - CheckEnumerableForNullElement(enumerable, enumerableName, null); - } - - /// - /// Throw an exception if IEnumerable contains a null element. - /// - /// enumerable to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckEnumerableForNullElement(IEnumerable enumerable, String enumerableName, String expectedServiceArea) - { - CheckForNull(enumerable, enumerableName, expectedServiceArea); - - IEnumerator enumerator = enumerable.GetEnumerator(); - while (enumerator.MoveNext()) - { - if (enumerator.Current == null) - { - throw new ArgumentException(CommonResources.NullElementNotAllowedInCollection(), enumerableName).Expected(expectedServiceArea); - } - } - } - - /// - /// Throw an exception if the guid is equal to Guid.Empty. - /// - /// the guid to check - /// the variable or parameter name to display - public static void CheckForEmptyGuid(Guid guid, String varName) - { - CheckForEmptyGuid(guid, varName, null); - } - - /// - /// Throw an exception if the guid is equal to Guid.Empty. - /// - /// the guid to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckForEmptyGuid(Guid guid, String varName, String expectedServiceArea) - { - if (guid.Equals(Guid.Empty)) - { - throw new ArgumentException(CommonResources.EmptyGuidNotAllowed(varName), varName).Expected(expectedServiceArea); - } - } - - /// - /// Throw an exception if the value contains more than one bit set. - /// - /// the value to check - /// the variable or parameter name to display - public static void CheckForMultipleBits(int value, String varName) - { - CheckForMultipleBits(value, varName, null); - } - - /// - /// Throw an exception if the value contains more than one bit set. - /// - /// the value to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckForMultipleBits(int value, String varName, String expectedServiceArea) - { - if (0 == value || - (value & (value - 1)) != 0) - { - throw new ArgumentException(CommonResources.SingleBitRequired(varName), varName).Expected(expectedServiceArea); - } - } - - /// - /// Throw an exception if the value equals the default for the type. - /// - /// the value to check - /// the variable or parameter name to display - public static void CheckForDefault(T value, String varName) - { - if (EqualityComparer.Default.Equals(value, default(T))) - { - throw new ArgumentException(CommonResources.DefaultValueNotAllowed(varName), varName); - } - } - - /// - /// Checks if character is not displayable. - /// - /// - /// Carriage return and line-feed is considered legal if the allowCrLf parameter is set to true. - /// A character is "not displayable" if it's UnicodeCategory is in the set {LineSeparator, ParagraphSeparator, Control, Format, OtherNotAssigned}. - public static bool IsIllegalInputCharacter(char c, Boolean allowCrLf = false) - { - if (allowCrLf && (c == '\r' || c == '\n')) - { - return false; - } - - UnicodeCategory cat = Char.GetUnicodeCategory(c); - - // see http://www.w3.org/TR/REC-xml/#charsets - return (cat == UnicodeCategory.LineSeparator - || cat == UnicodeCategory.ParagraphSeparator - || cat == UnicodeCategory.Control - || cat == UnicodeCategory.Format - || cat == UnicodeCategory.OtherNotAssigned); - } - - /// - /// Replace illegal characters with specified character. A character is considered illegal as per definition of - /// - public static string ReplaceIllegalCharacters(string str, char replaceWith, bool allowCrLf = false) - { - if (IsIllegalInputCharacter(replaceWith, allowCrLf)) - { - throw new ArgumentException(CommonResources.VssInvalidUnicodeCharacter((int)replaceWith), nameof(replaceWith)); - } - - if (string.IsNullOrEmpty(str)) - { - return str; - } - - char[] strArray = str.ToCharArray(); - for (int i = 0; i < strArray.Length; i++) - { - if (IsIllegalInputCharacter(strArray[i], allowCrLf: allowCrLf)) - { - strArray[i] = replaceWith; - } - } - - return new string(strArray); - } - - /// - /// Checks for invalid unicode characters - /// - /// - /// - public static void CheckStringForInvalidCharacters(String stringVar, String stringVarName) - { - CheckStringForInvalidCharacters(stringVar, stringVarName, false, null); - } - - /// - /// Checks for invalid unicode characters - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForInvalidCharacters(String stringVar, String stringVarName, String expectedServiceArea) - { - CheckStringForInvalidCharacters(stringVar, stringVarName, false, expectedServiceArea); - } - - /// - /// Checks for invalid unicode characters - /// - /// - /// - /// - public static void CheckStringForInvalidCharacters(String stringVar, String stringVarName, Boolean allowCrLf) - { - CheckStringForInvalidCharacters(stringVar, stringVarName, allowCrLf, null); - } - - /// - /// Checks for invalid unicode characters - /// - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForInvalidCharacters(String stringVar, String stringVarName, Boolean allowCrLf, String expectedServiceArea) - { - Debug.Assert(!String.IsNullOrEmpty(stringVarName), "!String.IsNullOrEmpty(stringVarName)"); - - ArgumentUtility.CheckForNull(stringVar, stringVarName); - - for (int i = 0; i < stringVar.Length; i++) - { - if (IsIllegalInputCharacter(stringVar[i], allowCrLf)) - { - throw new ArgumentException(CommonResources.VssInvalidUnicodeCharacter((int)stringVar[i]), stringVarName).Expected(expectedServiceArea); - } - } - } - - /// - /// - /// - /// - /// - /// - public static void CheckStringForInvalidCharacters(String stringVar, String stringVarName, Char[] invalidCharacters) - { - CheckStringForInvalidCharacters(stringVar, stringVarName, invalidCharacters, null); - } - - /// - /// - /// - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForInvalidCharacters(String stringVar, String stringVarName, Char[] invalidCharacters, String expectedServiceArea) - { - Debug.Assert(null != stringVar, "null != stringVar"); - Debug.Assert(!String.IsNullOrEmpty(stringVarName), "!String.IsNullOrEmpty(stringVarName)"); - Debug.Assert(invalidCharacters != null, "invalidCharacters != null"); - - ArgumentUtility.CheckForNull(stringVar, stringVarName); - - for (int i = 0; i < invalidCharacters.Length; i++) - { - if (stringVar.IndexOf(invalidCharacters[i]) >= 0) - { - throw new ArgumentException(CommonResources.StringContainsInvalidCharacters(invalidCharacters[i]), stringVarName).Expected(expectedServiceArea); - } - } - } - - /// - /// Checks for escape sequences that are invalid in SQL - /// - /// The value to be checked - /// The name of the value to be checked - /// The service area where this exception is expected due to user input. See - public static void CheckStringForInvalidSqlEscapeCharacters(String stringVar, String stringVarName, String expectedServiceArea = null) - { - Debug.Assert(!String.IsNullOrEmpty(stringVar), "null != stringVar"); - Debug.Assert(!String.IsNullOrEmpty(stringVarName), "!String.IsNullOrEmpty(stringVarName)"); - - ArgumentUtility.CheckStringForNullOrEmpty(stringVar, stringVarName); - - for (int i = 0; i < stringVar.Length - 1; i++) - { - if (stringVar[i] == '\\') - { - // Make sure the next character after the slash is a valid escape character - char escapedCharacter = stringVar[++i]; - if (escapedCharacter != '*' && escapedCharacter != '?' && escapedCharacter != '\\') - { - throw new ArgumentException(CommonResources.StringContainsInvalidCharacters('\\'), stringVarName).Expected(expectedServiceArea); - } - } - } - } - - public static void CheckBoundsInclusive(Int32 value, Int32 minValue, Int32 maxValue, String varName) - { - CheckBoundsInclusive(value, minValue, maxValue, varName, null); - } - - public static void CheckBoundsInclusive(Int32 value, Int32 minValue, Int32 maxValue, String varName, String expectedServiceArea) - { - Debug.Assert(!String.IsNullOrEmpty(varName), "!String.IsNullOrEmpty(stringVarName)"); - - if (value < minValue || value > maxValue) - { - throw new ArgumentOutOfRangeException(varName, CommonResources.ValueOutOfRange(value, varName, minValue, maxValue)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the value is out of range. - /// - /// The comparable type - /// the value to check - /// the variable or parameter name to display - /// minimum legal value - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(T var, string varName, T minimum) - where T : IComparable - { - CheckForOutOfRange(var, varName, minimum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the value is out of range. - /// - /// The comparable type - /// the value to check - /// the variable or parameter name to display - /// minimum legal value - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(T var, string varName, T minimum, String expectedServiceArea) - where T : IComparable - { - ArgumentUtility.CheckForNull(var, varName, expectedServiceArea); - if (var.CompareTo(minimum) < 0) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the value is out of range. - /// - /// The comparable type - /// the value to check - /// the variable or parameter name to display - /// minimum legal value - /// maximum legal value - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(T var, string varName, T minimum, T maximum) - where T : IComparable - { - CheckForOutOfRange(var, varName, minimum, maximum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the value is out of range. - /// - /// The comparable type - /// the value to check - /// the variable or parameter name to display - /// minimum legal value - /// maximum legal value - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(T var, string varName, T minimum, T maximum, String expectedServiceArea) - where T : IComparable - { - CheckForNull(var, varName, expectedServiceArea); - if (var.CompareTo(minimum) < 0 || var.CompareTo(maximum) > 0) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(int var, String varName, int minimum) - { - CheckForOutOfRange(var, varName, minimum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(int var, String varName, int minimum, String expectedServiceArea) - { - if (var < minimum) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - /// maximum legal value - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(int var, String varName, int minimum, int maximum) - { - CheckForOutOfRange(var, varName, minimum, maximum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - /// maximum legal value - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(int var, String varName, int minimum, int maximum, String expectedServiceArea) - { - if (var < minimum || var > maximum) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(long var, String varName, long minimum) - { - CheckForOutOfRange(var, varName, minimum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(long var, String varName, long minimum, String expectedServiceArea) - { - if (var < minimum) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - /// maximum legal value - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(long var, String varName, long minimum, long maximum) - { - CheckForOutOfRange(var, varName, minimum, maximum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the integer is out of range. - /// - /// the int to check - /// the variable or parameter name to display - /// minimum legal value - /// maximum legal value - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CheckForOutOfRange(long var, String varName, long minimum, long maximum, String expectedServiceArea) - { - if (var < minimum || var > maximum) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the date is not in the range. - /// - /// the DateTime to check - /// the variable or parameter name to display - /// minimum legal value - /// - //******************************************************************************************** - public static void CheckForDateTimeRange(DateTime var, String varName, DateTime minimum, DateTime maximum) - { - CheckForDateTimeRange(var, varName, minimum, maximum, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the date is not in the range. - /// - /// the DateTime to check - /// the variable or parameter name to display - /// minimum legal value - /// - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckForDateTimeRange(DateTime var, String varName, DateTime minimum, DateTime maximum, String expectedServiceArea) - { - if (var < minimum || var > maximum) - { - throw new ArgumentOutOfRangeException(varName, var, CommonResources.OutOfRange(var)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throws an exception if the provided value is less than zero. - /// - /// value to check - /// the variable or parameter name to display - //******************************************************************************************** - public static void CheckGreaterThanOrEqualToZero(float value, string valueName) - { - CheckGreaterThanOrEqualToZero(value, valueName, null); - } - - //******************************************************************************************** - /// - /// Throws an exception if the provided value is less than zero. - /// - /// value to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckGreaterThanOrEqualToZero(float value, string valueName, String expectedServiceArea) - { - if (value < 0) - { - throw new ArgumentException(CommonResources.ValueMustBeGreaterThanZero(), valueName).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throws an exception if the provided value is less than or equal to zero. - /// - /// value to check - /// the variable or parameter name to display - //******************************************************************************************** - public static void CheckGreaterThanZero(float value, string valueName) - { - CheckGreaterThanZero(value, valueName, null); - } - - //******************************************************************************************** - /// - /// Throws an exception if the provided value is less than or equal to zero. - /// - /// value to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckGreaterThanZero(float value, string valueName, String expectedServiceArea) - { - if (value <= 0) - { - throw new ArgumentException(CommonResources.ValueMustBeGreaterThanZero(), valueName).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the object is not null. - /// - /// the object to check - /// the variable or parameter name to display - //******************************************************************************************** - public static void EnsureIsNull(Object var, String varName) - { - EnsureIsNull(var, varName, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the object is not null. - /// - /// the object to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void EnsureIsNull(Object var, String varName, String expectedServiceArea) - { - if (var != null) - { - throw new ArgumentException(CommonResources.NullValueNecessary(varName)).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if the string is not entirely of a specified casing (lowercase, uppercase). - /// - /// The string to check. - /// The variable or parameter name to display. - /// Indicates whether the check should require - /// lowercase characters, as opposed to uppercase characters. - //******************************************************************************************** - public static void CheckStringCasing(String stringVar, String varName, Boolean checkForLowercase = true) - { - CheckStringCasing(stringVar, varName, checkForLowercase, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if the string is not entirely of a specified casing (lowercase, uppercase). - /// - /// The string to check. - /// The variable or parameter name to display. - /// Indicates whether the check should require - /// lowercase characters, as opposed to uppercase characters. - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckStringCasing(String stringVar, String varName, Boolean checkForLowercase = true, String expectedServiceArea = null) - { - foreach (Char c in stringVar) - { - if (Char.IsLetter(c) == true && - Char.IsLower(c) == !checkForLowercase) - { - throw new ArgumentException( - checkForLowercase ? - CommonResources.LowercaseStringRequired(varName) : - CommonResources.UppercaseStringRequired(varName)) - .Expected(expectedServiceArea); - } - } - } - - //******************************************************************************************** - /// - /// Throw an exception if IEnumerable is empty. - /// - /// enumerable to check - /// the variable or parameter name to display - //******************************************************************************************** - public static void CheckEnumerableForEmpty(IEnumerable enumerable, String enumerableName) - { - CheckEnumerableForEmpty(enumerable, enumerableName, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if IEnumerable is empty. - /// - /// enumerable to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckEnumerableForEmpty(IEnumerable enumerable, String enumerableName, String expectedServiceArea) - { - if (enumerable != null) - { - IEnumerator enumerator = enumerable.GetEnumerator(); - if (!enumerator.MoveNext()) - { - throw new ArgumentException(CommonResources.EmptyArrayNotAllowed(), enumerableName).Expected(expectedServiceArea); - } - } - } - - //******************************************************************************************** - /// - /// Throw an exception if a string is null, empty, or consists only of white-space characters. - /// - /// string to check - /// the variable or parameter name to display - //******************************************************************************************** - public static void CheckStringForNullOrWhiteSpace(String stringVar, String stringVarName) - { - CheckStringForNullOrWhiteSpace(stringVar, stringVarName, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if a string is null, empty, or consists only of white-space characters. - /// - /// string to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckStringForNullOrWhiteSpace(String stringVar, String stringVarName, String expectedServiceArea) - { - CheckForNull(stringVar, stringVarName, expectedServiceArea); - if (String.IsNullOrWhiteSpace(stringVar) == true) - { - throw new ArgumentException(CommonResources.EmptyOrWhiteSpaceStringNotAllowed(), stringVarName).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if a string length is not given value. - /// - /// string to check - /// length to check - /// the variable or parameter name to display - //******************************************************************************************** - public static void CheckStringExactLength(String stringVar, int length, String stringVarName) - { - CheckStringExactLength(stringVar, length, stringVarName, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if a string length is not given value. - /// - /// string to check - /// length to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckStringExactLength(String stringVar, int length, String stringVarName, String expectedServiceArea) - { - CheckForNull(stringVar, stringVarName, expectedServiceArea); - - if (stringVar.Length != length) - { - throw new ArgumentException(CommonResources.StringLengthNotMatch(length), stringVarName).Expected(expectedServiceArea); - } - } - - //******************************************************************************************** - /// - /// Throw an exception if one of the strings is not null or empty. - /// - /// the first object to check - /// the variable or parameter name to display for the first object - /// the second object to check - /// the variable or parameter name to display for the second object - //******************************************************************************************** - public static void CheckForBothStringsNullOrEmpty(String var1, String varName1, String var2, String varName2) - { - CheckForBothStringsNullOrEmpty(var1, varName1, var2, varName2, null); - } - - //******************************************************************************************** - /// - /// Throw an exception if one of the strings is not null or empty. - /// - /// the first object to check - /// the variable or parameter name to display for the first object - /// the second object to check - /// the variable or parameter name to display for the second object - /// the Service Area where this exception is expected due to user input. See - //******************************************************************************************** - public static void CheckForBothStringsNullOrEmpty(String var1, String varName1, String var2, String varName2, String expectedServiceArea) - { - if (String.IsNullOrEmpty(var1) && String.IsNullOrEmpty(var2)) - { - throw new ArgumentException(CommonResources.BothStringsCannotBeNull(varName1, varName2)).Expected(expectedServiceArea); - } - } - - /// - /// Checks if a string contains any whitespace characters. Throws an exception if it does. - /// - /// - /// - public static void CheckStringForAnyWhiteSpace(string stringVar, string stringVarName) - { - CheckStringForAnyWhiteSpace(stringVar, stringVarName, null); - } - - /// - /// Checks if a string contains any whitespace characters. Throws an exception if it does. - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForAnyWhiteSpace(string stringVar, string stringVarName, String expectedServiceArea) - { - if (stringVar != null) - { - for (Int32 i = 0; i < stringVar.Length; i++) - { - if (Char.IsWhiteSpace(stringVar[i])) - { - throw new ArgumentException(CommonResources.WhiteSpaceNotAllowed(), stringVarName).Expected(expectedServiceArea); - } - } - } - } - - /// - /// Performs a type check on the variable, and throws if there is a mismatch - /// - /// - /// - /// - /// - public static void CheckType(object var, string varName, string typeName) - { - CheckType(var, varName, typeName, null); - } - - /// - /// Performs a type check on the variable, and throws if there is a mismatch - /// - /// - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckType(object var, string varName, string typeName, String expectedServiceArea) - { - if (!(var is T)) - { - throw new ArgumentException(CommonResources.UnexpectedType(varName, typeName)).Expected(expectedServiceArea); - } - } - - /// - /// Checks if an enum value is defined on the enum type - /// - /// The type of the enum - /// The enum value - /// The name of the enum argument - public static void CheckForDefinedEnum(TEnum value, string enumVarName) - where TEnum : struct - { - CheckForDefinedEnum(value, enumVarName, null); - } - - /// - /// Checks if an enum value is defined on the enum type - /// - /// The type of the enum - /// The enum value - /// The name of the enum argument - /// the Service Area where this exception is expected due to user input. See - public static void CheckForDefinedEnum(TEnum value, string enumVarName, String expectedServiceArea) - where TEnum : struct - { - // IsEnumDefined throws ArgumentException if TEnum is not an enum type - if (!typeof(TEnum).IsEnumDefined(value)) - { - throw new global::System.ComponentModel.InvalidEnumArgumentException(enumVarName, (int)(object)value, typeof(TEnum)).Expected(expectedServiceArea); - } - } - - /// - /// Determines if a string value is a valid email address. Does NOT throw. - /// - /// - /// - public static Boolean IsValidEmailAddress(string emailAddress) - { - // WARNING: If you switch this to code to use the MailAddress class for validation, - // you need to evaluate all callers to see if they handle inputs like these: - // "John Smith " - // "" - // - // The MailAddress constructor supports those strings. - - return s_emailPattern.IsMatch(emailAddress); - } - - /// - /// Checks if a string is a valid email address. Throws an exception otherwise. - /// - /// - /// - public static void CheckEmailAddress(string stringVar, string stringVarName) - { - CheckEmailAddress(stringVar, stringVarName, null); - } - - /// - /// Checks if a string is a valid email address. Throws an exception otherwise. - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckEmailAddress(string stringVar, string stringVarName, String expectedServiceArea) - { - if (!IsValidEmailAddress(stringVar)) - { - throw new ArgumentException(CommonResources.InvalidEmailAddressError(), stringVarName).Expected(expectedServiceArea); - } - } - - /// - /// Checks if a string value is a valid URI in accordance with RFC 3986 and RFC 3987. Throws an exception otherwise. - /// - /// - /// - /// - public static void CheckIsValidURI(string uriString, UriKind uriKind, string stringVarName) - { - if (!Uri.IsWellFormedUriString(uriString, uriKind)) - { - throw new ArgumentException(CommonResources.InvalidUriError(uriKind), stringVarName); - } - } - - /// - /// - /// - /// - /// - public static void CheckStringForInvalidCharacters(string[] stringArrayVar, string stringArrayVarName) - { - CheckStringForInvalidCharacters(stringArrayVar, stringArrayVarName, null); - } - - /// - /// - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForInvalidCharacters(string[] stringArrayVar, string stringArrayVarName, String expectedServiceArea) - { - CheckStringForInvalidCharacters(stringArrayVar, stringArrayVarName, false, expectedServiceArea); - } - - /// - /// Checks for invalid unicode characters - /// - /// - /// - /// - public static void CheckStringForInvalidCharacters(string[] stringArrayVar, string stringArrayVarName, Boolean allowCrLf) - { - CheckStringForInvalidCharacters(stringArrayVar, stringArrayVarName, allowCrLf, null); - } - - /// - /// Checks for invalid unicode characters - /// - /// - /// - /// - /// the Service Area where this exception is expected due to user input. See - public static void CheckStringForInvalidCharacters(string[] stringArrayVar, string stringArrayVarName, Boolean allowCrLf, String expectedServiceArea) - { - Debug.Assert(null != stringArrayVar, "null != stringArrayVar"); - Debug.Assert(stringArrayVar.Length > 0, "stringArrayVar.Length > 0"); - Debug.Assert(!String.IsNullOrEmpty(stringArrayVarName), "!String.IsNullOrEmpty(stringArrayVarName)"); - - for (int i = 0; i < stringArrayVar.Length; i++) - { - CheckStringForInvalidCharacters(stringArrayVar[i], String.Format(CultureInfo.InvariantCulture, "{0}[{1}]", stringArrayVarName, i), allowCrLf, expectedServiceArea); - } - } - - /// - /// Throws an exception if the provided value equals to infinity. - /// - /// value to check - /// the variable or parameter name to display - public static void CheckValueEqualsToInfinity(float value, string valueName) - { - CheckValueEqualsToInfinity(value, valueName, null); - } - - /// - /// Throws an exception if the provided value equals to infinity. - /// - /// value to check - /// the variable or parameter name to display - /// the Service Area where this exception is expected due to user input. See - public static void CheckValueEqualsToInfinity(float value, string valueName, String expectedServiceArea) - { - if (float.IsInfinity(value)) - { - throw new ArgumentException(CommonResources.ValueEqualsToInfinity(), valueName).Expected(expectedServiceArea); - } - } - - private static readonly Regex s_emailPattern = new Regex(@"^([a-z0-9.!#$%&'*+/=?^_`{|}~-]+)@((\[[0-9]{1,3}" + - @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" + - @".)+))([a-z]{2,63}|[0-9]{1,3})(\]?)$", RegexOptions.IgnoreCase); - - public static bool IsInvalidString(string strIn) - { - return IsInvalidString(strIn, false); - } - - public static bool IsInvalidString(string strIn, Boolean allowCrLf) - { - ArgumentUtility.CheckForNull(strIn, "strIn"); - - foreach (char c in strIn) - { - if (ArgumentUtility.IsIllegalInputCharacter(c, allowCrLf)) - { - return true; - } - } - - if (HasMismatchedSurrogates(strIn) == true) - { - return true; - } - - return false; - } - - public static bool HasSurrogates(string strIn) - { - for (int i = 0; i < strIn.Length; i++) - { - Char c = strIn[i]; - - if (char.IsSurrogate(c) == true) - { - return true; - } - } - return false; - } - - public static bool HasMismatchedSurrogates(string strIn) - { - for (int i = 0; i < strIn.Length; i++) - { - Char c = strIn[i]; - - // If this is a low surrogate, that means that there wasn't a preceeding high - // surrogate, and it is invalid - if (Char.IsLowSurrogate(c)) - { - return true; - } - - // is this the start of a surrogate pair? - if (Char.IsHighSurrogate(c)) - { - if (!Char.IsSurrogatePair(strIn, i)) - { - return true; - } - - // skip the low surogate - i++; - } - } - return false; - } - } -} diff --git a/src/Sdk/Common/Common/Utility/ArrayUtility.cs b/src/Sdk/Common/Common/Utility/ArrayUtility.cs deleted file mode 100644 index 8c3e8b790..000000000 --- a/src/Sdk/Common/Common/Utility/ArrayUtility.cs +++ /dev/null @@ -1,148 +0,0 @@ -//************************************************************************************************* -// ArrayUtil.cs -// -// A class with random array processing helper routines. -// -// Copyright (c) Microsoft Corporation. All rights reserved. -//************************************************************************************************* -using System; -using System.Diagnostics; -using System.Text; - -namespace GitHub.Services.Common -{ - //******************************************************************************************** - /// - /// A class with random array processing helper routines. - /// - //******************************************************************************************** - public static class ArrayUtility - { - //**************************************************************************************** - /// - /// Compare two byte arrays to determine if they contain the same data. - /// - /// First array to compare. - /// Second array to compare. - /// true if the arrays are equal and false if not. - //**************************************************************************************** - public unsafe static bool Equals(byte[] a1, byte[] a2) - { - Debug.Assert(a1 != null, "a1 was null"); - Debug.Assert(a2 != null, "a2 was null"); - - // Check if the lengths are the same. - if (a1.Length != a2.Length) - { - return false; - } - if (a1.Length == 0) - { - return true; - } - - return Equals(a1, a2, a1.Length); - } - - //**************************************************************************************** - /// - /// Generate hash code for a byte array. - /// - /// array to generate hash code for. - /// hash generated from the array members. - //**************************************************************************************** - public static int GetHashCode(byte[] array) - { - Debug.Assert(array != null, "array was null"); - - int hash = 0; - // the C# compiler defaults to unchecked behavior, so this will - // wrap silently. Since this is a hash code and not a count, this - // is fine with us. - foreach (byte item in array) - { - hash += item; - } - - return hash; - } - - //**************************************************************************************** - /// - /// Compare two byte arrays to determine if they contain the same data. - /// - /// First array to compare. - /// Second array to compare. - /// # of bytes to compare. - /// true if the arrays are equal and false if not. - //**************************************************************************************** - public unsafe static bool Equals(byte[] a1, byte[] a2, int length) - { - // Pin the arrays so that we can use unsafe pointers to compare an int at a time. - fixed (byte* p1 = &a1[0]) - { - fixed (byte* p2 = &a2[0]) - { - // Get temps for the pointers because you can't change fixed pointers. - byte* q1 = p1, q2 = p2; - - // Compare an int at a time for as long as we can. We divide by four because an int - // is always 32 bits in C# regardless of platform. - int i; - for (i = length >> 2; i > 0; --i) - { - if (*((int*) q1) != *((int*) q2)) - { - return false; - } - q1 += sizeof(int); - q2 += sizeof(int); - } - - // Compare a byte at a time for the remaining bytes (0 - 3 of them). This also - // depends on ints being 32 bits. - for (i = length & 0x3; i > 0; --i) - { - if (*q1 != *q2) - { - return false; - } - ++q1; - ++q2; - } - } - } - return true; - } - - //**************************************************************************************** - /// - /// Convert the byte array to a lower case hex string. - /// - /// byte array to be converted. - /// hex string converted from byte array. - //**************************************************************************************** - public static String StringFromByteArray(byte[] bytes) - { - if (bytes == null || bytes.Length == 0) - { - return "null"; - } - - StringBuilder sb = new StringBuilder(bytes.Length * 2); - - for (int i = 0; i < bytes.Length; i++) - { - byte b = bytes[i]; - - char first = (char)(((b >> 4) & 0x0F) + 0x30); - char second = (char)((b & 0x0F) + 0x30); - - sb.Append(first >= 0x3A ? (char)(first + 0x27) : first); - sb.Append(second >= 0x3A ? (char)(second + 0x27) : second); - } - - return sb.ToString(); - } - } -} // namespace diff --git a/src/Sdk/Common/Common/Utility/BackoffTimerHelper.cs b/src/Sdk/Common/Common/Utility/BackoffTimerHelper.cs deleted file mode 100644 index f2c4df504..000000000 --- a/src/Sdk/Common/Common/Utility/BackoffTimerHelper.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.ComponentModel; - -namespace GitHub.Services.Common -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public static class BackoffTimerHelper - { - public static TimeSpan GetRandomBackoff( - TimeSpan minBackoff, - TimeSpan maxBackoff, - TimeSpan? previousBackoff = null) - { - Random random = null; - if (previousBackoff.HasValue) - { - random = new Random((Int32)previousBackoff.Value.TotalMilliseconds); - } - else - { - random = new Random(); - } - - return TimeSpan.FromMilliseconds(random.Next((Int32)minBackoff.TotalMilliseconds, (Int32)maxBackoff.TotalMilliseconds)); - } - - public static TimeSpan GetExponentialBackoff( - Int32 attempt, - TimeSpan minBackoff, - TimeSpan maxBackoff, - TimeSpan deltaBackoff) - { - Double randomBackoff = (Double)new Random().Next((Int32)(deltaBackoff.TotalMilliseconds * 0.8), (Int32)(deltaBackoff.TotalMilliseconds * 1.2)); - Double additionalBackoff = attempt < 0 ? (Math.Pow(2.0, (Double)attempt)) * randomBackoff : (Math.Pow(2.0, (Double)attempt) - 1.0) * randomBackoff; - return TimeSpan.FromMilliseconds(Math.Min(minBackoff.TotalMilliseconds + additionalBackoff, maxBackoff.TotalMilliseconds)); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/CollectionsExtensions.cs b/src/Sdk/Common/Common/Utility/CollectionsExtensions.cs deleted file mode 100644 index f7d593378..000000000 --- a/src/Sdk/Common/Common/Utility/CollectionsExtensions.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.Common -{ - public static class CollectionsExtensions - { - /// - /// Adds all of the given values to this collection. - /// Can be used with dictionaries, which implement and where T is . - /// For dictionaries, also see - /// - public static TCollection AddRange(this TCollection collection, IEnumerable values) - where TCollection : ICollection - { - foreach (var value in values) - { - collection.Add(value); - } - - return collection; - } - - /// - /// Adds all of the given values to this collection if and only if the values object is not null. - /// See for more details. - /// - public static TCollection AddRangeIfRangeNotNull(this TCollection collection, IEnumerable values) - where TCollection : ICollection - { - if (values != null) - { - collection.AddRange(values); - } - - return collection; - } - } -} diff --git a/src/Sdk/Common/Common/Utility/ConvertUtility.cs b/src/Sdk/Common/Common/Utility/ConvertUtility.cs deleted file mode 100644 index b5f394a40..000000000 --- a/src/Sdk/Common/Common/Utility/ConvertUtility.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; - -namespace GitHub.Services.Common -{ - /// - /// Utility class for wrapping Convert.ChangeType to handle nullable values. - /// - public class ConvertUtility - { - public static object ChangeType(object value, Type type) - { - return ChangeType(value, type, CultureInfo.CurrentCulture); - } - - public static object ChangeType(object value, Type type, IFormatProvider provider) - { - if (type.IsOfType(typeof(Nullable<>))) - { - var nullableConverter = new NullableConverter(type); - return nullableConverter.ConvertTo(value, nullableConverter.UnderlyingType); - } - - return Convert.ChangeType(value, type, provider); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/DictionaryExtensions.cs b/src/Sdk/Common/Common/Utility/DictionaryExtensions.cs deleted file mode 100644 index 1dd010c6a..000000000 --- a/src/Sdk/Common/Common/Utility/DictionaryExtensions.cs +++ /dev/null @@ -1,655 +0,0 @@ -using GitHub.Services.Common.Internal; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; -using System.Linq; - -namespace GitHub.Services.Common -{ - public static class DictionaryExtensions - { - /// - /// Adds a new value to the dictionary or updates the value if the entry already exists. - /// Returns the updated value inserted into the dictionary. - /// - public static V AddOrUpdate(this IDictionary dictionary, - K key, V addValue, Func updateValueFactory) - { - if (dictionary.TryGetValue(key, out V returnValue)) - { - addValue = updateValueFactory(returnValue, addValue); - } - - dictionary[key] = addValue; - return addValue; - } - - /// - /// Returns the value in an IDictionary at the given key, or the default - /// value for that type if it is not present. - /// - public static V GetValueOrDefault(this IDictionary dictionary, K key, V @default = default(V)) - { - V value; - return dictionary.TryGetValue(key, out value) ? value : @default; - } - - /// - /// Returns the value in an IReadOnlyDictionary at the given key, or the default - /// value for that type if it is not present. - /// - public static V GetValueOrDefault(this IReadOnlyDictionary dictionary, K key, V @default = default(V)) - { - V value; - return dictionary.TryGetValue(key, out value) ? value : @default; - } - - /// - /// Returns the value in a Dictionary at the given key, or the default - /// value for that type if it is not present. - /// - /// - /// This overload is necessary to prevent Ambiguous Match issues, as Dictionary implements both - /// IDictionary and IReadonlyDictionary, but neither interface implements the other - /// - public static V GetValueOrDefault(this Dictionary dictionary, K key, V @default = default(V)) - { - V value; - return dictionary.TryGetValue(key, out value) ? value : @default; - } - - /// - /// Returns the value in an IDictionary at the given key, or the default - /// nullable value for that type if it is not present. - /// - public static V? GetNullableValueOrDefault(this IDictionary dictionary, K key, V? @default = default(V?)) where V : struct - { - V value; - return dictionary.TryGetValue(key, out value) ? value : @default; - } - - /// - /// Returns the value in an IReadOnlyDictionary at the given key, or the default - /// nullable value for that type if it is not present. - /// - public static V? GetNullableValueOrDefault(this IReadOnlyDictionary dictionary, K key, V? @default = default(V?)) where V : struct - { - V value; - return dictionary.TryGetValue(key, out value) ? value : @default; - } - - /// - /// Returns the value in a Dictionary at the given key, or the default - /// nullable value for that type if it is not present. - /// - /// - /// This overload is necessary to prevent Ambiguous Match issues, as Dictionary implements both - /// IDictionary and IReadonlyDictionary, but neither interface implements the other - /// - public static V? GetNullableValueOrDefault(this Dictionary dictionary, K key, V? @default = default(V?)) where V : struct - { - V value; - return dictionary.TryGetValue(key, out value) ? value : @default; - } - - /// - /// Returns the value in an IReadonlyDictionary with values of type - /// casted as values of requested type, or the defualt if the key is not found or - /// if the value was found but not compatabile with the requested type. - /// - /// The key type - /// The requested type of the stored value - /// the dictionary to perform the lookup on - /// The key to lookup - /// Optional: the default value to return if not found - /// The value at the key, or the default if it is not found or of the wrong type - public static V GetCastedValueOrDefault(this IReadOnlyDictionary dictionary, K key, V @default = default(V)) - { - object value; - return dictionary.TryGetValue(key, out value) && value is V ? (V)value : @default; - } - - /// - /// Returns the value in an IDictionary with values of type - /// casted as values of requested type, or the defualt if the key is not found or - /// if the value was found but not compatabile with the requested type. - /// - /// The key type - /// The requested type of the stored value - /// the dictionary to perform the lookup on - /// The key to lookup - /// Optional: the default value to return if not found - /// The value at the key, or the default if it is not found or of the wrong type - public static V GetCastedValueOrDefault(this IDictionary dictionary, K key, V @default = default(V)) - { - object value; - return dictionary.TryGetValue(key, out value) && value is V ? (V)value : @default; - } - - /// - /// Returns the value in a Dictionary with values of type - /// casted as values of requested type, or the defualt if the key is not found or - /// if the value was found but not compatabile with the requested type. - /// - /// - /// This overload is necessary to prevent Ambiguous Match issues, as Dictionary implements both - /// IDictionary and IReadonlyDictionary, but neither interface implements the other - /// - /// The key type - /// The requested type of the stored value - /// the dictionary to perform the lookup on - /// The key to lookup - /// Optional: the default value to return if not found - /// The value at the key, or the default if it is not found or of the wrong type - public static V GetCastedValueOrDefault(this Dictionary dictionary, K key, V @default = default(V)) - { - return ((IReadOnlyDictionary)dictionary).GetCastedValueOrDefault(key, @default); - } - - /// - /// Returns the value in an IDictionary at the given key, or creates a new value using the default constructor, adds it at the given key, and returns the new value. - /// - public static V GetOrAddValue(this IDictionary dictionary, K key) where V : new() - { - V value = default(V); - - if (!dictionary.TryGetValue(key, out value)) - { - value = new V(); - dictionary.Add(key, value); - } - - return value; - } - - /// - /// Returns the value in an IDictionary at the given key, or creates a new value using the given delegate, adds it at the given key, and returns the new value. - /// - public static V GetOrAddValue(this IDictionary dictionary, K key, Func createValueToAdd) - { - V value = default(V); - - if (!dictionary.TryGetValue(key, out value)) - { - value = createValueToAdd(); - dictionary.Add(key, value); - } - - return value; - } - - /// - /// Adds all of the given key-value pairs (such as from another dictionary, since IDictionary implements IEnumerable) to this dictionary. - /// Overwrites preexisting values of the same key. - /// To avoid overwriting values, use . - /// - /// this dictionary - public static TDictionary SetRange(this TDictionary dictionary, IEnumerable> keyValuePairs) - where TDictionary : IDictionary - { - foreach (var keyValuePair in keyValuePairs) - { - dictionary[keyValuePair.Key] = keyValuePair.Value; - } - - return dictionary; - } - - /// - /// Adds all of the given key-value pairs if and only if the key-value pairs object is not null. - /// See for more details. - /// - /// this dictionary - public static TDictionary SetRangeIfRangeNotNull(this TDictionary dictionary, IEnumerable> keyValuePairs) - where TDictionary : IDictionary - { - if (keyValuePairs != null) - { - dictionary.SetRange(keyValuePairs); - } - - return dictionary; - } - - /// - /// Adds all of the given key-value pairs to this lazily initialized dictionary if and only if the key-value pairs object is not null or empty. - /// Does not initialize the dictionary otherwise. - /// See for more details. - /// - /// this dictionary - public static Lazy SetRangeIfRangeNotNullOrEmpty(this Lazy lazyDictionary, IEnumerable> keyValuePairs) - where TDictionary : IDictionary - { - if (keyValuePairs != null && keyValuePairs.Any()) - { - lazyDictionary.Value.SetRange(keyValuePairs); - } - - return lazyDictionary; - } - - /// - /// Tries to add a key to the dictionary, if it does not already exist. - /// - /// The instance where TValue is object - /// The key to add - /// The value to add - /// true if the key was added with the specified value. If the key already exists, the method returns false without updating the value. - public static bool TryAdd(this IDictionary dictionary, TKey key, TValue value) - { - if (dictionary.ContainsKey(key)) - { - return false; - } - - dictionary.Add(key, value); - return true; - } - - /// - /// Tries to add all of the given key-values pairs to the dictionary, if they do not already exist. - /// - /// The instance where TValue is object - /// The values to try and add to the dictionary - /// true if the all of the values were added. If any of the keys exists, the method returns false without updating the value. - public static bool TryAddRange(this TDictionary dictionary, IEnumerable> keyValuePairs) where TDictionary : IDictionary - { - bool rangeAdded = true; - foreach (var keyValuePair in keyValuePairs) - { - rangeAdded &= dictionary.TryAdd(keyValuePair.Key, keyValuePair.Value); - } - - return rangeAdded; - } - - /// - /// Gets the value of associated with the specified key or default value if - /// either the key is not present or the value is not of type . - /// - /// The type of the value associated with the specified key. - /// The instance where TValue is object. - /// The key whose value to get. - /// When this method returns, the value associated with the specified key, if the key is found; otherwise, the default value for the type of the value parameter. - /// true if key was found, value is non-null, and value is of type ; otherwise false. - public static bool TryGetValue(this IDictionary dictionary, string key, out T value) - { - object valueObj; - if (dictionary.TryGetValue(key, out valueObj)) - { - //Handle Guids specially - if (typeof(T) == typeof(Guid)) - { - Guid guidVal; - if (dictionary.TryGetGuid(key, out guidVal)) - { - value = (T)(object)guidVal; - return true; - } - } - - //Handle Enums specially - if (typeof(T).GetTypeInfo().IsEnum) - { - if (dictionary.TryGetEnum(key, out value)) - { - return true; - } - } - - if (valueObj is T) - { - value = (T)valueObj; - return true; - } - } - - value = default(T); - return false; - } - - /// - /// Gets the value of T associated with the specified key if the value can be converted to T according to . - /// - /// the type of the value associated with the specified key - /// the dictionary from which we should retrieve the value - /// the key of the value to retrieve - /// when this method returns, the value associated with the specified key, if the key is found and the value is convertible to T, - /// or default of T, if not - /// true if the value was retrieved successfully, otherwise false - public static bool TryGetValidatedValue(this IDictionary dictionary, string key, out T value, bool allowNull = true) - { - value = default(T); - //try to convert to T. T *must* be something with - //TypeCode != TypeCode.object (and not DBNull) OR - //byte[] or guid or object. - if (!PropertyValidation.IsValidConvertibleType(typeof(T))) - { - return false; - } - - //special case guid... - if (typeof(T) == typeof(Guid)) - { - Guid guidVal; - if (dictionary.TryGetGuid(key, out guidVal)) - { - value = (T)(object)guidVal; - return true; - } - } - else - { - object objValue = null; - if (dictionary.TryGetValue(key, out objValue)) - { - if (objValue == null) - { - //we found it and it is - //null, which may be okay depending on the allowNull flag - //value is already = default(T) - return allowNull; - } - - if (typeof(T).GetTypeInfo().IsAssignableFrom(objValue.GetType().GetTypeInfo())) - { - value = (T)objValue; - return true; - } - - if (typeof(T).GetTypeInfo().IsEnum) - { - if (dictionary.TryGetEnum(key, out value)) - { - return true; - } - } - - if (objValue is string) - { - TypeCode typeCode = Type.GetTypeCode(typeof(T)); - - try - { - value = (T)Convert.ChangeType(objValue, typeCode, CultureInfo.CurrentCulture); - return true; - } - catch (Exception) - { - return false; - } - } - } - } - - return false; - } - - /// - /// Gets the Enum value associated with the specified key if the value can be converted to an Enum. - /// - public static bool TryGetEnum(this IDictionary dictionary, string key, out T value) - { - value = default(T); - - object objValue = null; - - if (dictionary.TryGetValue(key, out objValue)) - { - if (objValue is string) - { - try - { - value = (T)Enum.Parse(typeof(T), (string)objValue, true); - return true; - } - catch (ArgumentException) - { - // Provided string is not a member of enumeration - } - } - else - { - try - { - value = (T)objValue; - return true; - } - catch (InvalidCastException) - { - // Value cannot be cast to the enum - } - } - } - - return false; - } - - /// - /// Gets the Guid value associated with the specified key if the value can be converted to a Guid. - /// - public static bool TryGetGuid(this IDictionary dictionary, string key, out Guid value) - { - value = Guid.Empty; - - object objValue = null; - - if (dictionary.TryGetValue(key, out objValue)) - { - if (objValue is Guid) - { - value = (Guid)objValue; - return true; - } - else if (objValue is string) - { - return Guid.TryParse((string)objValue, out value); - } - } - - return false; - } - - /// - /// Copies the values from this into a destination . - /// - /// The source dictionary from which to from. - /// The destination dictionary to which to copy to. - /// Optional filtering predicate. - /// The destination dictionary. - /// - /// If is null, no changes are made. - /// - public static IDictionary Copy(this IDictionary source, IDictionary dest, Predicate filter) - { - if (dest == null) - { - return dest; - } - - foreach (var key in source.Keys) - { - if (filter == null || filter(key)) - { - dest[key] = source[key]; - } - } - - return dest; - } - - /// - /// Copies the values from this into a destination . - /// - /// The source dictionary from which to from. - /// The destination dictionary to which to copy to. - /// The destination dictionary. - /// - /// If is null, no changes are made. - /// - public static IDictionary Copy(this IDictionary source, IDictionary dest) - { - return source.Copy(dest, filter: null); - } - - /// - /// Sets the given key-value pair if and only if the value is not null. - /// - public static IDictionary SetIfNotNull( - this IDictionary dictionary, - TKey key, - TValue value) - where TValue : class - { - if (value != null) - { - dictionary[key] = value; - } - - return dictionary; - } - - /// - /// Sets the given key-value pair on this lazily initialized dictionary if and only if the value is not null. - /// Does not initialize the dictionary otherwise. - /// - public static Lazy> SetIfNotNull( - this Lazy> dictionary, - TKey key, - TValue value) - where TValue : class - { - if (value != null) - { - dictionary.Value[key] = value; - } - - return dictionary; - } - - /// - /// Adds the given key-value pair to this dictionary if the value is nonnull - /// and does not conflict with a preexisting value for the same key. - /// No-ops if the value is null. - /// No-ops if the preexisting value for the same key is equal to the given value. - /// Throws if the preexisting value for the same key is not equal to the given value. - /// - public static IDictionary SetIfNotNullAndNotConflicting( - this IDictionary dictionary, - TKey key, - TValue value, - string valuePropertyName = "value", - string dictionaryName = "dictionary") - where TValue : class - { - if (value == null) - { - return dictionary; - } - - dictionary.CheckForConflict(key, value, valuePropertyName, dictionaryName, ignoreDefaultValue: true); - - dictionary[key] = value; - - return dictionary; - } - - /// - /// Adds the given key-value pair to this dictionary if the value does not conflict with a preexisting value for the same key. - /// No-ops if the preexisting value for the same key is equal to the given value. - /// Throws if the preexisting value for the same key is not equal to the given value. - /// - public static IDictionary SetIfNotConflicting( - this IDictionary dictionary, - TKey key, - TValue value, - string valuePropertyName = "value", - string dictionaryName = "dictionary") - { - dictionary.CheckForConflict(key, value, valuePropertyName, dictionaryName, ignoreDefaultValue: false); - - dictionary[key] = value; - - return dictionary; - } - - /// - /// Throws if this IDictionary contains a preexisting value for the same key which is not equal to the given key. - /// - public static void CheckForConflict( - this IDictionary dictionary, - TKey key, - TValue value, - string valuePropertyName = "value", - string dictionaryName = "dictionary", - bool ignoreDefaultValue = true) - { - if (Equals(value, default(TValue)) && ignoreDefaultValue) - { - return; - } - - TValue previousValue = default(TValue); - - if (!dictionary.TryGetValue(key, out previousValue)) - { - return; - } - - if (Equals(previousValue, default(TValue)) && ignoreDefaultValue) - { - return; - } - - if (Equals(value, previousValue)) - { - return; - } - - throw new ArgumentException( - String.Format(CultureInfo.CurrentCulture, - "Parameter {0} = '{1}' inconsistent with {2}['{3}'] => '{4}'", - valuePropertyName, value, dictionaryName, key, previousValue)); - } - - /// - /// Throws if this IReadOnlyDictionary contains a preexisting value for the same key which is not equal to the given key. - /// - public static void CheckForConflict( - this IReadOnlyDictionary dictionary, - TKey key, - TValue value, - string valuePropertyName = "value", - string dictionaryName = "dictionary", - bool ignoreDefaultValue = true) - { - if (Equals(value, default(TValue)) && ignoreDefaultValue) - { - return; - } - - TValue previousValue = default(TValue); - - if (!dictionary.TryGetValue(key, out previousValue)) - { - return; - } - - if (Equals(previousValue, default(TValue)) && ignoreDefaultValue) - { - return; - } - - if (Equals(value, previousValue)) - { - return; - } - - throw new ArgumentException( - String.Format(CultureInfo.CurrentCulture, - "Parameter {0} = \"{1}\" is inconsistent with {2}[\"{3}\"] => \"{4}\"", - valuePropertyName, value, dictionaryName, key, previousValue)); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/EnumerableExtensions.cs b/src/Sdk/Common/Common/Utility/EnumerableExtensions.cs deleted file mode 100644 index 470317c6c..000000000 --- a/src/Sdk/Common/Common/Utility/EnumerableExtensions.cs +++ /dev/null @@ -1,422 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; - -namespace GitHub.Services.Common -{ - public static class EnumerableExtensions - { - /// - /// Returns an empty if the supplied source is null. - /// - /// The type of the elements of source. - /// A sequence of values to return when not null. - /// The source sequence, or a new empty one if source was null. - public static IEnumerable AsEmptyIfNull(this IEnumerable source) - => source ?? Enumerable.Empty(); - - /// - /// If an enumerable is null, and it has a default constructor, return an empty collection by calling the - /// default constructor. - /// - /// The type of the Enumerable - /// A sequence of values to return when not null - /// The source sequence, or a new empty one if source was null. - public static TEnumerable AsEmptyIfNull(this TEnumerable source) where TEnumerable : class, IEnumerable, new() - => source ?? new TEnumerable(); - - /// - /// Splits a source into several s - /// with a max size of batchSize. - /// Note that batchSize must be one or larger. - /// - /// A sequence of values to split into smaller batches. - /// The number of elements to place in each batch. - /// The original collection, split into batches. - public static IEnumerable> Batch(this IEnumerable source, int batchSize) - { - ArgumentUtility.CheckForNull(source, nameof(source)); - ArgumentUtility.CheckBoundsInclusive(batchSize, 1, int.MaxValue, nameof(batchSize)); - - var nextBatch = new List(batchSize); - foreach (T item in source) - { - nextBatch.Add(item); - if (nextBatch.Count == batchSize) - { - yield return nextBatch; - nextBatch = new List(batchSize); - } - } - - if (nextBatch.Count > 0) - { - yield return nextBatch; - } - } - - /// - /// Splits an into two partitions, determined by the supplied predicate. Those - /// that follow the predicate are returned in the first, with the remaining elements in the second. - /// - /// The type of the elements of source. - /// The source enumerable to partition. - /// The predicate applied to filter the items into their partitions. - /// An object containing the matching and nonmatching results. - public static PartitionResults Partition(this IEnumerable source, Predicate predicate) - { - ArgumentUtility.CheckForNull(source, nameof(source)); - ArgumentUtility.CheckForNull(predicate, nameof(predicate)); - - var results = new PartitionResults(); - - foreach (var item in source) - { - if (predicate(item)) - { - results.MatchingPartition.Add(item); - } - else - { - results.NonMatchingPartition.Add(item); - } - } - - return results; - } - - /// - /// Partitions items from a source IEnumerable into N+1 lists, where the first N lists are determened - /// by the sequential check of the provided predicates, with the N+1 list containing those items - /// which matched none of the provided predicates. - /// - /// The type of the elements in source. - /// The source containing the elements to partition - /// The predicates to determine which list the results end up in - /// An item containing the matching collections and a collection containing the non-matching items. - public static MultiPartitionResults Partition(this IEnumerable source, params Predicate[] predicates) - { - ArgumentUtility.CheckForNull(source, nameof(source)); - ArgumentUtility.CheckForNull(predicates, nameof(predicates)); - - var range = Enumerable.Range(0, predicates.Length).ToList(); - - var results = new MultiPartitionResults(); - results.MatchingPartitions.AddRange(range.Select(_ => new List())); - - foreach (var item in source) - { - bool added = false; - - foreach (var predicateIndex in range.Where(predicateIndex => predicates[predicateIndex](item))) - { - results.MatchingPartitions[predicateIndex].Add(item); - added = true; - break; - } - - if (!added) - { - results.NonMatchingPartition.Add(item); - } - } - - return results; - } - - /// - /// Merges two sorted IEnumerables using the given comparison function which - /// defines a total ordering of the data. - /// - public static IEnumerable Merge( - this IEnumerable first, - IEnumerable second, - IComparer comparer) - { - return Merge(first, second, comparer == null ? (Func)null : comparer.Compare); - } - - /// - /// Merges two sorted IEnumerables using the given comparison function which - /// defines a total ordering of the data. - /// - public static IEnumerable Merge( - this IEnumerable first, - IEnumerable second, - Func comparer) - { - ArgumentUtility.CheckForNull(first, nameof(first)); - ArgumentUtility.CheckForNull(second, nameof(second)); - ArgumentUtility.CheckForNull(comparer, nameof(comparer)); - - using (IEnumerator e1 = first.GetEnumerator()) - using (IEnumerator e2 = second.GetEnumerator()) - { - bool e1Valid = e1.MoveNext(); - bool e2Valid = e2.MoveNext(); - - while (e1Valid && e2Valid) - { - if (comparer(e1.Current, e2.Current) <= 0) - { - yield return e1.Current; - - e1Valid = e1.MoveNext(); - } - else - { - yield return e2.Current; - - e2Valid = e2.MoveNext(); - } - } - - while (e1Valid) - { - yield return e1.Current; - - e1Valid = e1.MoveNext(); - } - - while (e2Valid) - { - yield return e2.Current; - - e2Valid = e2.MoveNext(); - } - } - } - - /// - /// Merges two sorted IEnumerables using the given comparison function which defines a total ordering of the data. Unlike Merge, this method requires that - /// both IEnumerables contain distinct elements. Likewise, the returned IEnumerable will only contain distinct elements. If the same element appears in both inputs, - /// it will appear only once in the output. - /// - /// Example: - /// first: [1, 3, 5] - /// second: [4, 5, 7] - /// result: [1, 3, 4, 5, 7] - /// - public static IEnumerable MergeDistinct( - this IEnumerable first, - IEnumerable second, - IComparer comparer) - { - return MergeDistinct(first, second, comparer == null ? (Func)null : comparer.Compare); - } - - /// - /// Merges two sorted IEnumerables using the given comparison function which defines a total ordering of the data. Unlike Merge, this method requires that - /// both IEnumerables contain distinct elements. Likewise, the returned IEnumerable will only contain distinct elements. If the same element appears in both inputs, - /// it will appear only once in the output. - /// - /// Example: - /// first: [1, 3, 5] - /// second: [4, 5, 7] - /// result: [1, 3, 4, 5, 7] - /// - public static IEnumerable MergeDistinct( - this IEnumerable first, - IEnumerable second, - Func comparer) - { - ArgumentUtility.CheckForNull(first, nameof(first)); - ArgumentUtility.CheckForNull(second, nameof(second)); - ArgumentUtility.CheckForNull(comparer, nameof(comparer)); - - using (IEnumerator e1 = first.GetEnumerator()) - using (IEnumerator e2 = second.GetEnumerator()) - { - bool e1Valid = e1.MoveNext(); - bool e2Valid = e2.MoveNext(); - - while (e1Valid && e2Valid) - { - if (comparer(e1.Current, e2.Current) < 0) - { - yield return e1.Current; - - e1Valid = e1.MoveNext(); - } - else if (comparer(e1.Current, e2.Current) > 0) - { - yield return e2.Current; - - e2Valid = e2.MoveNext(); - } - else - { - yield return e1.Current; - - e1Valid = e1.MoveNext(); - e2Valid = e2.MoveNext(); - } - } - - while (e1Valid) - { - yield return e1.Current; - - e1Valid = e1.MoveNext(); - } - - while (e2Valid) - { - yield return e2.Current; - - e2Valid = e2.MoveNext(); - } - } - } - - /// - /// Creates a HashSet based on the elements in . - /// - public static HashSet ToHashSet( - IEnumerable source) - { - return new HashSet(source); - } - - /// - /// Creates a HashSet with equality comparer based on the elements - /// in . - /// - public static HashSet ToHashSet( - IEnumerable source, - IEqualityComparer comparer) - { - return new HashSet(source, comparer); - } - - /// - /// Creates a HashSet based on the elements in , using transformation - /// function . - /// - public static HashSet ToHashSet( - this IEnumerable source, - Func selector) - { - return new HashSet(source.Select(selector)); - } - - /// - /// Creates a HashSet with equality comparer based on the elements - /// in , using transformation function . - /// - public static HashSet ToHashSet( - this IEnumerable source, - Func selector, - IEqualityComparer comparer) - { - return new HashSet(source.Select(selector), comparer); - } - - /// - /// Executes the specified action to each of the items in the collection - /// The type of the elements in the collection. - /// The collection on which the action will be performed - /// The action to be performed - /// - public static void ForEach(this IEnumerable collection, Action action) - { - ArgumentUtility.CheckForNull(action, nameof(action)); - ArgumentUtility.CheckForNull(collection, nameof(collection)); - - foreach (T item in collection) - { - action(item); - } - } - - /// - /// Add the item to the List if the condition is satisfied - /// - /// The type of the elements in the collection. - /// The collection on which the action will be performed - /// The Condition under which the item will be added - /// The element to be added - public static void AddIf(this List list, bool condition, T element) - { - if (condition) - { - list.Add(element); - } - } - - /// - /// Converts a collection of key-value string pairs to a NameValueCollection. - /// - /// The key-value string pairs. - /// The NameValueCollection. - public static NameValueCollection ToNameValueCollection(this IEnumerable> pairs) - { - NameValueCollection collection = new NameValueCollection(); - - foreach (KeyValuePair pair in pairs) - { - collection.Add(pair.Key, pair.Value); - } - - return collection; - } - - public static IList

PartitionSolveAndMergeBack(this IList source, Predicate predicate, Func, IList

> matchingPartitionSolver, Func, IList

> nonMatchingPartitionSolver) - { - ArgumentUtility.CheckForNull(source, nameof(source)); - ArgumentUtility.CheckForNull(predicate, nameof(predicate)); - ArgumentUtility.CheckForNull(matchingPartitionSolver, nameof(matchingPartitionSolver)); - ArgumentUtility.CheckForNull(nonMatchingPartitionSolver, nameof(nonMatchingPartitionSolver)); - - var partitionedSource = new PartitionResults>(); - - for (int sourceCnt = 0; sourceCnt < source.Count; sourceCnt++) - { - var item = source[sourceCnt]; - - if (predicate(item)) - { - partitionedSource.MatchingPartition.Add(new Tuple(sourceCnt, item)); - } - else - { - partitionedSource.NonMatchingPartition.Add(new Tuple(sourceCnt, item)); - } - } - - var solvedResult = new List

(source.Count); - if (partitionedSource.MatchingPartition.Any()) - { - solvedResult.AddRange(matchingPartitionSolver(partitionedSource.MatchingPartition.Select(x => x.Item2).ToList())); - } - - if (partitionedSource.NonMatchingPartition.Any()) - { - solvedResult.AddRange(nonMatchingPartitionSolver(partitionedSource.NonMatchingPartition.Select(x => x.Item2).ToList())); - } - - var result = Enumerable.Repeat(default(P), source.Count).ToList(); - - if (solvedResult.Count != source.Count) - { - return solvedResult; // either we can throw here or just return solvedResult and ignore! - } - - for (int resultCnt = 0; resultCnt < source.Count; resultCnt++) - { - if (resultCnt < partitionedSource.MatchingPartition.Count) - { - result[partitionedSource.MatchingPartition[resultCnt].Item1] = solvedResult[resultCnt]; - } - else - { - result[partitionedSource.NonMatchingPartition[resultCnt - partitionedSource.MatchingPartition.Count].Item1] = solvedResult[resultCnt]; - } - } - - return result; - } - } -} diff --git a/src/Sdk/Common/Common/Utility/ExpectedExceptionExtensions.cs b/src/Sdk/Common/Common/Utility/ExpectedExceptionExtensions.cs deleted file mode 100644 index c9dab13f7..000000000 --- a/src/Sdk/Common/Common/Utility/ExpectedExceptionExtensions.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; - -namespace GitHub.Services.Common -{ - public static class ExpectedExceptionExtensions - { - private const string c_expectedKey = "isExpected"; - - ///

- /// Mark the exception as expected when caused by user input in the provided area. - /// If the exception thrower is the same area as the caller, the exception will be treated as expected. - /// However, in the case of a service to service call, then the exception will be treated as unexpected. - /// ex: GitRefsController throws ArgumentException called directly by a user then the exception will be expected - /// GitRefsController throws ArgumentException called by BuildDefinitionController then the exception will not be expected. - /// - /// - /// This allows for the use case "throw new ArgumentException().Expected(c_area)" - /// This will overwrite the expected area if called a second time. - /// This should not throw any exceptions as to avoid hiding the exception that was already caught. - /// See https://vsowiki.com/index.php?title=Whitelisting_Expected_Commands_and_Exceptions - /// - /// The area name where the exception is expected. This will be compared against IVssRequestContext.ServiceName. Area should be non-empty - /// after setting the area - public static Exception Expected(this Exception ex, string area) - { - if (!string.IsNullOrEmpty(area)) - { - ex.Data[c_expectedKey] = area; - } - - return ex; - } - - /// - /// Use this to "expect" an exception within the exception filtering syntax. - /// ex: - /// catch(ArgumentException ex) when (ex.ExpectedExceptionFilter(c_area)) - /// See - /// - /// false always - public static bool ExpectedExceptionFilter(this Exception ex, string area) - { - ex.Expected(area); - return false; - } - - /// - /// Determine if the exception is expected in the specified area. - /// Case is ignored for the area comparison. - /// - public static bool IsExpected(this Exception ex, string area) - { - if (string.IsNullOrEmpty(area)) - { - return false; - } - - // An exception's Data property is an IDictionary, which returns null for keys that do not exist. - return area.Equals(ex.Data[c_expectedKey] as string, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/HttpHeaders.cs b/src/Sdk/Common/Common/Utility/HttpHeaders.cs deleted file mode 100644 index e91d0f28a..000000000 --- a/src/Sdk/Common/Common/Utility/HttpHeaders.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace GitHub.Services.Common.Internal -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public static class HttpHeaders - { - public const String ActivityId = "ActivityId"; - public const String ETag = "ETag"; - public const String TfsVersion = "X-TFS-Version"; - public const String TfsRedirect = "X-TFS-Redirect"; - public const String TfsException = "X-TFS-Exception"; - public const String TfsServiceError = "X-TFS-ServiceError"; - public const String TfsSessionHeader = "X-TFS-Session"; - public const String TfsSoapException = "X-TFS-SoapException"; - public const String TfsFedAuthRealm = "X-TFS-FedAuthRealm"; - public const String TfsFedAuthIssuer = "X-TFS-FedAuthIssuer"; - public const String TfsFedAuthRedirect = "X-TFS-FedAuthRedirect"; - public const String VssAuthorizationEndpoint = "X-VSS-AuthorizationEndpoint"; - public const String VssPageHandlers = "X-VSS-PageHandlers"; - public const String VssE2EID = "X-VSS-E2EID"; - public const String VssOrchestrationId = "X-VSS-OrchestrationId"; - public const String AuditCorrelationId = "X-VSS-Audit-CorrelationId"; - public const String VssOriginUserAgent = "X-VSS-OriginUserAgent"; - - // Internal Headers that we use in our client. - public const string TfsInstanceHeader = "X-TFS-Instance"; - public const string TfsVersionOneHeader = "X-VersionControl-Instance"; - - [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Tfs")] - public const string TfsImpersonate = "X-TFS-Impersonate"; - public const string TfsSubjectDescriptorImpersonate = "X-TFS-SubjectDescriptorImpersonate"; - - public const string MsContinuationToken = "X-MS-ContinuationToken"; - public const String VssUserData = "X-VSS-UserData"; - public const String VssAgentHeader = "X-VSS-Agent"; - public const String VssAuthenticateError = "X-VSS-AuthenticateError"; - public const string VssReauthenticationAction = "X-VSS-ReauthenticationAction"; - public const string RequestedWith = "X-Requested-With"; - - public const String VssRateLimitResource = "X-RateLimit-Resource"; - public const String VssRateLimitDelay = "X-RateLimit-Delay"; - public const String VssRateLimitLimit = "X-RateLimit-Limit"; - public const String VssRateLimitRemaining = "X-RateLimit-Remaining"; - public const String VssRateLimitReset = "X-RateLimit-Reset"; - public const String RetryAfter = "Retry-After"; - - public const String VssGlobalMessage = "X-VSS-GlobalMessage"; - - public const String VssRequestRouted = "X-VSS-RequestRouted"; - public const String VssUseRequestRouting = "X-VSS-UseRequestRouting"; - - public const string VssResourceTenant = "X-VSS-ResourceTenant"; - public const String VssOverridePrompt = "X-VSS-OverridePrompt"; - - public const String VssOAuthS2STargetService = "X-VSS-S2STargetService"; - public const String VssHostOfflineError = "X-VSS-HostOfflineError"; - - public const string VssForceMsaPassThrough = "X-VSS-ForceMsaPassThrough"; - public const string VssRequestPriority = "X-VSS-RequestPriority"; - - // This header represents set of ';' delimited mappings (usually one) that are considered by DetermineAccessMapping API - public const string VssClientAccessMapping = "X-VSS-ClientAccessMapping"; - - // This header is used to download artifacts anonymously. - // N.B. Some resources secured with download tickets (e.g. TFVC files) are still retrieved with the download - // ticket in the query string. - public const string VssDownloadTicket = "X-VSS-DownloadTicket"; - - public const string IfModifiedSince = "If-Modified-Since"; - public const string Authorization = "Authorization"; - public const string Location = "Location"; - public const string ProxyAuthenticate = "Proxy-Authenticate"; - public const string WwwAuthenticate = "WWW-Authenticate"; - - public const string AfdIncomingRouteKey = "X-FD-RouteKey"; - public const string AfdOutgoingRouteKey = "X-AS-RouteKey"; - public const string AfdIncomingEndpointList = "X-FD-RouteKeyApplicationEndpointList"; - public const string AfdOutgoingEndpointList = "X-AS-RouteKeyApplicationEndpointList"; - public const string AfdResponseRef = "X-MSEdge-Ref"; - public const string AfdIncomingClientIp = "X-FD-ClientIP"; - public const string AfdIncomingSocketIp = "X-FD-SocketIP"; - public const string AfdIncomingRef = "X-FD-Ref"; - public const string AfdIncomingEventId = "X-FD-EventId"; - public const string AfdIncomingEdgeEnvironment = "X-FD-EdgeEnvironment"; - public const string AfdOutgoingQualityOfResponse = "X-AS-QualityOfResponse"; - public const string AfdOutgoingClientIp = "X-MSEdge-ClientIP"; - } -} diff --git a/src/Sdk/Common/Common/Utility/LongPathUtility.cs b/src/Sdk/Common/Common/Utility/LongPathUtility.cs deleted file mode 100644 index f179bbe9b..000000000 --- a/src/Sdk/Common/Common/Utility/LongPathUtility.cs +++ /dev/null @@ -1,553 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - /// - /// Provides path normalization/expansion for absolute, relative and UNC-style paths - /// and supports paths that contain more than 248 characters. - /// - /// - /// This utility class can be used in place of the .NET Path and Directory classes - /// that throw System.IO.PathTooLongException when paths are longer than 248 characters - /// - public static class LongPathUtility - { - private static Regex AbsolutePathRegEx = new Regex(@"^([a-zA-Z]:\\|\\\\)", RegexOptions.CultureInvariant | RegexOptions.Compiled); - private const int ERROR_FILE_NOT_FOUND = 2; - - /// - /// Returns a list of directory names under the path specified, and optionally all subdirectories - /// - /// The directory to search - /// Specifies whether the search operation should include only the currect directory or all subdirectories - /// A list of all subdirectories - public static IEnumerable EnumerateDirectories(string path, bool recursiveSearch) - { - var directoryPaths = new List(); - EnumerateDirectoriesInternal(directoryPaths, path, recursiveSearch); - return directoryPaths; - } - - /// - /// Returns a list of file names under the path specified, and optionally within all subdirectories. - /// - /// The directory to search - /// Specifies whether the search operation should include only the current directory or all subdirectories - /// - /// A list of full file names(including path) contained in the directory specified that match the specified search pattern. - public static IEnumerable EnumerateFiles(string path, bool recursiveSearch) - { - return EnumerateFiles(path, "*", recursiveSearch); - } - - /// - /// Returns an enumerable collection of file names that match a search pattern in a specified path, - /// and optionally searches subdirectories. - /// - /// The directory to search - /// The search string to match against the names of the files - /// Specifies whether the search operation should include only the current directory or all subdirectories - /// - /// A list of full file names(including path) contained in the directory specified (and subdirectories optionally) that match the specified pattern. - /// - public static IEnumerable EnumerateFiles(string path, string matchPattern, bool recursiveSearch) - { - if (!DirectoryExists(path)) - { - throw new DirectoryNotFoundException($"The path '{path}' is not a valid directory."); - } - - var filePaths = new List(); - EnumerateFilesInternal(filePaths, path, matchPattern, recursiveSearch); - return filePaths; - } - - /// - /// Returns true/false whether the file exists. This method inspects the - /// file system attributes and supports files without extensions (ex: DIRS, Sources). This method - /// supports file paths that are longer than 260 characters. - /// - /// The file path to inspect - /// - /// True if the file exists or false if not - /// - public static bool FileExists(string filePath) - { - return FileOrDirectoryExists(filePath, isDirectory: false); - } - - /// - /// Returns true/false whether the directory exists. This method inspects the - /// file system attributes and supports files without extensions (ex: DIRS, Sources). This method - /// supports file paths that are longer than 260 characters. - /// - /// The file path to inspect - /// - /// True if the directory exists or false if not - /// - public static bool DirectoryExists(string directoryPath) - { - return FileOrDirectoryExists(directoryPath, isDirectory: true); - } - - private static bool FileOrDirectoryExists(string filePath, bool isDirectory) - { - if (String.IsNullOrWhiteSpace(filePath)) - { - throw new ArgumentException("A path to the file is required and cannot be null, empty or whitespace", "filePath"); - } - - bool pathExists = false; - - // File names may or may not include an extension (ex: DIRS, Sources). We have to look at the attributes - // on the file system object in order to distinguish a directory from a file - var attributes = (FlagsAndAttributes)NativeMethods.GetFileAttributes(filePath); - - if (attributes != FlagsAndAttributes.InvalidFileAttributes) - { - bool pathIsDirectory = (attributes & FlagsAndAttributes.Directory) == FlagsAndAttributes.Directory; - - if (pathIsDirectory == isDirectory) - { - pathExists = true; - } - } - - return pathExists; - } - - /// - /// Returns the fully expanded/normalized path. This method supports paths that are - /// longer than 248 characters. - /// - /// The file or directory path - /// - public static string GetFullNormalizedPath(string path) - { - if (String.IsNullOrWhiteSpace(path)) - { - throw new ArgumentException("A path is required and cannot be null, empty or whitespace", "path"); - } - - string outPath = path; - - // We need the length of the absolute path in order to prepare a buffer of - // the correct size - uint bufferSize = NativeMethods.GetFullPathName(path, 0, null, null); - int lastWin32Error = Marshal.GetLastWin32Error(); - - if (bufferSize > 0) - { - var absolutePath = new StringBuilder((int)bufferSize); - uint length = NativeMethods.GetFullPathName(path, bufferSize, absolutePath, null); - lastWin32Error = Marshal.GetLastWin32Error(); - - if (length > 0) - { - outPath = absolutePath.ToString(); - } - else - { - // Path resolution failed - throw new Win32Exception( - lastWin32Error, - String.Format( - CultureInfo.InvariantCulture, - "Path normalization/expansion failed. The path length was not returned by the Kernel32 subsystem for '{0}'.", - path - ) - ); - } - } - else - { - // Path resolution failed and the path length could not - // be determined - throw new Win32Exception( - lastWin32Error, - String.Format( - CultureInfo.InvariantCulture, - "Path normalization/expansion failed. A full path was not returned by the Kernel32 subsystem for '{0}'.", - path - ) - ); - } - - return outPath != null ? outPath.TrimEnd('\\') : null; - } - - /// - /// Determines whether the specified path is an absolute path or not. - /// - /// The path to be tested. - /// - /// true if the path is absolute; otherwise, false. - /// - public static bool IsAbsolutePath(string path) - { - return LongPathUtility.AbsolutePathRegEx.Match(path).Success; - } - - public static string RemoveExtendedLengthPathPrefix(string inPath) - { - string outPath = inPath; - - if (!String.IsNullOrWhiteSpace(inPath)) - { - if (inPath.StartsWith("\\", StringComparison.OrdinalIgnoreCase)) - { - // ex: \\?\UNC\server\share to \\server\share - outPath = inPath.Replace(@"\\?\UNC", @"\"); - - // ex: \\?\c:\windows to c:\windows - outPath = outPath.Replace(@"\\?\", String.Empty); - } - } - - return outPath; - } - - private static string CombinePaths(string pathA, string pathB) - { - if (pathA == null) - { - throw new ArgumentNullException("pathA"); - } - - if (pathB == null) - { - throw new ArgumentNullException("pathB"); - } - - // The Path class does not suffer from the 248/260 character limitation - // that the File and Directory classes do. - return Path.Combine( - pathA.TrimEnd('\\'), - pathB.TrimStart('\\') - ); - } - - private static string ConvertToExtendedLengthPath(string path) - { - string extendedLengthPath = GetFullNormalizedPath(path); - - if (!String.IsNullOrWhiteSpace(extendedLengthPath)) - { - //no need to modify- it's already unicode - if (!extendedLengthPath.StartsWith(@"\\?", StringComparison.OrdinalIgnoreCase)) - { - // ex: \\server\share - if (extendedLengthPath.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase)) - { - // make it \\?\UNC\server\share - extendedLengthPath = String.Format( - CultureInfo.InvariantCulture, - @"\\?\UNC{0}", - extendedLengthPath.Substring(1) - ); - } - else //not unicode already, and not UNC - { - extendedLengthPath = String.Format( - CultureInfo.InvariantCulture, - @"\\?\{0}", - extendedLengthPath - ); - } - } - } - - return extendedLengthPath; - } - - private static IEnumerable EnumerateDirectoriesInPath(string path) - { - SafeFindHandle handle = null; - var findData = new FindData(); - var childDirectories = new List(); - - using (handle = NativeMethods.FindFirstFile(CombinePaths(ConvertToExtendedLengthPath(path), "*"), findData)) - { - if (!handle.IsInvalid) - { - bool searchComplete = false; - - do - { - // skip the dot directories - if (!findData.fileName.Equals(@".") && !findData.fileName.Equals(@"..")) - { - if ((findData.fileAttributes & (int)FileAttributes.Directory) != 0) - { - childDirectories.Add(RemoveExtendedLengthPathPrefix(CombinePaths(path, findData.fileName))); - } - } - - if (NativeMethods.FindNextFile(handle, findData)) - { - if (handle.IsInvalid) - { - throw new Win32Exception( - Marshal.GetLastWin32Error(), - String.Format( - CultureInfo.InvariantCulture, - "Enumerating subdirectories for path '{0}' failed.", - path - ) - ); - } - } - else - { - searchComplete = true; - } - - } while (!searchComplete); - } - } - - return childDirectories; - } - - private static IEnumerable EnumerateFilesInPath(string path, string matchPattern) - { - SafeFindHandle handle = null; - var findData = new FindData(); - var fullFilePaths = new List(); - - using (handle = NativeMethods.FindFirstFile(CombinePaths(ConvertToExtendedLengthPath(path), matchPattern), findData)) - { - int lastWin32Error = Marshal.GetLastWin32Error(); - - if (handle.IsInvalid) - { - if (lastWin32Error != ERROR_FILE_NOT_FOUND) - { - throw new Win32Exception( - lastWin32Error, - String.Format(CultureInfo.InvariantCulture, "Enumerating files for path '{0}' failed.", path) - ); - } - } - else - { - bool searchComplete = false; - - do - { - // skip the dot directories - if (!findData.fileName.Equals(@".") && !findData.fileName.Equals(@"..")) - { - if ((findData.fileAttributes & (int)FileAttributes.Directory) == 0) - { - fullFilePaths.Add(RemoveExtendedLengthPathPrefix(CombinePaths(path, findData.fileName))); - } - } - - if (NativeMethods.FindNextFile(handle, findData)) - { - lastWin32Error = Marshal.GetLastWin32Error(); - - if (handle.IsInvalid) - { - throw new Win32Exception( - lastWin32Error, - String.Format( - CultureInfo.InvariantCulture, - "Enumerating subdirectories for path '{0}' failed.", - path - ) - ); - } - } - else - { - searchComplete = true; - } - - } while (!searchComplete); - } - } - - return fullFilePaths; - } - - private static void EnumerateFilesInternal(List filePaths, string path, string matchPattern, bool recursiveSearch) - { - var fullFilePaths = EnumerateFilesInPath(path, matchPattern); - if (fullFilePaths.Any()) - { - lock (filePaths) - { - filePaths.AddRange(fullFilePaths); - } - } - - if (recursiveSearch) - { - var directorySearchPaths = EnumerateDirectoriesInPath(path); - if (directorySearchPaths.Any()) - { - Parallel.ForEach( - directorySearchPaths, - (searchPath) => - { - EnumerateFilesInternal(filePaths, searchPath, matchPattern, recursiveSearch); - } - ); - } - } - } - - public static void EnumerateDirectoriesInternal(List directoryPaths, string path, bool recursiveSearch) - { - var directorySearchPaths = EnumerateDirectoriesInPath(path); - if (directorySearchPaths.Any()) - { - lock (directoryPaths) - { - directoryPaths.AddRange(directorySearchPaths); - } - - if (recursiveSearch) - { - // This will not ensure that the directory paths are added to the list - // in alphabetical order but does provide performance 2 - 4 times better than the - // canonical Directory.GetDirectories() method. - Parallel.ForEach( - directorySearchPaths, - (searchPath) => - { - EnumerateDirectoriesInternal(directoryPaths, searchPath, recursiveSearch); - } - ); - } - } - } - - /// - /// Kernel32.dll native interop methods for use with utility file/path parsing - /// operations - /// - private static class NativeMethods - { - private const string Kernel32Dll = "kernel32.dll"; - - [DllImport(Kernel32Dll, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FindClose(IntPtr hFindFile); - - [SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "FindData.alternateFileName")] - [SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "FindData.fileName")] - [DllImport(Kernel32Dll, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] - public static extern SafeFindHandle FindFirstFile( - [MarshalAs(UnmanagedType.LPTStr)] - string fileName, - [In, Out] FindData findFileData - ); - [SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "FindData.alternateFileName")] - [SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments", MessageId = "FindData.fileName")] - [DllImport(Kernel32Dll, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool FindNextFile(SafeFindHandle hFindFile, [In, Out] FindData lpFindFileData); - - [DllImport(Kernel32Dll, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] - public static extern int GetFileAttributes(string lpFileName); - - [DllImport(Kernel32Dll, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] - public static extern uint GetFullPathName( - [MarshalAs(UnmanagedType.LPTStr)] - string lpFileName, - uint nBufferLength, - [Out] - StringBuilder lpBuffer, - StringBuilder lpFilePart - ); - } - - //for mapping to the WIN32_FIND_DATA native structure - [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1307:AccessibleFieldsMustBeginWithUpperCaseLetter", Justification = "Reviewed.")] - [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:FieldsMustBePrivate", Justification = "Reviewed.")] - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private sealed class FindData - { - // NOTE: - // Although it may seem correct to Marshal the string members of this class as UnmanagedType.LPWStr, they - // must explicitly remain UnmanagedType.ByValTStr with the size constraints noted. Otherwise we end up with - // COM Interop exceptions while trying to marshal the data across the PInvoke boundaries. We thus require the StyleCop - // suppressions on the NativeMethods.FindNextFile() method above. - public int fileAttributes; - public System.Runtime.InteropServices.ComTypes.FILETIME creationTime; - public System.Runtime.InteropServices.ComTypes.FILETIME lastAccessTime; - public System.Runtime.InteropServices.ComTypes.FILETIME lastWriteTime; - public int nFileSizeHigh; - public int nFileSizeLow; - public int dwReserved0; - public int dwReserved1; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string fileName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)] - public string alternateFileName; - } - - //A Win32 safe find handle in which a return value of -1 indicates it's invalid - private sealed class SafeFindHandle : Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid - { - public SafeFindHandle() - : base(true) - { - return; - } - - [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] - protected override bool ReleaseHandle() - { - return NativeMethods.FindClose(handle); - } - } - - [Flags] - private enum FlagsAndAttributes : uint - { - None = 0x00000000, - Readonly = 0x00000001, - Hidden = 0x00000002, - System = 0x00000004, - Directory = 0x00000010, - Archive = 0x00000020, - Device = 0x00000040, - Normal = 0x00000080, - Temporary = 0x00000100, - SparseFile = 0x00000200, - ReparsePoint = 0x00000400, - Compressed = 0x00000800, - Offline = 0x00001000, - NotContentIndexed = 0x00002000, - Encrypted = 0x00004000, - Write_Through = 0x80000000, - Overlapped = 0x40000000, - NoBuffering = 0x20000000, - RandomAccess = 0x10000000, - SequentialScan = 0x08000000, - DeleteOnClose = 0x04000000, - BackupSemantics = 0x02000000, - PosixSemantics = 0x01000000, - OpenReparsePoint = 0x00200000, - OpenNoRecall = 0x00100000, - FirstPipeInstance = 0x00080000, - - InvalidFileAttributes = 0xFFFFFFFF // Returned by GetFileAttributes on Non existant path - } - } -} diff --git a/src/Sdk/Common/Common/Utility/PartitioningResults.cs b/src/Sdk/Common/Common/Utility/PartitioningResults.cs deleted file mode 100644 index 4b0b82e73..000000000 --- a/src/Sdk/Common/Common/Utility/PartitioningResults.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.Common -{ - /// - /// Contains results from two-way variant of EnuemrableExtensions.Partition() - /// - /// The type of the elements in the contained lists. - public sealed class PartitionResults - { - public List MatchingPartition { get; } = new List(); - - public List NonMatchingPartition { get; } = new List(); - } - - /// - /// Contains results from multi-partitioning variant of EnuemrableExtensions.Partition() - /// - /// The type of the elements in the contained lists. - public sealed class MultiPartitionResults - { - public List> MatchingPartitions { get; } = new List>(); - - public List NonMatchingPartition { get; } = new List(); - } -} diff --git a/src/Sdk/Common/Common/Utility/PathUtility.cs b/src/Sdk/Common/Common/Utility/PathUtility.cs deleted file mode 100644 index 5b902ea01..000000000 --- a/src/Sdk/Common/Common/Utility/PathUtility.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - [EditorBrowsable(EditorBrowsableState.Never)] - internal static class PathUtility - { - /// - /// Replacement for Path.Combine. - /// For URL please use UrlUtility.CombineUrl - /// - /// The first half of the path. - /// The second half of the path. - /// The concatenated string with and leading slashes or - /// tildes removed from the second string. - public static String Combine(String path1, String path2) - { - if (String.IsNullOrEmpty(path1)) - { - return path2; - } - - if (String.IsNullOrEmpty(path2)) - { - return path1; - } - - Char separator = path1.Contains("/") ? '/' : '\\'; - - Char[] trimChars = new Char[] { '\\', '/' }; - - return path1.TrimEnd(trimChars) + separator.ToString() + path2.TrimStart(trimChars); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/PrimitiveExtensions.cs b/src/Sdk/Common/Common/Utility/PrimitiveExtensions.cs deleted file mode 100644 index 6c51e9cc4..000000000 --- a/src/Sdk/Common/Common/Utility/PrimitiveExtensions.cs +++ /dev/null @@ -1,89 +0,0 @@ -using GitHub.Services.Common.Internal; -using System; -using System.Text; - -namespace GitHub.Services.Common -{ - public static class PrimitiveExtensions - { - public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - private static readonly long maxSecondsSinceUnixEpoch = (long)DateTime.MaxValue.Subtract(UnixEpoch).TotalSeconds; - - //extension methods to convert to and from a Unix Epoch time to a DateTime - public static Int64 ToUnixEpochTime(this DateTime dateTime) - { - return Convert.ToInt64((dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds); - } - - public static DateTime FromUnixEpochTime(this Int64 unixTime) - { - if (unixTime >= maxSecondsSinceUnixEpoch) - { - return DateTime.MaxValue; - } - else - { - return UnixEpoch + TimeSpan.FromSeconds(unixTime); - } - } - - public static string ToBase64StringNoPaddingFromString(string utf8String) - { - return ToBase64StringNoPadding(Encoding.UTF8.GetBytes(utf8String)); - } - - public static string FromBase64StringNoPaddingToString(string base64String) - { - byte[] result = FromBase64StringNoPadding(base64String); - - if (result == null || result.Length == 0) - { - return null; - } - - return Encoding.UTF8.GetString(result, 0, result.Length); - } - - //These methods convert To and From base64 strings without padding - //for JWT scenarios - //code taken from the JWS spec here: - //http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-08#appendix-C - public static String ToBase64StringNoPadding(this byte[] bytes) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(bytes, "bytes"); - - string s = Convert.ToBase64String(bytes); // Regular base64 encoder - s = s.Split('=')[0]; // Remove any trailing '='s - s = s.Replace('+', '-'); // 62nd char of encoding - s = s.Replace('/', '_'); // 63rd char of encoding - return s; - } - - public static byte[] FromBase64StringNoPadding(this String base64String) - { - ArgumentUtility.CheckStringForNullOrEmpty(base64String, "base64String"); - - string s = base64String; - s = s.Replace('-', '+'); // 62nd char of encoding - s = s.Replace('_', '/'); // 63rd char of encoding - switch (s.Length % 4) // Pad with trailing '='s - { - case 0: break; // No pad chars in this case - case 2: s += "=="; break; // Two pad chars - case 3: s += "="; break; // One pad char - default: - throw new ArgumentException(CommonResources.IllegalBase64String(), "base64String"); - } - return Convert.FromBase64String(s); // Standard base64 decoder - } - - /// - /// Converts base64 represented value into hex string representation. - /// - public static String ConvertToHex(String base64String) - { - var bytes = FromBase64StringNoPadding(base64String); - return BitConverter.ToString(bytes).Replace("-", String.Empty); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/PropertyValidation.cs b/src/Sdk/Common/Common/Utility/PropertyValidation.cs deleted file mode 100644 index 6e682115a..000000000 --- a/src/Sdk/Common/Common/Utility/PropertyValidation.cs +++ /dev/null @@ -1,361 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; - -namespace GitHub.Services.Common.Internal -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public class PropertyValidation - { - public static void ValidateDictionary(IDictionary source) - { - ArgumentUtility.CheckForNull(source, "source"); - - foreach (var entry in source) - { - ValidatePropertyName(entry.Key); - ValidatePropertyValue(entry.Key, entry.Value); - } - } - - public static Boolean IsValidConvertibleType(Type type) - { - return type != null && (type.GetTypeInfo().IsEnum || - type == typeof(Object) || - type == typeof(Byte[]) || - type == typeof(Guid) || - type == typeof(Boolean) || - type == typeof(Char) || - type == typeof(SByte) || - type == typeof(Byte) || - type == typeof(Int16) || - type == typeof(UInt16) || - type == typeof(Int32) || - type == typeof(UInt32) || - type == typeof(Int64) || - type == typeof(UInt64) || - type == typeof(Single) || - type == typeof(Double) || - type == typeof(Decimal) || - type == typeof(DateTime) || - type == typeof(String) - ); - } - - /// - /// Used for deserialization checks. Makes sure that - /// the type string presented is in the inclusion list - /// of valid types for the property service - /// - /// - /// - public static Boolean IsValidTypeString(String type) - { - return s_validPropertyTypeStrings.ContainsKey(type); - } - - /// - /// Used for deserialization checks. Looks up the - /// type string presented in the inclusion list - /// of valid types for the property service and returns the Type object - /// - /// - /// Resulting type that maps to the type string - /// - public static Boolean TryGetValidType(String type, out Type result) - { - return s_validPropertyTypeStrings.TryGetValue(type, out result); - } - - /// - /// Make sure the property name conforms to the requirements for a - /// property name. - /// - /// - public static void ValidatePropertyName(String propertyName) - { - ValidatePropertyString(propertyName, c_maxPropertyNameLengthInChars, "propertyName"); - - // Key must not start or end in whitespace. ValidatePropertyString() checks for null and empty strings, - // which is why indexing on length without re-checking String.IsNullOrEmpty() is ok. - if (Char.IsWhiteSpace(propertyName[0]) || Char.IsWhiteSpace(propertyName[propertyName.Length - 1])) - { - throw new VssPropertyValidationException(propertyName, CommonResources.InvalidPropertyName(propertyName)); - } - } - - /// - /// Make sure the property value is within the supported range of values - /// for the type of the property specified. - /// - /// - /// - public static void ValidatePropertyValue(String propertyName, Object value) - { - // Keep this consistent with XmlPropertyWriter.Write. - if (null != value) - { - Type type = value.GetType(); - TypeCode typeCode = Type.GetTypeCode(type); - - if (type.IsEnum) - { - ValidateStringValue(propertyName, ((Enum)value).ToString("D")); - } - else if (typeCode == TypeCode.Object && value is byte[]) - { - ValidateByteArray(propertyName, (byte[])value); - } - else if (typeCode == TypeCode.Object && value is Guid) - { - //treat Guid like the other valid primitive types that - //don't have explicit columns, e.g. it gets stored as a string - ValidateStringValue(propertyName, ((Guid)value).ToString("N")); - } - else if (typeCode == TypeCode.Object) - { - throw new PropertyTypeNotSupportedException(propertyName, type); - } - else if (typeCode == TypeCode.DBNull) - { - throw new PropertyTypeNotSupportedException(propertyName, type); - } - else if (typeCode == TypeCode.Empty) - { - // should be impossible with null check above, but just in case. - throw new PropertyTypeNotSupportedException(propertyName, type); - } - else if (typeCode == TypeCode.Int32) - { - ValidateInt32(propertyName, (int)value); - } - else if (typeCode == TypeCode.Double) - { - ValidateDouble(propertyName, (double)value); - } - else if (typeCode == TypeCode.DateTime) - { - ValidateDateTime(propertyName, (DateTime)value); - } - else if (typeCode == TypeCode.String) - { - ValidateStringValue(propertyName, (String)value); - } - else - { - // Here are the remaining types. All are supported over in DbArtifactPropertyValueColumns. - // With a property definition they'll be strongly-typed when they're read back. - // Otherwise they read back as strings. - // Boolean - // Char - // SByte - // Byte - // Int16 - // UInt16 - // UInt32 - // Int64 - // UInt64 - // Single - // Decimal - ValidateStringValue(propertyName, value.ToString()); - } - } - } - - private static void ValidateStringValue(String propertyName, String propertyValue) - { - if (propertyValue.Length > c_maxStringValueLength) - { - throw new VssPropertyValidationException("value", CommonResources.InvalidPropertyValueSize(propertyName, typeof(String).FullName, c_maxStringValueLength)); - } - ArgumentUtility.CheckStringForInvalidCharacters(propertyValue, "value", true); - } - - private static void ValidateByteArray(String propertyName, Byte[] propertyValue) - { - if (propertyValue.Length > c_maxByteValueSize) - { - throw new VssPropertyValidationException("value", CommonResources.InvalidPropertyValueSize(propertyName, typeof(Byte[]).FullName, c_maxByteValueSize)); - } - } - - private static void ValidateDateTime(String propertyName, DateTime propertyValue) - { - // Let users get an out of range error for MinValue and MaxValue, not a DateTimeKind unspecified error. - if (propertyValue != DateTime.MinValue - && propertyValue != DateTime.MaxValue) - { - if (propertyValue.Kind == DateTimeKind.Unspecified) - { - throw new VssPropertyValidationException("value", CommonResources.DateTimeKindMustBeSpecified()); - } - - // Make sure the property value is in Universal time. - if (propertyValue.Kind != DateTimeKind.Utc) - { - propertyValue = propertyValue.ToUniversalTime(); - } - } - - CheckRange(propertyValue, s_minAllowedDateTime, s_maxAllowedDateTime, propertyName, "value"); - } - - private static void ValidateDouble(String propertyName, Double propertyValue) - { - if (Double.IsInfinity(propertyValue) || Double.IsNaN(propertyValue)) - { - throw new VssPropertyValidationException("value", CommonResources.DoubleValueOutOfRange(propertyName, propertyValue)); - } - - // SQL Server support: - 1.79E+308 to -2.23E-308, 0 and 2.23E-308 to 1.79E+308 - if (propertyValue < s_minNegative || - (propertyValue < 0 && propertyValue > s_maxNegative) || - propertyValue > s_maxPositive || - (propertyValue > 0 && propertyValue < s_minPositive)) - { - throw new VssPropertyValidationException("value", CommonResources.DoubleValueOutOfRange(propertyName, propertyValue)); - } - } - - private static void ValidateInt32(String propertyName, Int32 propertyValue) - { - // All values allowed. - } - - /// - /// Validation helper for validating all property strings. - /// - /// - /// - /// - private static void ValidatePropertyString(String propertyString, Int32 maxSize, String argumentName) - { - ArgumentUtility.CheckStringForNullOrEmpty(propertyString, argumentName); - if (propertyString.Length > maxSize) - { - throw new VssPropertyValidationException(argumentName, CommonResources.PropertyArgumentExceededMaximumSizeAllowed(argumentName, maxSize)); - } - ArgumentUtility.CheckStringForInvalidCharacters(propertyString, argumentName, true); - } - - public static void CheckPropertyLength(String propertyValue, Boolean allowNull, Int32 minLength, Int32 maxLength, String propertyName, Type containerType, String topLevelParamName) - { - Boolean valueIsInvalid = false; - - if (propertyValue == null) - { - if (!allowNull) - { - valueIsInvalid = true; - } - } - else if ((propertyValue.Length < minLength) || (propertyValue.Length > maxLength)) - { - valueIsInvalid = true; - } - - // throw exception if the value is invalid. - if (valueIsInvalid) - { - // If the propertyValue is null, just print it like an empty string. - if (propertyValue == null) - { - propertyValue = String.Empty; - } - - if (allowNull) - { - // paramName comes second for ArgumentException. - throw new ArgumentException(CommonResources.InvalidStringPropertyValueNullAllowed(propertyValue, propertyName, containerType.Name, minLength, maxLength), topLevelParamName); - } - else - { - throw new ArgumentException(CommonResources.InvalidStringPropertyValueNullForbidden(propertyValue, propertyName, containerType.Name, minLength, maxLength), topLevelParamName); - } - } - } - - /// - /// Verify that a propery is within the bounds of the specified range. - /// - /// The property value - /// The minimum value allowed - /// The maximum value allowed - /// The name of the property - /// The container of the property - /// The top level parameter name - public static void CheckRange(T propertyValue, T minValue, T maxValue, String propertyName, Type containerType, String topLevelParamName) - where T : IComparable - { - if (propertyValue.CompareTo(minValue) < 0 || propertyValue.CompareTo(maxValue) > 0) - { - // paramName comes first for ArgumentOutOfRangeException. - throw new ArgumentOutOfRangeException(topLevelParamName, CommonResources.ValueTypeOutOfRange(propertyValue, propertyName, containerType.Name, minValue, maxValue)); - } - } - - private static void CheckRange(T propertyValue, T minValue, T maxValue, String propertyName, String topLevelParamName) - where T : IComparable - { - if (propertyValue.CompareTo(minValue) < 0 || propertyValue.CompareTo(maxValue) > 0) - { - // paramName comes first for ArgumentOutOfRangeException. - throw new ArgumentOutOfRangeException(topLevelParamName, CommonResources.VssPropertyValueOutOfRange(propertyName, propertyValue, minValue, maxValue)); - } - } - - /// - /// Make sure the property filter conforms to the requirements for a - /// property filter. - /// - /// - public static void ValidatePropertyFilter(String propertyNameFilter) - { - PropertyValidation.ValidatePropertyString(propertyNameFilter, c_maxPropertyNameLengthInChars, "propertyNameFilter"); - } - - // Limits on the sizes of property values - private const Int32 c_maxPropertyNameLengthInChars = 400; - private const Int32 c_maxByteValueSize = 8 * 1024 * 1024; - private const Int32 c_maxStringValueLength = 4 * 1024 * 1024; - - // Minium date time allowed for a property value. - private static readonly DateTime s_minAllowedDateTime = new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - // Maximum date time allowed for a property value. - // We can't preserve DateTime.MaxValue faithfully because SQL's cut-off is 3 milliseconds lower. Also to handle UTC to Local shifts, we give ourselves a buffer of one day. - private static readonly DateTime s_maxAllowedDateTime = DateTime.SpecifyKind(DateTime.MaxValue, DateTimeKind.Utc).AddDays(-1); - - private static Double s_minNegative = Double.Parse("-1.79E+308", CultureInfo.InvariantCulture); - private static Double s_maxNegative = Double.Parse("-2.23E-308", CultureInfo.InvariantCulture); - private static Double s_minPositive = Double.Parse("2.23E-308", CultureInfo.InvariantCulture); - private static Double s_maxPositive = Double.Parse("1.79E+308", CultureInfo.InvariantCulture); - - private static readonly Dictionary s_validPropertyTypeStrings = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - //primitive types: - //(NO DBNull or Empty) - { "System.Boolean", typeof(Boolean) }, - { "System.Byte", typeof(Byte) }, - { "System.Char", typeof(Char) }, - { "System.DateTime", typeof(DateTime) }, - { "System.Decimal", typeof(Decimal) }, - { "System.Double", typeof(Double) }, - { "System.Int16", typeof(Int16) }, - { "System.Int32", typeof(Int32) }, - { "System.Int64", typeof(Int64) }, - { "System.SByte", typeof(SByte) }, - { "System.Single", typeof(Single) }, - { "System.String", typeof(String) }, - { "System.UInt16", typeof(UInt16) }, - { "System.UInt32", typeof(UInt32) }, - { "System.UInt64", typeof(UInt64) }, - - //other valid types - { "System.Byte[]", typeof(Byte[]) }, - { "System.Guid", typeof(Guid) } - }; - } -} diff --git a/src/Sdk/Common/Common/Utility/SecretUtility.cs b/src/Sdk/Common/Common/Utility/SecretUtility.cs deleted file mode 100644 index ec804836d..000000000 --- a/src/Sdk/Common/Common/Utility/SecretUtility.cs +++ /dev/null @@ -1,253 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - /// - /// Utility for masking common secret patterns - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class SecretUtility - { - /// - /// The string to use to replace secrets when throwing exceptions, logging - /// or otherwise risking exposure - /// - internal const string PasswordMask = "******"; - - /// - /// The string used to mask newer secrets - /// - internal const string SecretMask = ""; - - //We use a different mask per token, to help track down suspicious mask sequences in error - // strings that shouldn't obviously be masked - // Internal for testing, please don't reuse - internal const string PasswordRemovedMask = "**password-removed**"; - internal const string PwdRemovedMask = "**pwd-removed**"; - internal const string PasswordSpaceRemovedMask = "**password-space-removed**"; - internal const string PwdSpaceRemovedMask = "**pwd-space-removed**"; - internal const string AccountKeyRemovedMask = "**account-key-removed**"; - - - /// - /// Whether this string contains an unmasked secret - /// - /// The message to check - /// True if a secret this class supports was found - /// This implementation is as least as expensive as a ScrubSecrets call - public static bool ContainsUnmaskedSecret(string message) - { - return !String.Equals(message, ScrubSecrets(message, false), StringComparison.Ordinal); - } - - - /// - /// Whether this string contains an unmasked secret - /// - /// The message to check - /// True if a secret was found and only jwts were found - /// True if a message this class supports was found - /// This method is a temporary workaround and should be removed in M136 - /// This implementation is as least as expensive as a ScrubSecrets call - public static bool ContainsUnmaskedSecret(string message, out bool onlyJwtsFound) - { - if (string.IsNullOrEmpty(message)) - { - onlyJwtsFound = false; - return false; - } - - string scrubbedMessage = ScrubJwts(message, assertOnDetection: false); - bool jwtsFound = !String.Equals(message, scrubbedMessage, StringComparison.Ordinal); - scrubbedMessage = ScrubTraditionalSecrets(message, assertOnDetection: false); - bool secretsFound = !String.Equals(message, scrubbedMessage, StringComparison.Ordinal); - onlyJwtsFound = !secretsFound && jwtsFound; - return secretsFound || jwtsFound; - } - - /// - /// Scrub a message for any secrets(passwords, tokens) in known formats - /// This method is called to scrub exception messages and traces to prevent any secrets - /// from being leaked. - /// - /// The message to verify for secret data. - /// When true, if a message contains a - /// secret in a known format the method will debug assert. Default = true. - /// The message with any detected secrets masked - /// This only does best effort pattern matching for a set of known patterns - public static string ScrubSecrets(string message, bool assertOnDetection = true) - { - if (string.IsNullOrEmpty(message)) - { - return message; - } - - message = ScrubTraditionalSecrets(message, assertOnDetection); - message = ScrubJwts(message, assertOnDetection); - return message; - } - - private static string ScrubTraditionalSecrets(string message, bool assertOnDetection) - { - message = ScrubSecret(message, c_passwordToken, PasswordRemovedMask, assertOnDetection); - message = ScrubSecret(message, c_pwdToken, PwdRemovedMask, assertOnDetection); - message = ScrubSecret(message, c_passwordTokenSpaced, PasswordSpaceRemovedMask, assertOnDetection); - message = ScrubSecret(message, c_pwdTokenSpaced, PwdSpaceRemovedMask, assertOnDetection); - message = ScrubSecret(message, c_accountKeyToken, AccountKeyRemovedMask, assertOnDetection); - - message = ScrubSecret(message, c_authBearerToken, SecretMask, assertOnDetection); - return message; - } - - private static string ScrubJwts(string message, bool assertOnDetection) - { - //JWTs are sensitive and we need to scrub them, so this is a best effort attempt to - // scrub them based on typical patterns we see - message = ScrubSecret(message, c_jwtTypToken, SecretMask, assertOnDetection, - maskToken: true); - message = ScrubSecret(message, c_jwtAlgToken, SecretMask, assertOnDetection, - maskToken: true); - message = ScrubSecret(message, c_jwtX5tToken, SecretMask, assertOnDetection, - maskToken: true); - message = ScrubSecret(message, c_jwtKidToken, SecretMask, assertOnDetection, - maskToken: true); - return message; - } - - private static string ScrubSecret(string message, string token, string mask, bool assertOnDetection, bool maskToken=false) - { - int startIndex = -1; - - do - { - startIndex = message.IndexOf(token, (startIndex < 0) ? 0 : startIndex, StringComparison.OrdinalIgnoreCase); - if (startIndex < 0) - { - // Common case, there is not a password. - break; - } - - //Explicitly check for original password mask so code that uses the orignal doesn't assert - if (!maskToken && ( - message.IndexOf(token + mask, StringComparison.OrdinalIgnoreCase) == startIndex - || (message.IndexOf(token + PasswordMask, StringComparison.OrdinalIgnoreCase) == startIndex))) - { - // The password is already masked, move past this string. - startIndex += token.Length + mask.Length; - continue; - } - - // At this point we detected a password that is not masked, remove it! - try - { - if (!maskToken) - { - startIndex += token.Length; - } - // Find the end of the password. - int endIndex = message.Length - 1; - - if (message[startIndex] == '"' || message[startIndex] == '\'') - { - // The password is wrapped in quotes. The end of the string will be the next unpaired quote. - // Unless the message itself wrapped the connection string in quotes, in which case we may mask out the rest of the message. Better to be safe than leak the connection string. - // Intentionally going to "i < message.Length - 1". If the quote isn't the second to last character, it is the last character, and we delete to the end of the string anyway. - for (int i = startIndex + 1; i < message.Length - 1; i++) - { - if (message[startIndex] == message[i]) - { - if (message[startIndex] == message[i + 1]) - { - // we found a pair of quotes. Skip over the pair and continue. - i++; - continue; - } - else - { - // this is a single quote, and the end of the password. - endIndex = i; - break; - } - } - } - } - else - { - // The password is not wrapped in quotes. - // The end is any whitespace, semi-colon, single, or double quote character. - for (int i = startIndex + 1; i < message.Length; i++) - { - if (Char.IsWhiteSpace(message[i]) || ((IList)s_validPasswordEnding).Contains(message[i])) - { - endIndex = i - 1; - break; - } - } - } - - message = message.Substring(0, startIndex) + mask + message.Substring(endIndex + 1); - - // Bug 94478: We need to scrub the message before Assert, otherwise we will fall into - // a recursive assert where the TeamFoundationServerException contains same message - if (assertOnDetection) - { - Debug.Assert(false, String.Format(CultureInfo.InvariantCulture, "Message contains an unmasked secret. Message: {0}", message)); - } - - // Trace raw that we have scrubbed a message. - //FUTURE: We need a work item to add Tracing to the VSS Client assembly. - //TraceLevel traceLevel = assertOnDetection ? TraceLevel.Error : TraceLevel.Info; - //TeamFoundationTracingService.TraceRaw(99230, traceLevel, s_area, s_layer, "An unmasked password was detected in a message. MESSAGE: {0}. STACK TRACE: {1}", message, Environment.StackTrace); - } - catch (Exception /*exception*/) - { - // With an exception here the message may still contain an unmasked password. - // We also do not want to interupt the current thread with this exception, because it may be constucting a message - // for a different exception. Trace this exception and continue on using a generic exception message. - //TeamFoundationTracingService.TraceExceptionRaw(99231, s_area, s_layer, exception); - } - finally - { - // Iterate to the next password (if it exists) - startIndex += mask.Length; - } - } while (startIndex < message.Length); - - return message; - } - - private const string c_passwordToken = "Password="; - private const string c_passwordTokenSpaced = "-Password "; - private const string c_pwdToken = "Pwd="; - private const string c_pwdTokenSpaced = "-Pwd "; - private const string c_accountKeyToken = "AccountKey="; - private const string c_authBearerToken = "Bearer "; - /// - /// {"typ":" // eyJ0eXAiOi - /// - private const string c_jwtTypToken = "eyJ0eXAiOi"; - /// - /// {"alg":" // eyJhbGciOi - /// - private const string c_jwtAlgToken = "eyJhbGciOi"; - /// - /// {"x5t":" // eyJ4NXQiOi - /// - private const string c_jwtX5tToken = "eyJ4NXQiOi"; - /// - /// {"kid":" // eyJraWQiOi - /// - private const string c_jwtKidToken = "eyJraWQiOi"; - - - - private static readonly char[] s_validPasswordEnding = new char[] { ';', '\'', '"' }; - } -} diff --git a/src/Sdk/Common/Common/Utility/SecureCompare.cs b/src/Sdk/Common/Common/Utility/SecureCompare.cs deleted file mode 100644 index 90e896bf6..000000000 --- a/src/Sdk/Common/Common/Utility/SecureCompare.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.ComponentModel; - -namespace GitHub.Services.Common -{ - public static class SecureCompare - { - /// - /// Compare two byte arrays for byte-by-byte equality. - /// If both arrays are the same length, the running time of this routine will not vary with the number of equal bytes between the two. - /// - /// A byte array (non-null) - /// A byte array (non-null) - /// - /// Checking secret values using built-in equality operators is insecure. - /// Operations like `==` on strings will stop the comparison when the first unmatched character is encountered. - /// When checking secret values from an untrusted source that we use for authentication, we must be careful - /// not to stop the comparison early for incorrect values. - /// If we do, an attacker can send a large volume of requests and use statistical methods to infer the secret value byte-by-byte. - /// - /// This method is intended to be used with arrays of the same length -- for example, two hashes from the same SHA algorithm. - /// Comparing strings of unequal length can leak length information to an attacker. - /// - public static bool TimeInvariantEquals(byte[] lhs, byte[] rhs) - { - if (lhs.Length != rhs.Length) - { - return false; - } - - // Must use bitwise operations - // Conditional branching or short-circuiting Boolean operators would change the running time depending on the result - int result = 0; - for (int i = 0; i < lhs.Length; i++) - { - result |= lhs[i] ^ rhs[i]; - } - - return result == 0; - } - - // Hide the `Equals` method inherited from `object` - [EditorBrowsable(EditorBrowsableState.Never)] - public new static bool Equals(object lhs, object rhs) - { - throw new NotImplementedException($"This is not the secure equals method! Use `{nameof(SecureCompare.TimeInvariantEquals)}` instead."); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/StreamParser.cs b/src/Sdk/Common/Common/Utility/StreamParser.cs deleted file mode 100644 index f67b0f88e..000000000 --- a/src/Sdk/Common/Common/Utility/StreamParser.cs +++ /dev/null @@ -1,188 +0,0 @@ -using System; -using System.ComponentModel; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace GitHub.Services.Common -{ - /// - /// Simple helper class used to break up a stream into smaller streams - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public class StreamParser - { - public StreamParser(Stream fileStream, int chunkSize) - { - m_stream = fileStream; - m_chunkSize = chunkSize; - } - - /// - /// Returns total length of file. - /// - public long Length - { - get - { - return m_stream.Length; - } - } - - /// - /// returns the next substream - /// - /// - public SubStream GetNextStream() - { - return new SubStream(m_stream, m_chunkSize); - } - - Stream m_stream; - int m_chunkSize; - } - - /// - /// Streams a subsection of a larger stream - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public class SubStream : Stream - { - public SubStream(Stream stream, int maxStreamSize) - { - m_startingPosition = stream.Position; - long remainingStream = stream.Length - m_startingPosition; - m_length = Math.Min(maxStreamSize, remainingStream); - m_stream = stream; - } - - public override bool CanRead - { - get - { - return m_stream.CanRead && m_stream.Position <= this.EndingPostionOnOuterStream; - } - } - - public override bool CanSeek - { - get { return m_stream.CanSeek; } - } - - public override bool CanWrite - { - get { return false; } - } - - public override void Flush() - { - throw new NotImplementedException(); - } - - public override long Length - { - get - { - return m_length; - } - } - - public override long Position - { - get - { - return m_stream.Position - m_startingPosition; - } - set - { - if (value >= m_length) - { - throw new EndOfStreamException(); - } - - m_stream.Position = m_startingPosition + value; - } - } - - /// - /// Postion in larger stream where this substream starts - /// - public long StartingPostionOnOuterStream - { - get - { - return m_startingPosition; - } - } - - /// - /// Postion in larger stream where this substream ends - /// - public long EndingPostionOnOuterStream - { - get - { - return m_startingPosition + m_length - 1; - } - } - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - // check that the read is only in our substream - count = EnsureLessThanOrEqualToRemainingBytes(count); - - return m_stream.ReadAsync(buffer, offset, count, cancellationToken); - } - - public override int Read(byte[] buffer, int offset, int count) - { - // check that the read is only in our substream - count = EnsureLessThanOrEqualToRemainingBytes(count); - - return m_stream.Read(buffer, offset, count); - } - - public override long Seek(long offset, SeekOrigin origin) - { - if (origin == SeekOrigin.Begin && 0 <= offset && offset < m_length) - { - return m_stream.Seek(offset + m_startingPosition, origin); - } - else if (origin == SeekOrigin.End && 0 >= offset && offset > -m_length) - { - return m_stream.Seek(offset - ((m_stream.Length-1) - this.EndingPostionOnOuterStream), origin); - } - else if (origin == SeekOrigin.Current && (offset + m_stream.Position) >= this.StartingPostionOnOuterStream && (offset + m_stream.Position) < this.EndingPostionOnOuterStream) - { - return m_stream.Seek(offset, origin); - } - - throw new ArgumentException(); - } - - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - - private int EnsureLessThanOrEqualToRemainingBytes(int numBytes) - { - long remainingBytesInStream = m_length - this.Position; - if (numBytes > remainingBytesInStream) - { - numBytes = Convert.ToInt32(remainingBytesInStream); - } - return numBytes; - } - - private long m_length; - private long m_startingPosition; - private Stream m_stream; - } - -} diff --git a/src/Sdk/Common/Common/Utility/TypeExtensionMethods.cs b/src/Sdk/Common/Common/Utility/TypeExtensionMethods.cs deleted file mode 100644 index f1c68fbdf..000000000 --- a/src/Sdk/Common/Common/Utility/TypeExtensionMethods.cs +++ /dev/null @@ -1,294 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Reflection; - -namespace GitHub.Services.Common -{ - public static class TypeExtensionMethods - { - /// - /// Determins if a value is assignable to the requested type. It goes - /// the extra step beyond IsAssignableFrom in that it also checks for - /// IConvertible and attempts to convert the value. - /// - /// - /// - /// - public static bool IsAssignableOrConvertibleFrom(this Type type, object value) - { - if (value == null) - { - return false; - } - - if (!type.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo())) - { - if (value is IConvertible) - { - // Try and convert to the requested type, if successful - // assign value to the result so we don't have to do again. - try - { - ConvertUtility.ChangeType(value, type, CultureInfo.CurrentCulture); - return true; - } - catch (FormatException) - { - } - catch (InvalidCastException) - { - } - catch (OverflowException) - { - } - } - return false; - } - - return true; - } - - /// - /// Determines if the type is of the type t. - /// - /// The type to check. - /// The type to compare to. - /// True if of the same type, otherwise false. - public static bool IsOfType(this Type type, Type t) - { - if (t.GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) - { - return true; - } - else if (type.GetTypeInfo().IsGenericType && - type.GetGenericTypeDefinition() == t) - { - //generic type - return true; - } - else if (type.GetTypeInfo().ImplementedInterfaces.Any( - i => i.GetTypeInfo().IsGenericType && - i.GetGenericTypeDefinition() == t)) - { - //implements generic type - return true; - } - - return false; - } - - - /// - /// Determines if the type is a Dictionary. - /// - /// The type to check. - /// True if a dictionary, otherwise false. - public static bool IsDictionary(this Type type) - { - if (typeof(IDictionary).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) - { - //non-generic dictionary - return true; - } - else if (type.GetTypeInfo().IsGenericType && - type.GetGenericTypeDefinition() == typeof(IDictionary<,>)) - { - //generic dictionary interface - return true; - } - else if (type.GetTypeInfo().ImplementedInterfaces.Any( - i => i.GetTypeInfo().IsGenericType && - i.GetGenericTypeDefinition() == typeof(IDictionary<,>))) - { - //implements generic dictionary - return true; - } - - return false; - } - - /// - /// Determines if the type is a List. - /// - /// The type to check. - /// True if a list, otherwise false. - public static bool IsList(this Type type) - { - if (typeof(IList).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo())) - { - //non-generic list - return true; - } - else if (type.GetTypeInfo().IsGenericType && - type.GetGenericTypeDefinition() == typeof(IList<>)) - { - //generic list interface - return true; - } - else if (type.GetTypeInfo().ImplementedInterfaces.Any( - i => i.GetTypeInfo().IsGenericType && - i.GetGenericTypeDefinition() == typeof(IList<>))) - { - //implements generic list - return true; - } - - return false; - } - - /// - /// Get's the type of the field/property specified. - /// - /// The type to get the field/property from. - /// The name of the field/property. - /// The type of the field/property or null if no match found. - public static Type GetMemberType(this Type type, string name) - { - TypeInfo typeInfo = type.GetTypeInfo(); - PropertyInfo propertyInfo = GetPublicInstancePropertyInfo(type, name); - if (propertyInfo != null) - { - return propertyInfo.PropertyType; - } - else - { - FieldInfo fieldInfo = GetPublicInstanceFieldInfo(type, name); - if (fieldInfo != null) - { - return fieldInfo.FieldType; - } - } - return null; - } - - /// - /// Get's the value of the field/property specified. - /// - /// The type to get the field/property from. - /// The name of the field/property. - /// The object to get the value from. - /// The value of the field/property or null if no match found. - public static object GetMemberValue(this Type type, string name, object obj) - { - PropertyInfo propertyInfo = GetPublicInstancePropertyInfo(type, name); - if (propertyInfo != null) - { - return propertyInfo.GetValue(obj); - } - else - { - FieldInfo fieldInfo = GetPublicInstanceFieldInfo(type, name); - if (fieldInfo != null) - { - return fieldInfo.GetValue(obj); - } - } - return null; - } - - /// - /// Set's the value of the field/property specified. - /// - /// The type to get the field/property from. - /// The name of the field/property. - /// The object to set the value to. - /// The value to set. - public static void SetMemberValue(this Type type, string name, object obj, object value) - { - PropertyInfo propertyInfo = GetPublicInstancePropertyInfo(type, name); - if (propertyInfo != null) - { - if (!propertyInfo.SetMethod.IsPublic) - { - // this is here to match original behaviour before we switched to PCL version of code. - throw new ArgumentException("Property set method not public."); - } - propertyInfo.SetValue(obj, value); - } - else - { - FieldInfo fieldInfo = GetPublicInstanceFieldInfo(type, name); - if (fieldInfo != null) - { - fieldInfo.SetValue(obj, value); - } - } - } - -#if NETSTANDARD - /// - /// Portable compliant way to get a constructor with specified arguments. This will return a constructor that is public or private as long as the arguments match. NULL will be returned if there is no match. - /// Note that it will pick the first one it finds that matches, which is not necesarily the best match. - /// - /// The Type that has the constructor - /// The type of the arguments for the constructor. - /// - public static ConstructorInfo GetFirstMatchingConstructor(this Type type, params Type[] parameterTypes) - { - return type.GetTypeInfo().DeclaredConstructors.GetFirstMatchingConstructor(parameterTypes); - } - - /// - /// Portable compliant way to get a constructor with specified arguments from a prefiltered list. This will return a constructor that is public or private as long as the arguments match. NULL will be returned if there is no match. - /// Note that it will pick the first one it finds that matches, which is not necesarily the best match. - /// - /// Prefiltered list of constructors - /// The type of the arguments for the constructor. - /// - public static ConstructorInfo GetFirstMatchingConstructor(this IEnumerable constructors, params Type[] parameterTypes) - { - foreach (ConstructorInfo constructorInfo in constructors) - { - ParameterInfo[] parameters = constructorInfo.GetParameters(); - if (parameters.Length == parameterTypes.Length) - { - int i; - bool matches = true; - for (i = 0; i < parameterTypes.Length; i++) - { - if (parameters[i].ParameterType != parameterTypes[i] && !parameters[i].ParameterType.GetTypeInfo().IsAssignableFrom(parameterTypes[i].GetTypeInfo())) - { - matches = false; - break; - } - } - if (matches) - { - return constructorInfo; - } - } - } - return null; - } -#endif - - private static PropertyInfo GetPublicInstancePropertyInfo(Type type, string name) - { - Type typeToCheck = type; - PropertyInfo propertyInfo = null; - while (propertyInfo == null && typeToCheck != null) - { - TypeInfo typeInfo = typeToCheck.GetTypeInfo(); - propertyInfo = typeInfo.DeclaredProperties.FirstOrDefault(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase) && p.GetMethod.Attributes.HasFlag(MethodAttributes.Public) && !p.GetMethod.Attributes.HasFlag(MethodAttributes.Static)); - typeToCheck = typeInfo.BaseType; - } - return propertyInfo; - } - - private static FieldInfo GetPublicInstanceFieldInfo(Type type, string name) - { - Type typeToCheck = type; - FieldInfo fieldInfo = null; - while (fieldInfo == null && typeToCheck != null) - { - TypeInfo typeInfo = typeToCheck.GetTypeInfo(); - fieldInfo = typeInfo.DeclaredFields.FirstOrDefault(f => f.Name.Equals(name, StringComparison.OrdinalIgnoreCase) && f.IsPublic && !f.IsStatic); - typeToCheck = typeInfo.BaseType; - } - return fieldInfo; - } - } -} diff --git a/src/Sdk/Common/Common/Utility/UriExtensions.cs b/src/Sdk/Common/Common/Utility/UriExtensions.cs deleted file mode 100644 index e25d8f0c8..000000000 --- a/src/Sdk/Common/Common/Utility/UriExtensions.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; -using System.Text; - -namespace GitHub.Services.Common -{ - public static class UriExtensions - { - public static Uri AppendQuery(this Uri uri, String name, String value) - { - ArgumentUtility.CheckForNull(uri, "uri"); - ArgumentUtility.CheckStringForNullOrEmpty(name, "name"); - ArgumentUtility.CheckStringForNullOrEmpty(value, "value"); - - StringBuilder stringBuilder = new StringBuilder(uri.Query.TrimStart('?')); - - AppendSingleQueryValue(stringBuilder, name, value); - - UriBuilder uriBuilder = new UriBuilder(uri); - - uriBuilder.Query = stringBuilder.ToString(); - - return uriBuilder.Uri; - } - - public static Uri AppendQuery(this Uri uri, IEnumerable> queryValues) - { - ArgumentUtility.CheckForNull(uri, "uri"); - ArgumentUtility.CheckForNull(queryValues, "queryValues"); - - StringBuilder stringBuilder = new StringBuilder(uri.Query.TrimStart('?')); - - foreach (KeyValuePair kvp in queryValues) - { - AppendSingleQueryValue(stringBuilder, kvp.Key, kvp.Value); - } - - UriBuilder uriBuilder = new UriBuilder(uri); - uriBuilder.Query = stringBuilder.ToString(); - return uriBuilder.Uri; - } - - public static Uri AppendQuery(this Uri uri, NameValueCollection queryValues) - { - ArgumentUtility.CheckForNull(uri, "uri"); - ArgumentUtility.CheckForNull(queryValues, "queryValues"); - - StringBuilder stringBuilder = new StringBuilder(uri.Query.TrimStart('?')); - - foreach (String name in queryValues) - { - AppendSingleQueryValue(stringBuilder, name, queryValues[name]); - } - - UriBuilder uriBuilder = new UriBuilder(uri); - - uriBuilder.Query = stringBuilder.ToString(); - - return uriBuilder.Uri; - } - - /// - /// Performs an Add similar to the NameValuCollection 'Add' method where the value gets added as an item in a comma delimited list if the key is already present. - /// - /// - /// - /// - /// - /// - public static void Add(this IList> collection, String key, T value, Func convert = null) - { - collection.AddMultiple(key, new List { value }, convert); - } - - public static void AddMultiple(this IList> collection, String key, IEnumerable values, Func convert) - { - ArgumentUtility.CheckForNull(collection, "collection"); - ArgumentUtility.CheckStringForNullOrEmpty(key, "name"); - - if (convert == null) convert = (val) => val.ToString(); - - if (values != null && values.Any()) - { - StringBuilder newValue = new StringBuilder(); - KeyValuePair matchingKvp = collection.FirstOrDefault(kvp => kvp.Key.Equals(key)); - if (matchingKvp.Key == key) - { - collection.Remove(matchingKvp); - newValue.Append(matchingKvp.Value); - } - - foreach (var value in values) - { - if (newValue.Length > 0) - { - newValue.Append(","); - } - newValue.Append(convert(value)); - } - - collection.Add(new KeyValuePair(key, newValue.ToString())); - } - } - - public static void Add(this IList> collection, String key, String value) - { - collection.AddMultiple(key, new[] { value }); - } - - public static void AddMultiple(this IList> collection, String key, IEnumerable values) - { - collection.AddMultiple(key, values, (val) => val); - } - - public static void AddMultiple(this NameValueCollection collection, String name, IEnumerable values, Func convert) - { - ArgumentUtility.CheckForNull(collection, "collection"); - ArgumentUtility.CheckStringForNullOrEmpty(name, "name"); - - if (convert == null) convert = (val) => val.ToString(); - - if (values != null) - { - foreach (var value in values) - { - collection.Add(name, convert(value)); - } - } - } - - public static void AddMultiple(this NameValueCollection collection, String name, IEnumerable values) - { - ArgumentUtility.CheckForNull(collection, "collection"); - collection.AddMultiple(name, values, (val) => val); - } - - /// - /// Get the absolute path of the given Uri, if it is absolute. - /// - /// If the URI is absolute, the string form of it is returned; otherwise, - /// the URI's string representation. - public static string AbsoluteUri(this Uri uri) - { - return uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.ToString(); - } - - private static void AppendSingleQueryValue(StringBuilder builder, String name, String value) - { - if (builder.Length > 0) - { - builder.Append("&"); - } - builder.Append(Uri.EscapeDataString(name)); - builder.Append("="); - builder.Append(Uri.EscapeDataString(value)); - } - } -} diff --git a/src/Sdk/Common/Common/Utility/UriUtility.cs b/src/Sdk/Common/Common/Utility/UriUtility.cs deleted file mode 100644 index 875fdc065..000000000 --- a/src/Sdk/Common/Common/Utility/UriUtility.cs +++ /dev/null @@ -1,2204 +0,0 @@ -// This #define is used by the HtmlEncode and HtmlDecode logic below. The original comment -// from ndp/fx/src/net/system/net/webutility.cs follows. -#define ENTITY_ENCODE_HIGH_ASCII_CHARS - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.IO; -using System.Net; -using System.Runtime.Serialization; -using System.Text; -using System.Text.RegularExpressions; -using System.Net.Sockets; - -namespace GitHub.Services.Common.Internal -{ - /// - /// Utility class for general Uri actions. See LinkingUtilities for artifact uri specific methods. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static class UriUtility - { - private const String c_uriSchemeHttp = "http"; - private const String c_uriSchemeHttps = "https"; - - /// - /// List of URI schemes considered to be UNSAFE. When a URL with this is scheme is navigated to, we will - /// inform the user that it is unsafe and prevent navigation. - /// - /// - /// Note: the data scheme is not in this list nor is it in the safe list either, this is by design. - /// See http://msdn.microsoft.com/en-us/library/ie/cc848897(v=vs.85).aspx for a reference of the data protocol. - /// See http://www.gnucitizen.org/blog/bugs-in-the-browser-firefoxs-data-url-scheme-vulnerability/ for attacks on the data protocol. - /// - private static readonly ICollection UnsafeUriSchemeList = new HashSet(new string[] { - "javascript", "vbscript" - }, VssStringComparer.UriScheme); - - /// - /// List of URI schemes considered to be SAFE. When a URL with this scheme is navigated to (e.g. in WIT client or - /// web access), we will not warn the user about it as they are trusted. For any other URL not in this list, we will - /// warn the user about it! - /// - /// - /// "x-mvwit" is here as it is used and saved to work item history rich HTML changes. It is used to reference other work - /// items in the list. If we remove it from this list, it will not be a navigatable link in e.g. Web Access. - /// - private static readonly ICollection SafeUriSchemeList = new HashSet(new string[] { - "http", "https", "ftp", "gopher", "mailto", "news", "telnet", "wais", - "vstfs", "tfs", "alm", "mtm", "mtms", "mfbclient", "mfbclients", - "x-mvwit" - }, VssStringComparer.UriScheme); - - private const char PathSeparatorChar = '/'; - private const string PathSeparator = "/"; - - private class _AbsoluteUriStringComparer : IEqualityComparer - { - public bool Equals(Uri x, Uri y) - { - string xAbsoluteUri = (x != null) ? GetInvariantAbsoluteUri(x) : null; - string yAbsoluteUri = (y != null) ? GetInvariantAbsoluteUri(y) : null; - - return VssStringComparer.Url.Equals(xAbsoluteUri, yAbsoluteUri); - } - - public int GetHashCode(Uri obj) - { - return GetInvariantAbsoluteUri(obj).GetHashCode(); - } - } - - private class _UrlPathIgnoreSeparatorsComparer : IEqualityComparer - { - public bool Equals(string x, string y) - { - return VssStringComparer.UrlPath.Equals(TrimPathSeparators(x), TrimPathSeparators(y)); - } - - public int GetHashCode(string obj) - { - return VssStringComparer.UrlPath.GetHashCode(TrimPathSeparators(obj)); - } - } - - /// - /// string comparer for uri, is not case sensitive and does not care about trailing '/' - /// - public static IEqualityComparer AbsoluteUriStringComparer = new _AbsoluteUriStringComparer(); - - /// - /// Compares URL Paths ignoring any starting or ending path separators. - /// - public static IEqualityComparer UrlPathIgnoreSeparatorsComparer = new _UrlPathIgnoreSeparatorsComparer(); - - /// - /// A URL is considered unsafe IF: - /// * It is not an absolute URI (e.g. a relative file.html) - /// * It's scheme is part of the unsafe scheme list. - /// * It is a file:// URI pointing to a local file, e.g. file://C:\Windows\System32\notepad.exe - /// - public static bool IsUriUnsafe(Uri uri) - { - ArgumentUtility.CheckForNull(uri, "uri"); - - return !uri.IsAbsoluteUri || UnsafeUriSchemeList.Contains(uri.Scheme) - || IsUriLocalFile(uri); // Also exclude all file URLs pointing to local files - } - - /// - /// Checks if a URL is considered safe. Users will not e.g. be prompted with a warning when navigating - /// to these URLs. - /// - /// A url. - /// - /// A URL is approved IF: - /// * It is an absolute URI. - /// * It's scheme is part of the safe scheme list. - /// * It is NOT a file:// URI pointing to a local file, e.g. file://C:\Windows\System32\notepad.exe - /// - public static bool IsUriSafe(Uri uri) - { - ArgumentUtility.CheckForNull(uri, "uri"); - return uri.IsAbsoluteUri && SafeUriSchemeList.Contains(uri.Scheme) - && !IsUriLocalFile(uri); // Also exclude all file URLs pointing to local files - } - - /// - /// Checks if a URL is pointing to a local file (not on a network share or host), based on the presence of a host/authority in the URL. - /// It attempts to do no comparison based on the host name. - /// - /// A url. - /// true if the URL points to a file on the local computer. - public static bool IsUriLocalFile(Uri uri) - { - ArgumentUtility.CheckForNull(uri, "uri"); - return uri.IsAbsoluteUri && uri.IsFile && !uri.IsUnc; - } - - /// - /// returns the absolute Uri but in a consistent way such that the presence of a trailing slash doesnt affect the returned string, - /// also converts the uri to lowerInvariant - /// - /// Uri, cannot be null, must be Absolute - /// - public static string GetInvariantAbsoluteUri(Uri uri) - { - //examples (Uri -> return value): - // new Uri("http://server/tfs/")-> "http://server/tfs" - // new Uri("http://server/tfs") -> "http://server/tfs" - // new Uri("http://server/") -> "http://server/" - // new Uri("http://server") -> "http://server/" - - Debug.Assert(uri != null); - Debug.Assert(uri.IsAbsoluteUri); - - string absoluteUri = uri.AbsoluteUri; - - if (uri.Segments.Length > 1) - { - absoluteUri = TrimEndingPathSeparator(absoluteUri); - } - return absoluteUri.ToLowerInvariant(); - } - - /// - /// Joins a URI and a relativePath with a single forward slash. Duplicate slashes at the junction point are removed. - /// - /// The base Uri. Must be an absolute Uri. The last segment of the Uri path (if any) is considered a virtual directory and not removed, even if it does not have a trailing forward slash. - /// The relative path to append to the Uri. - /// If true, any leading forward slashes on the relative path argument are discarded. - /// The base Uri with the relativePath appended to it. - /// - /// This is intended to be an alternative the Uri constructor, which can remove several path segments from your arguments. For example: - /// - /// new Uri(new Uri("http://localhost/abc/efg/"), "/Hello/World") returns http://localhost/Hello/World ("/abc/efg/" removed due to absolute path argument) - /// new Uri(new Uri("http://localhost/dir1/dir2"), "hi.txt") returns http://localhost/dir1/hi.txt ("dir2" removed due to lack of trailing slash) - /// - public static Uri Combine(string baseUri, String relativePath, Boolean treatAbsolutePathAsRelative) - { - Uri uri = new Uri(baseUri); - Debug.Assert(uri.IsAbsoluteUri); - - return Combine(uri, relativePath, treatAbsolutePathAsRelative); - } - - /// - /// Joins a URI and a relativePath with a single forward slash. Duplicate slashes at the junction point are removed. - /// - /// The base Uri. Must be an absolute Uri. The last segment of the Uri path (if any) is considered a virtual directory and not removed, even if it does not have a trailing forward slash. - /// The relative path to append to the Uri. - /// If true, any leading forward slashes on the relative path argument are discarded. - /// The base Uri with the relativePath appended to it. - /// - /// This is intended to be an alternative the Uri constructor, which can remove several path segments from your arguments. For example: - /// - /// new Uri(new Uri("http://localhost/abc/efg/"), "/Hello/World") returns http://localhost/Hello/World ("/abc/efg/" removed due to absolute path argument) - /// new Uri(new Uri("http://localhost/dir1/dir2"), "hi.txt") returns http://localhost/dir1/hi.txt ("dir2" removed due to lack of trailing slash) - /// - public static Uri Combine(Uri baseUri, String relativePath, Boolean treatAbsolutePathAsRelative) - { - if (baseUri == null) - { - throw new ArgumentNullException("baseUri"); - } - - if (relativePath == null) - { - throw new ArgumentNullException("relativePath"); - } - - UriBuilder uriBuilder = new UriBuilder(baseUri); - - Char[] forwardSlash = new Char[] { '/' }; - - // The base Uri might have several trailing slashes, so lets get rid of all of them. - uriBuilder.Path = uriBuilder.Path.TrimEnd(forwardSlash); - - // Now add a single trailing slash to the baseUri to ensure its last path segment is interpreted as a directory instead of a file. - uriBuilder.Path = UriUtility.AppendSlashToPathIfNeeded(uriBuilder.Path); - - if (VssStringComparer.Url.StartsWith(relativePath, "/")) - { - if (treatAbsolutePathAsRelative) - { - // remove any leading slashes - relativePath = relativePath.TrimStart(forwardSlash); - } - else - { - throw new ArgumentException(CommonResources.AbsoluteVirtualPathNotAllowed(relativePath), "relativePath"); - } - } - - CheckRelativePath(relativePath); - - Uri relativeUri = new Uri(relativePath, UriKind.Relative); - - return new Uri(uriBuilder.Uri, relativeUri); - } - - public static bool Equals(Uri uri1, Uri uri2) - { - return AbsoluteUriStringComparer.Equals(uri1, uri2); - } - - /// - /// Combine two paths using "/" instead of "\" like Path.Combine does - /// - /// the first part of the path - /// the second part of the path - /// combined path - public static string CombinePath(string part1, string part2) - { - char[] slash = new char[] { '/' }; - - if (string.IsNullOrEmpty(part1)) - { - return part2; - } - - if (string.IsNullOrEmpty(part2)) - { - return part1; - } - - return string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", part1.TrimEnd(slash), part2.TrimStart(slash)); - } - - /// - /// Returns 'true' if the specified uri is http or https, 'false' otherwise. - /// - public static bool IsUriHttp(Uri uri) - { - ArgumentUtility.CheckForNull(uri, "uri"); - - return uri.IsAbsoluteUri && (uri.Scheme == c_uriSchemeHttp || uri.Scheme == c_uriSchemeHttps); - } - - /// - /// Check that the Uri has http or https as its scheme. We don't want anyone pointing at file://virus.exe. - /// - /// Uri to be checked. - public static void CheckUriIsHttp(Uri uri) - { - CheckUriIsHttp(uri, true); - } - - /// - /// Check that the Uri has http or https as its scheme. We don't want anyone pointing at file://virus.exe. - /// - /// Uri to be checked. - /// Allow sub path and query string if true. If false, the URL must be authority only. - public static void CheckUriIsHttp(Uri uri, bool allowPathAndQuery) - { - if (uri != null) - { - if (!IsUriHttp(uri)) - { - //It isn't an http/https location so we disallow it. - throw new VssServiceException(CommonResources.UriUtility_UriNotAllowed(uri.AbsoluteUri)); - } - - if (allowPathAndQuery == false && uri.PathAndQuery.Trim(new char[] { '/' }).Length > 0) - { - throw new VssServiceException(CommonResources.UriUtility_MustBeAuthorityOnlyUri(uri, uri.GetLeftPart(UriPartial.Authority))); - } - } - } - - /// - /// Check that a given Uri is an absolute Uri. Also, ensure its is http or https. - /// - /// Uri to be checked. - public static void CheckUriIsAbsoluteAndHttp(Uri uri) - { - CheckUriIsAbsoluteAndHttp(uri, true); - } - - /// - /// Check that a given Uri is an absolute Uri. Also, ensure its is http or https. - /// - /// Uri to be checked. - /// Allow sub path and query string if true. If false, the URL must be authority only. - public static void CheckUriIsAbsoluteAndHttp(Uri uri, bool allowPathAndQuery) - { - if (uri != null) - { - if (uri.IsAbsoluteUri == false) - { - throw new VssServiceException(CommonResources.UriUtility_AbsoluteUriRequired(uri.OriginalString)); - } - CheckUriIsHttp(uri, allowPathAndQuery); - } - } - - /// - /// Check the relative path to ensure it is valid. - /// - /// - public static void CheckRelativePath(string relativePath) - { - if (string.IsNullOrEmpty(relativePath) == false) - { - try - { - relativePath = relativePath.Replace("\\", "/"); - - Uri temp = new Uri(relativePath, UriKind.RelativeOrAbsolute); - if (temp.IsAbsoluteUri == true) - { - //It isn't a valid relative path so we disallow it. - throw new VssServiceException(CommonResources.UriUtility_RelativePathInvalid(relativePath)); - } - } - - catch (Exception) - { - //It isn't a valid relative path so we disallow it. - throw new VssServiceException(CommonResources.UriUtility_RelativePathInvalid(relativePath)); - } - } - } - - /// - /// Given an HTTP URI, returns the UNC URI as known to the Windows Client WebDav Redirector. - /// The UNC path is in the following form: - /// \\server[@SSL][@port][\path] - /// This function is equivalent to the native API by the same name on Vista/2008+, but provided here for compatibility with XP/2003. - /// - /// Well-formed http or https path. Alternate ports are supported. - /// UNC path - public static string GetDavUncFromHttpPath(string httppath) - { - Uri uri = new Uri(httppath, UriKind.Absolute); - CheckUriIsHttp(uri); - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - sb.Append(System.IO.Path.DirectorySeparatorChar); - sb.Append(System.IO.Path.DirectorySeparatorChar); - sb.Append(uri.Host); - - if (uri.Scheme == Uri.UriSchemeHttps) - { - sb.Append("@SSL"); - } - - if (!uri.IsDefaultPort) - { - sb.Append("@"); - sb.Append(uri.Port); - } - - sb.Append(System.IO.Path.DirectorySeparatorChar); - - // Add "DavWWWRoot" to be explicit (this is supported by redirector on all OS versions): - // + resistent to conflicts and ordering of UNC providers. - // + better performance on Vista (after KB945435 hotfix applied) since it goes directly - // to WebDAV redirector instead of trying each UNC provider which may timeout due to - // certain routers configured to drop packets on SMB ports (139, 445). - // - confusing to user => avoid displaying UNC path, cuz user may think there's - // supposed to be a "DavWWWRoot" directory when it's just a client name-mangling. - sb.Append("DavWWWRoot"); // don't localize! - sb.Append(System.IO.Path.DirectorySeparatorChar); - - string specpath = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped); - string normpath = specpath.Replace('/', System.IO.Path.DirectorySeparatorChar); - sb.Append(normpath); - - return sb.ToString(); - } - - /// - /// Given a input path that might correspond to a UNC path known to the Windows Client WebDav Redirector, - /// returns the converted UNC path to an HTTP (or HTTPS) url. - /// - /// - /// - /// The UNC path is in the following form: - /// \\server[@SSL][@port][\path] - /// - public static Uri TryGetHttpUriFromDavUncPath(string uncPath) - { - if (uncPath == null) - { - throw new ArgumentNullException("uncPath"); - } - - // Some valid paths for this regex - // \\foo\DavWWWRoot\bar\baz - // \\foo@8888\DavWWWRoot\bar\baz - // \\foo@SSL\DavWWWRoot\bar\baz - // \\foo@SSL@3234\DavWWWRoot\bar\baz - Regex regex = new Regex(@"^\\\\(?[^\\|@]+)(?@SSL)?(@(?\d+))?\\DavWWWRoot\\(?.+)$", RegexOptions.IgnoreCase | RegexOptions.Singleline); - - Match match = regex.Match(uncPath); - if (match.Success) - { - Group hostGroup = match.Groups["host"]; - Group sslGroup = match.Groups["ssl"]; - Group portGroup = match.Groups["port"]; - Group pathGroup = match.Groups["path"]; - - string scheme = (!sslGroup.Success) ? Uri.UriSchemeHttp : Uri.UriSchemeHttps; - string hostName = hostGroup.Value; - string port = (!portGroup.Success) ? "" : ":" + portGroup.Value; - string path = pathGroup.Value.Replace(Path.DirectorySeparatorChar, '/'); - - string url = String.Format(CultureInfo.InvariantCulture, "{0}://{1}{2}/{3}", scheme, hostName, port, path); - return new Uri(url, UriKind.Absolute); - } - - return null; - } - - /// - /// Determine if two hostnames correspond to the same machine. - /// - /// First hostname - /// Second hostname - /// True, if same machine. - public static bool IsSameMachine(string hostname1, string hostname2) - { - bool isSame = false; - - try - { - if (string.IsNullOrEmpty(hostname1) || string.IsNullOrEmpty(hostname2)) - { - isSame = false; - } - else if (String.Equals(hostname1, hostname2, StringComparison.OrdinalIgnoreCase)) - { - isSame = true; - } - else - { - string host1Dns = Dns.GetHostEntry(hostname1).HostName; - string host2Dns = Dns.GetHostEntry(hostname2).HostName; - isSame = string.Equals(host1Dns, host2Dns, StringComparison.OrdinalIgnoreCase); - } - } - catch (SocketException)// ex) - { - // A machine name could not be resolved, for the purposes of this method, - // assume that machines are not the same and ignore the error - - // ToDo: tedchamb come back to this - //TeamFoundationTrace.TraceException(ex); - } - - return isSame; - } - - /// - /// Returns true if supplied domain is equal to or is a sub-domain of parentDomain - /// - public static Boolean IsSubdomainOf(string domain, string parentDomain) - { - // More efficient than: 'domain.Equals(parentDomain) || domain.EndsWith("." + parentDomain)' - return domain.EndsWith(parentDomain, StringComparison.Ordinal) && - (domain.Length == parentDomain.Length || domain[domain.Length - parentDomain.Length - 1] == '.'); - } - - /// - /// Verifies that the specified uri is valid or can be made into a valid http address by prepending 'http://' to it. - /// If the uri is not valid an exception is thrown. - /// - /// - /// The validated uri, including 'http://' if it was prepended to make it valid. - public static Uri GetAbsoluteUriFromString(string uriString) - { - Uri uri = GetUriFromString(uriString); - - if (uri == null) - { - throw new VssServiceException(CommonResources.UrlNotValid()); - } - - return uri; - } - - /// - /// Creates a URI from a string. Adds http to the front if its not there. - /// Requires that the Uri scheme be http or https. - /// - /// String to convert to an absolute uri. - /// The validated uri, including 'http://' if it was prepended to make it valid, or null if the uri is not valid. - public static Uri GetUriFromString(string val) - { - Uri uri; - if (TryCreateAbsoluteUri(val, true, out uri)) - { - return uri; - } - return null; - } - - /// - /// Creates an absolute URI from a string. Adds http to the front if its not there. - /// If 'requireHttpScheme' is 'true' this method will return false if the url - /// doesn't start with http or https. - /// - /// String to convert to an absolute uri. - /// 'true' to require that the scheme is http or https, 'false' to allow any scheme. - /// - /// Either the uri or 'null' if it is not valid. - public static bool TryCreateAbsoluteUri(string val, bool requireHttpScheme, out Uri uri) - { - uri = null; - - val = val != null ? val.Trim() : null; - - if (string.IsNullOrEmpty(val)) - { - return false; - } - - try - { - uri = new Uri(val); - } - catch (FormatException) - { - } - - // try adding http if the uri doesn't already start with http or https - if ((uri == null || !uri.IsAbsoluteUri) && - !VssStringComparer.Url.StartsWith(val, c_uriSchemeHttp) && - !VssStringComparer.Url.StartsWith(val, c_uriSchemeHttps)) - { - try - { - val = c_uriSchemeHttp + "://" + val; - uri = new Uri(val); - } - catch (FormatException) - { - } - } - - if (uri == null) - { - return false; - } - - if (requireHttpScheme && - !VssStringComparer.Url.StartsWith(uri.Scheme, c_uriSchemeHttp) && - !VssStringComparer.Url.StartsWith(uri.Scheme, c_uriSchemeHttps)) - { - return false; - } - - if (!uri.IsAbsoluteUri) - { - uri = null; - return false; - } - - return true; - } - - /// - /// Ensures that a relative path starts with a forward slash. - /// - /// The relative path. - public static string EnsureStartsWithPathSeparator(string relativePath) - { - if (relativePath != null && !VssStringComparer.Url.StartsWith(relativePath, PathSeparator)) - { - relativePath = PathSeparator + relativePath; - } - - return relativePath; - } - - /// - /// Ensures that a relative path ends with a forward slash. - /// - /// The relative path. - public static string EnsureEndsWithPathSeparator(string relativePath) - { - if (relativePath != null && !VssStringComparer.Url.EndsWith(relativePath, PathSeparator)) - { - relativePath += PathSeparator; - } - - return relativePath; - } - - /// - /// Trims any starting slashes from the input path. - /// - /// The relative path. - public static string TrimStartingPathSeparator(string relativePath) - { - return (relativePath != null) ? relativePath.TrimStart(PathSeparatorChar) : null; - } - - /// - /// Trims any ending slashes from the input path. - /// - /// The relative path. - public static string TrimEndingPathSeparator(string relativePath) - { - return (relativePath != null) ? relativePath.TrimEnd(PathSeparatorChar) : null; - } - - /// - /// Trims any starting or ending slashes from the input path. - /// - /// The relative path. - public static string TrimPathSeparators(string relativePath) - { - return (relativePath != null) ? relativePath.Trim(PathSeparatorChar) : null; - } - - public static String AppendSlashToPathIfNeeded(string path) - { - - if (path == null) return null; - - int l = path.Length; - if (l == 0) return path; - - if (path[l - 1] != '/') - path += '/'; - - return path; - } - - /// - /// Correct URI content to remove excess(duplicate) separators in path section. - /// - public static Uri NormalizePathSeparators(Uri uri) - { - //Skip normalization when content is properly formed. - if (uri.LocalPath.Contains("//")) - { - UriBuilder builder = new UriBuilder(uri); - string path = builder.Path; - - //Remove grouped slashes - bias towards robustness over algorithmic efficiency on this corner scenario. - while (path.Contains("//")) - { - path = path.Replace("//", "/"); - } - builder.Path = path; - uri = builder.Uri; - } - return uri; - } - -#region functionality forked from System.Web.HttpUtility - //************************************************************************************************* - // This region UriUtility contains functionality forked from System.Web.HttpUtility. - // Only our server assemblies can take a dependency on System.Web because it is not part of the - // .NET Framework "Client Profile". Client and common code that needs to use helper functions - // such as UrlEncode and UrlDecode from System.Web.HttpUtility must call the methods on this class - // instead to avoid a dependency on System.Web. - // - // Copyright (c) Microsoft Corporation. All rights reserved. - //************************************************************************************************* - - // Don't entity encode high chars (160 to 256), to fix bugs VSWhidbey 85857/111927 - // REVIEW: comment out this line to fix VSWhidbey 85857/111927, after we verify that it's safe to do so - -#region ParseFragmentString - - public static NameValueCollection ParseFragmentString(string fragment) - { - return ParseFragmentString(fragment, Encoding.UTF8); - } - - public static NameValueCollection ParseFragmentString(string fragment, Encoding encoding) - { - return ParseFragmentString(fragment, encoding, true); - } - - public static NameValueCollection ParseFragmentString(string fragment, Encoding encoding, Boolean urlEncoded) - { - ArgumentUtility.CheckForNull(fragment, "fragment"); - ArgumentUtility.CheckForNull(encoding, "encoding"); - - if (fragment.Length > 0 && fragment[0] == '#') - { - fragment = fragment.Substring(1); - } - - return new HttpValueCollection(fragment, false, urlEncoded, encoding); - } - -#endregion - -#region ParseQueryString - - // *** Source: ndp/fx/src/xsp/system/web/httpserverutility.cs - - public static NameValueCollection ParseQueryString(string query) - { - return ParseQueryString(query, Encoding.UTF8); - } - - public static NameValueCollection ParseQueryString(string query, Encoding encoding) - { - return ParseQueryString(query, encoding, true); - } - - public static NameValueCollection ParseQueryString(string query, Encoding encoding, Boolean urlEncoded) - { - ArgumentUtility.CheckForNull(query, "query"); - ArgumentUtility.CheckForNull(encoding, "encoding"); - - if (query.Length > 0 && query[0] == '?') - { - query = query.Substring(1); - } - - return new HttpValueCollection(query, false, urlEncoded, encoding); - } - -#endregion - -#region UrlEncode implementation - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoder.cs - - private static byte[] UrlEncode(byte[] bytes, int offset, int count, bool alwaysCreateNewReturnValue) - { - byte[] encoded = UrlEncode(bytes, offset, count); - - return (alwaysCreateNewReturnValue && (encoded != null) && (encoded == bytes)) - ? (byte[])encoded.Clone() - : encoded; - } - - private static byte[] UrlEncode(byte[] bytes, int offset, int count) - { - if (!ValidateUrlEncodingParameters(bytes, offset, count)) - { - return null; - } - - int cSpaces = 0; - int cUnsafe = 0; - - // count them first - for (int i = 0; i < count; i++) - { - char ch = (char)bytes[offset + i]; - - if (ch == ' ') - cSpaces++; - else if (!IsUrlSafeChar(ch)) - cUnsafe++; - } - - // nothing to expand? - if (cSpaces == 0 && cUnsafe == 0) - return bytes; - - // expand not 'safe' characters into %XX, spaces to +s - byte[] expandedBytes = new byte[count + cUnsafe * 2]; - int pos = 0; - - for (int i = 0; i < count; i++) - { - byte b = bytes[offset + i]; - char ch = (char)b; - - if (IsUrlSafeChar(ch)) - { - expandedBytes[pos++] = b; - } - else if (ch == ' ') - { - expandedBytes[pos++] = (byte)'+'; - } - else - { - expandedBytes[pos++] = (byte)'%'; - expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf); - expandedBytes[pos++] = (byte)IntToHex(b & 0x0f); - } - } - - return expandedBytes; - } - - // Helper to encode the non-ASCII url characters only - private static String UrlEncodeNonAscii(string str, Encoding e) - { - if (String.IsNullOrEmpty(str)) - return str; - if (e == null) - e = Encoding.UTF8; - byte[] bytes = e.GetBytes(str); - byte[] encodedBytes = UrlEncodeNonAscii(bytes, 0, bytes.Length, false /* alwaysCreateNewReturnValue */); - return Encoding.ASCII.GetString(encodedBytes); - } - - private static byte[] UrlEncodeNonAscii(byte[] bytes, int offset, int count, bool alwaysCreateNewReturnValue) - { - if (!ValidateUrlEncodingParameters(bytes, offset, count)) - { - return null; - } - - int cNonAscii = 0; - - // count them first - for (int i = 0; i < count; i++) - { - if (IsNonAsciiByte(bytes[offset + i])) - cNonAscii++; - } - - // nothing to expand? - if (!alwaysCreateNewReturnValue && cNonAscii == 0) - return bytes; - - // expand not 'safe' characters into %XX, spaces to +s - byte[] expandedBytes = new byte[count + cNonAscii * 2]; - int pos = 0; - - for (int i = 0; i < count; i++) - { - byte b = bytes[offset + i]; - - if (IsNonAsciiByte(b)) - { - expandedBytes[pos++] = (byte)'%'; - expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf); - expandedBytes[pos++] = (byte)IntToHex(b & 0x0f); - } - else - { - expandedBytes[pos++] = b; - } - } - - return expandedBytes; - } - -#endregion - -#region UrlEncode public methods - - // *** Source: ndp/fx/src/xsp/system/web/httpserverutility.cs - - public static string UrlEncode(string str) - { - if (str == null) - return null; - - return UrlEncode(str, Encoding.UTF8); - } - - public static string Base64Encode(string str) - { - if (str == null) - return null; - - return Convert.ToBase64String(Encoding.UTF8.GetBytes(str)); - } - - public static string UrlEncode(string str, Encoding e) - { - if (str == null) - return null; - - return Encoding.ASCII.GetString(UrlEncodeToBytes(str, e)); - } - public static string UrlEncode(byte[] bytes) - { - if (bytes == null) - return null; - - return Encoding.ASCII.GetString(UrlEncodeToBytes(bytes)); - } - - public static byte[] UrlEncodeToBytes(string str) - { - if (str == null) - return null; - - return UrlEncodeToBytes(str, Encoding.UTF8); - } - - public static byte[] UrlEncodeToBytes(byte[] bytes) - { - if (bytes == null) - return null; - - return UrlEncodeToBytes(bytes, 0, bytes.Length); - } - - public static byte[] UrlEncodeToBytes(string str, Encoding e) - { - if (str == null) - return null; - - byte[] bytes = e.GetBytes(str); - return UrlEncode(bytes, 0, bytes.Length, false /* alwaysCreateNewReturnValue */); - } - - public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) - { - return UrlEncode(bytes, offset, count, true /* alwaysCreateNewReturnValue */); - } - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoder.cs - - public static string UrlPathEncode(string str) - { - if (String.IsNullOrEmpty(str)) - { - return str; - } - - // recurse in case there is a query string - int i = str.IndexOf('?'); - if (i >= 0) - return UrlPathEncode(str.Substring(0, i)) + str.Substring(i); - - // encode DBCS characters and spaces only - return UrlEncodeSpaces(UrlEncodeNonAscii(str, Encoding.UTF8)); - } - -#endregion - -#region UrlEncodeUnicode - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoder.cs - - public static string UrlEncodeUnicode(string value) - { - if (value == null) - { - return null; - } - - int l = value.Length; - StringBuilder sb = new StringBuilder(l); - - for (int i = 0; i < l; i++) - { - char ch = value[i]; - - if ((ch & 0xff80) == 0) - { // 7 bit? - if (IsUrlSafeChar(ch)) - { - sb.Append(ch); - } - else if (ch == ' ') - { - sb.Append('+'); - } - else - { - sb.Append('%'); - sb.Append(IntToHex((ch >> 4) & 0xf)); - sb.Append(IntToHex((ch) & 0xf)); - } - } - else - { // arbitrary Unicode? - sb.Append("%u"); - sb.Append(IntToHex((ch >> 12) & 0xf)); - sb.Append(IntToHex((ch >> 8) & 0xf)); - sb.Append(IntToHex((ch >> 4) & 0xf)); - sb.Append(IntToHex((ch) & 0xf)); - } - } - - return sb.ToString(); - } - -#endregion - -#region HttpValueCollection nested class - - // *** Source: ndp/fx/src/xsp/system/web/httpvaluecollection.cs - - [Serializable()] - internal class HttpValueCollection : NameValueCollection - { - internal HttpValueCollection() - : base(StringComparer.OrdinalIgnoreCase) - { - } - - internal HttpValueCollection(String str, bool readOnly, bool urlencoded, Encoding encoding) - : base(StringComparer.OrdinalIgnoreCase) - { - if (!String.IsNullOrEmpty(str)) - FillFromString(str, urlencoded, encoding); - - IsReadOnly = readOnly; - } - - internal HttpValueCollection(int capacity) - : base(capacity, StringComparer.OrdinalIgnoreCase) - { - } - - protected HttpValueCollection(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - internal void MakeReadOnly() - { - IsReadOnly = true; - } - - internal void MakeReadWrite() - { - IsReadOnly = false; - } - - internal void FillFromString(String s) - { - FillFromString(s, false, null); - } - - internal void FillFromString(String s, bool urlencoded, Encoding encoding) - { - int l = (s != null) ? s.Length : 0; - int i = 0; - - while (i < l) - { - // find next & while noting first = on the way (and if there are more) - - int si = i; - int ti = -1; - - while (i < l) - { - char ch = s[i]; - - if (ch == '=') - { - if (ti < 0) - ti = i; - } - else if (ch == '&') - { - break; - } - - i++; - } - - // extract the name / value pair - - String name = null; - String value = null; - - if (ti >= 0) - { - name = s.Substring(si, ti - si); - value = s.Substring(ti + 1, i - ti - 1); - } - else - { - value = s.Substring(si, i - si); - } - - // add name / value pair to the collection - - if (urlencoded) - base.Add( - UriUtility.UrlDecode(name, encoding), - UriUtility.UrlDecode(value, encoding)); - else - base.Add(name, value); - - // trailing '&' - - if (i == l - 1 && s[i] == '&') - base.Add(null, String.Empty); - - i++; - } - } - - internal void FillFromEncodedBytes(byte[] bytes, Encoding encoding) - { - int l = (bytes != null) ? bytes.Length : 0; - int i = 0; - - while (i < l) - { - // find next & while noting first = on the way (and if there are more) - - int si = i; - int ti = -1; - - while (i < l) - { - byte b = bytes[i]; - - if (b == '=') - { - if (ti < 0) - ti = i; - } - else if (b == '&') - { - break; - } - - i++; - } - - // extract the name / value pair - - String name, value; - - if (ti >= 0) - { - name = UriUtility.UrlDecode(bytes, si, ti - si, encoding); - value = UriUtility.UrlDecode(bytes, ti + 1, i - ti - 1, encoding); - } - else - { - name = null; - value = UriUtility.UrlDecode(bytes, si, i - si, encoding); - } - - // add name / value pair to the collection - - base.Add(name, value); - - // trailing '&' - - if (i == l - 1 && bytes[i] == '&') - base.Add(null, String.Empty); - - i++; - } - } - - internal void Reset() - { - base.Clear(); - } - - public override String ToString() - { - return ToString(true); - } - - internal virtual String ToString(bool urlencoded) - { - return ToString(urlencoded, null); - } - - internal virtual String ToString(bool urlencoded, IDictionary excludeKeys) - { - int n = Count; - if (n == 0) - return String.Empty; - - StringBuilder s = new StringBuilder(); - String key, keyPrefix, item; - - for (int i = 0; i < n; i++) - { - key = GetKey(i); - - if (excludeKeys != null && key != null && excludeKeys[key] != null) - continue; - if (urlencoded) - key = UriUtility.UrlEncodeUnicode(key); - keyPrefix = (key != null) ? (key + "=") : String.Empty; - - ArrayList values = (ArrayList)BaseGet(i); - int numValues = (values != null) ? values.Count : 0; - - if (s.Length > 0) - s.Append('&'); - - if (numValues == 1) - { - s.Append(keyPrefix); - item = (String)values[0]; - if (urlencoded) - item = UriUtility.UrlEncodeUnicode(item); - s.Append(item); - } - else if (numValues == 0) - { - s.Append(keyPrefix); - } - else - { - for (int j = 0; j < numValues; j++) - { - if (j > 0) - s.Append('&'); - s.Append(keyPrefix); - item = (String)values[j]; - if (urlencoded) - item = UriUtility.UrlEncodeUnicode(item); - s.Append(item); - } - } - } - - return s.ToString(); - } - } - -#endregion - -#region HtmlEncode - - // *** Source: ndp/fx/src/net/system/net/webutility.cs - - public static string HtmlEncode(string value) - { - if (String.IsNullOrEmpty(value)) - { - return value; - } - - // Don't create string writer if we don't have nothing to encode - int index = IndexOfHtmlEncodingChars(value, 0); - if (index == -1) - { - return value; - } - - using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture)) - { - HtmlEncode(value, writer); - return writer.ToString(); - } - } - - public static unsafe void HtmlEncode(string value, TextWriter output) - { - if (value == null) - { - return; - } - if (output == null) - { - throw new ArgumentNullException("output"); - } - - int index = IndexOfHtmlEncodingChars(value, 0); - if (index == -1) - { - output.Write(value); - return; - } - - Debug.Assert(0 <= index && index <= value.Length, "0 <= index && index <= value.Length"); - - int cch = value.Length - index; - fixed (char* str = value) - { - char* pch = str; - while (index-- > 0) - { - output.Write(*pch++); - } - - while (cch-- > 0) - { - char ch = *pch++; - if (ch <= '>') - { - switch (ch) - { - case '<': - output.Write("<"); - break; - case '>': - output.Write(">"); - break; - case '"': - output.Write("""); - break; - case '\'': - output.Write("'"); - break; - case '&': - output.Write("&"); - break; - default: - output.Write(ch); - break; - } - } -#if ENTITY_ENCODE_HIGH_ASCII_CHARS - else if (ch >= 160 && ch < 256) - { - // The seemingly arbitrary 160 comes from RFC - output.Write("&#"); - output.Write(((int)ch).ToString(NumberFormatInfo.InvariantInfo)); - output.Write(';'); - } -#endif // ENTITY_ENCODE_HIGH_ASCII_CHARS - else - { - output.Write(ch); - } - } - } - } - - #endregion - -#region HtmlEncode/Decode helper methods - - // *** Source: ndp/fx/src/net/system/net/webutility.cs - - private static unsafe int IndexOfHtmlEncodingChars(string s, int startPos) - { - Debug.Assert(0 <= startPos && startPos <= s.Length, "0 <= startPos && startPos <= s.Length"); - - int cch = s.Length - startPos; - fixed (char* str = s) - { - for (char* pch = &str[startPos]; cch > 0; pch++, cch--) - { - char ch = *pch; - if (ch <= '>') - { - switch (ch) - { - case '<': - case '>': - case '"': - case '\'': - case '&': - return s.Length - cch; - } - } -#if ENTITY_ENCODE_HIGH_ASCII_CHARS - else if (ch >= 160 && ch < 256) - { - return s.Length - cch; - } -#endif // ENTITY_ENCODE_HIGH_ASCII_CHARS - } - } - - return -1; - } - -#endregion - -#region UrlDecode implementation - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoder.cs - - private static string UrlDecodeInternal(string value, Encoding encoding) - { - if (value == null) - { - return null; - } - - int count = value.Length; - UrlDecoder helper = new UrlDecoder(count, encoding); - - // go through the string's chars collapsing %XX and %uXXXX and - // appending each char as char, with exception of %XX constructs - // that are appended as bytes - - for (int pos = 0; pos < count; pos++) - { - char ch = value[pos]; - - if (ch == '+') - { - ch = ' '; - } - else if (ch == '%' && pos < count - 2) - { - if (value[pos + 1] == 'u' && pos < count - 5) - { - int h1 = HexToInt(value[pos + 2]); - int h2 = HexToInt(value[pos + 3]); - int h3 = HexToInt(value[pos + 4]); - int h4 = HexToInt(value[pos + 5]); - - if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0) - { // valid 4 hex chars - ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4); - pos += 5; - - // only add as char - helper.AddChar(ch); - continue; - } - } - else - { - int h1 = HexToInt(value[pos + 1]); - int h2 = HexToInt(value[pos + 2]); - - if (h1 >= 0 && h2 >= 0) - { // valid 2 hex chars - byte b = (byte)((h1 << 4) | h2); - pos += 2; - - // don't add as char - helper.AddByte(b); - continue; - } - } - } - - if ((ch & 0xFF80) == 0) - helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode - else - helper.AddChar(ch); - } - - return helper.GetString(); - } - - private static byte[] UrlDecodeInternal(byte[] bytes, int offset, int count) - { - if (!ValidateUrlEncodingParameters(bytes, offset, count)) - { - return null; - } - - int decodedBytesCount = 0; - byte[] decodedBytes = new byte[count]; - - for (int i = 0; i < count; i++) - { - int pos = offset + i; - byte b = bytes[pos]; - - if (b == '+') - { - b = (byte)' '; - } - else if (b == '%' && i < count - 2) - { - int h1 = HexToInt((char)bytes[pos + 1]); - int h2 = HexToInt((char)bytes[pos + 2]); - - if (h1 >= 0 && h2 >= 0) - { // valid 2 hex chars - b = (byte)((h1 << 4) | h2); - i += 2; - } - } - - decodedBytes[decodedBytesCount++] = b; - } - - if (decodedBytesCount < decodedBytes.Length) - { - byte[] newDecodedBytes = new byte[decodedBytesCount]; - Array.Copy(decodedBytes, newDecodedBytes, decodedBytesCount); - decodedBytes = newDecodedBytes; - } - - return decodedBytes; - } - - private static string UrlDecodeInternal(byte[] bytes, int offset, int count, Encoding encoding) - { - if (!ValidateUrlEncodingParameters(bytes, offset, count)) - { - return null; - } - - UrlDecoder helper = new UrlDecoder(count, encoding); - - // go through the bytes collapsing %XX and %uXXXX and appending - // each byte as byte, with exception of %uXXXX constructs that - // are appended as chars - - for (int i = 0; i < count; i++) - { - int pos = offset + i; - byte b = bytes[pos]; - - // The code assumes that + and % cannot be in multibyte sequence - - if (b == '+') - { - b = (byte)' '; - } - else if (b == '%' && i < count - 2) - { - if (bytes[pos + 1] == 'u' && i < count - 5) - { - int h1 = HexToInt((char)bytes[pos + 2]); - int h2 = HexToInt((char)bytes[pos + 3]); - int h3 = HexToInt((char)bytes[pos + 4]); - int h4 = HexToInt((char)bytes[pos + 5]); - - if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0) - { // valid 4 hex chars - char ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4); - i += 5; - - // don't add as byte - helper.AddChar(ch); - continue; - } - } - else - { - int h1 = HexToInt((char)bytes[pos + 1]); - int h2 = HexToInt((char)bytes[pos + 2]); - - if (h1 >= 0 && h2 >= 0) - { // valid 2 hex chars - b = (byte)((h1 << 4) | h2); - i += 2; - } - } - } - - helper.AddByte(b); - } - - return helper.GetString(); - } - -#endregion - -#region UrlDecode public methods - - // *** Source: ndp/fx/src/xsp/system/web/httpserverutility.cs - - public static string UrlDecode(string str) - { - if (str == null) - return null; - - return UrlDecode(str, Encoding.UTF8); - } - - public static string Base64Decode(string str) - { - if (str == null) - { - return null; - } - return Encoding.UTF8.GetString(Convert.FromBase64String(str)); - } - - public static string UrlDecode(string str, Encoding e) - { - return UrlDecodeInternal(str, e); - } - - public static string UrlDecode(byte[] bytes, Encoding e) - { - if (bytes == null) - return null; - - return UrlDecode(bytes, 0, bytes.Length, e); - } - - public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e) - { - return UrlDecodeInternal(bytes, offset, count, e); - } - - public static byte[] UrlDecodeToBytes(string str) - { - if (str == null) - return null; - - return UrlDecodeToBytes(str, Encoding.UTF8); - } - - public static byte[] UrlDecodeToBytes(string str, Encoding e) - { - if (str == null) - return null; - - return UrlDecodeToBytes(e.GetBytes(str)); - } - - public static byte[] UrlDecodeToBytes(byte[] bytes) - { - if (bytes == null) - return null; - - return UrlDecodeToBytes(bytes, 0, (bytes != null) ? bytes.Length : 0); - } - - public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count) - { - return UrlDecodeInternal(bytes, offset, count); - } - -#endregion - -#region Helper methods - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoderutility.cs - - public static int HexToInt(char h) - { - return (h >= '0' && h <= '9') ? h - '0' : - (h >= 'a' && h <= 'f') ? h - 'a' + 10 : - (h >= 'A' && h <= 'F') ? h - 'A' + 10 : - -1; - } - - public static char IntToHex(int n) - { - Debug.Assert(n < 0x10); - - if (n <= 9) - return (char)(n + (int)'0'); - else - return (char)(n - 10 + (int)'a'); - } - - // Set of safe chars, from RFC 1738.4 minus '+' - public static bool IsUrlSafeChar(char ch) - { - if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9') - return true; - - switch (ch) - { - case '-': - case '_': - case '.': - case '!': - case '*': - case '(': - case ')': - return true; - } - - return false; - } - - // Helper to encode spaces only - internal static String UrlEncodeSpaces(string str) - { - if (str != null && str.IndexOf(' ') >= 0) - str = str.Replace(" ", "%20"); - return str; - } - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoder.cs - - private static bool ValidateUrlEncodingParameters(byte[] bytes, int offset, int count) - { - if (bytes == null && count == 0) - return false; - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - if (offset < 0 || offset > bytes.Length) - { - throw new ArgumentOutOfRangeException("offset"); - } - if (count < 0 || offset + count > bytes.Length) - { - throw new ArgumentOutOfRangeException("count"); - } - - return true; - } - - private static bool IsNonAsciiByte(byte b) - { - return (b >= 0x7F || b < 0x20); - } - -#endregion - -#region UrlDecoder nested class - - // *** Source: ndp/fx/src/xsp/system/web/util/httpencoder.cs - - // Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either chars or bytes - private class UrlDecoder - { - private int _bufferSize; - - // Accumulate characters in a special array - private int _numChars; - private char[] _charBuffer; - - // Accumulate bytes for decoding into characters in a special array - private int _numBytes; - private byte[] _byteBuffer; - - // Encoding to convert chars to bytes - private Encoding _encoding; - - private void FlushBytes() - { - if (_numBytes > 0) - { - _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars); - _numBytes = 0; - } - } - - internal UrlDecoder(int bufferSize, Encoding encoding) - { - _bufferSize = bufferSize; - _encoding = encoding; - - _charBuffer = new char[bufferSize]; - // byte buffer created on demand - } - - internal void AddChar(char ch) - { - if (_numBytes > 0) - FlushBytes(); - - _charBuffer[_numChars++] = ch; - } - - internal void AddByte(byte b) - { - if (_byteBuffer == null) - _byteBuffer = new byte[_bufferSize]; - - _byteBuffer[_numBytes++] = b; - } - - internal String GetString() - { - if (_numBytes > 0) - FlushBytes(); - - if (_numChars > 0) - return new String(_charBuffer, 0, _numChars); - else - return String.Empty; - } - } - -#endregion - -#region HtmlDecode - - // *** Source: ndp/fx/src/net/system/net/webutility.cs - - public static string HtmlDecode(string value) - { - if (String.IsNullOrEmpty(value)) - { - return value; - } - - // Don't create string writer if we don't have nothing to encode - if (value.IndexOf('&') < 0) - { - return value; - } - - using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture)) - { - HtmlDecode(value, writer); - return writer.ToString(); - } - } - - [SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "System.UInt16.TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt16@)", Justification = "UInt16.TryParse guarantees that result is zero if the parse fails.")] - public static void HtmlDecode(string value, TextWriter output) - { - if (value == null) - { - return; - } - if (output == null) - { - throw new ArgumentNullException("output"); - } - - if (value.IndexOf('&') < 0) - { - output.Write(value); // good as is - return; - } - - int l = value.Length; - for (int i = 0; i < l; i++) - { - char ch = value[i]; - - if (ch == '&') - { - // We found a '&'. Now look for the next ';' or '&'. The idea is that - // if we find another '&' before finding a ';', then this is not an entity, - // and the next '&' might start a real entity (VSWhidbey 275184) - int index = value.IndexOfAny(_htmlEntityEndingChars, i + 1); - if (index > 0 && value[index] == ';') - { - string entity = value.Substring(i + 1, index - i - 1); - - if (entity.Length > 1 && entity[0] == '#') - { - // The # syntax can be in decimal or hex, e.g. - // å --> decimal - // å --> same char in hex - // See http://www.w3.org/TR/REC-html40/charset.html#entities - - ushort parsed; - if (entity[1] == 'x' || entity[1] == 'X') - { - UInt16.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out parsed); - } - else - { - UInt16.TryParse(entity.Substring(1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out parsed); - } - - if (parsed != 0) - { - ch = (char)parsed; - i = index; // already looked at everything until semicolon - } - } - else - { - i = index; // already looked at everything until semicolon - - char entityChar = HtmlEntities.Lookup(entity); - if (entityChar != (char)0) - { - ch = entityChar; - } - else - { - output.Write('&'); - output.Write(entity); - output.Write(';'); - continue; - } - } - - } - } - - output.Write(ch); - } - } - -#endregion - -#region HtmlEntities nested class - - // *** Source: ndp/fx/src/net/system/net/webutility.cs - - // helper class for lookup of HTML encoding entities - private static class HtmlEntities - { - // The list is from http://www.w3.org/TR/REC-html40/sgml/entities.html, except for ', which - // is defined in http://www.w3.org/TR/2008/REC-xml-20081126/#sec-predefined-ent. - - private static String[] _entitiesList = new String[] { - "\x0022-quot", - "\x0026-amp", - "\x0027-apos", - "\x003c-lt", - "\x003e-gt", - "\x00a0-nbsp", - "\x00a1-iexcl", - "\x00a2-cent", - "\x00a3-pound", - "\x00a4-curren", - "\x00a5-yen", - "\x00a6-brvbar", - "\x00a7-sect", - "\x00a8-uml", - "\x00a9-copy", - "\x00aa-ordf", - "\x00ab-laquo", - "\x00ac-not", - "\x00ad-shy", - "\x00ae-reg", - "\x00af-macr", - "\x00b0-deg", - "\x00b1-plusmn", - "\x00b2-sup2", - "\x00b3-sup3", - "\x00b4-acute", - "\x00b5-micro", - "\x00b6-para", - "\x00b7-middot", - "\x00b8-cedil", - "\x00b9-sup1", - "\x00ba-ordm", - "\x00bb-raquo", - "\x00bc-frac14", - "\x00bd-frac12", - "\x00be-frac34", - "\x00bf-iquest", - "\x00c0-Agrave", - "\x00c1-Aacute", - "\x00c2-Acirc", - "\x00c3-Atilde", - "\x00c4-Auml", - "\x00c5-Aring", - "\x00c6-AElig", - "\x00c7-Ccedil", - "\x00c8-Egrave", - "\x00c9-Eacute", - "\x00ca-Ecirc", - "\x00cb-Euml", - "\x00cc-Igrave", - "\x00cd-Iacute", - "\x00ce-Icirc", - "\x00cf-Iuml", - "\x00d0-ETH", - "\x00d1-Ntilde", - "\x00d2-Ograve", - "\x00d3-Oacute", - "\x00d4-Ocirc", - "\x00d5-Otilde", - "\x00d6-Ouml", - "\x00d7-times", - "\x00d8-Oslash", - "\x00d9-Ugrave", - "\x00da-Uacute", - "\x00db-Ucirc", - "\x00dc-Uuml", - "\x00dd-Yacute", - "\x00de-THORN", - "\x00df-szlig", - "\x00e0-agrave", - "\x00e1-aacute", - "\x00e2-acirc", - "\x00e3-atilde", - "\x00e4-auml", - "\x00e5-aring", - "\x00e6-aelig", - "\x00e7-ccedil", - "\x00e8-egrave", - "\x00e9-eacute", - "\x00ea-ecirc", - "\x00eb-euml", - "\x00ec-igrave", - "\x00ed-iacute", - "\x00ee-icirc", - "\x00ef-iuml", - "\x00f0-eth", - "\x00f1-ntilde", - "\x00f2-ograve", - "\x00f3-oacute", - "\x00f4-ocirc", - "\x00f5-otilde", - "\x00f6-ouml", - "\x00f7-divide", - "\x00f8-oslash", - "\x00f9-ugrave", - "\x00fa-uacute", - "\x00fb-ucirc", - "\x00fc-uuml", - "\x00fd-yacute", - "\x00fe-thorn", - "\x00ff-yuml", - "\x0152-OElig", - "\x0153-oelig", - "\x0160-Scaron", - "\x0161-scaron", - "\x0178-Yuml", - "\x0192-fnof", - "\x02c6-circ", - "\x02dc-tilde", - "\x0391-Alpha", - "\x0392-Beta", - "\x0393-Gamma", - "\x0394-Delta", - "\x0395-Epsilon", - "\x0396-Zeta", - "\x0397-Eta", - "\x0398-Theta", - "\x0399-Iota", - "\x039a-Kappa", - "\x039b-Lambda", - "\x039c-Mu", - "\x039d-Nu", - "\x039e-Xi", - "\x039f-Omicron", - "\x03a0-Pi", - "\x03a1-Rho", - "\x03a3-Sigma", - "\x03a4-Tau", - "\x03a5-Upsilon", - "\x03a6-Phi", - "\x03a7-Chi", - "\x03a8-Psi", - "\x03a9-Omega", - "\x03b1-alpha", - "\x03b2-beta", - "\x03b3-gamma", - "\x03b4-delta", - "\x03b5-epsilon", - "\x03b6-zeta", - "\x03b7-eta", - "\x03b8-theta", - "\x03b9-iota", - "\x03ba-kappa", - "\x03bb-lambda", - "\x03bc-mu", - "\x03bd-nu", - "\x03be-xi", - "\x03bf-omicron", - "\x03c0-pi", - "\x03c1-rho", - "\x03c2-sigmaf", - "\x03c3-sigma", - "\x03c4-tau", - "\x03c5-upsilon", - "\x03c6-phi", - "\x03c7-chi", - "\x03c8-psi", - "\x03c9-omega", - "\x03d1-thetasym", - "\x03d2-upsih", - "\x03d6-piv", - "\x2002-ensp", - "\x2003-emsp", - "\x2009-thinsp", - "\x200c-zwnj", - "\x200d-zwj", - "\x200e-lrm", - "\x200f-rlm", - "\x2013-ndash", - "\x2014-mdash", - "\x2018-lsquo", - "\x2019-rsquo", - "\x201a-sbquo", - "\x201c-ldquo", - "\x201d-rdquo", - "\x201e-bdquo", - "\x2020-dagger", - "\x2021-Dagger", - "\x2022-bull", - "\x2026-hellip", - "\x2030-permil", - "\x2032-prime", - "\x2033-Prime", - "\x2039-lsaquo", - "\x203a-rsaquo", - "\x203e-oline", - "\x2044-frasl", - "\x20ac-euro", - "\x2111-image", - "\x2118-weierp", - "\x211c-real", - "\x2122-trade", - "\x2135-alefsym", - "\x2190-larr", - "\x2191-uarr", - "\x2192-rarr", - "\x2193-darr", - "\x2194-harr", - "\x21b5-crarr", - "\x21d0-lArr", - "\x21d1-uArr", - "\x21d2-rArr", - "\x21d3-dArr", - "\x21d4-hArr", - "\x2200-forall", - "\x2202-part", - "\x2203-exist", - "\x2205-empty", - "\x2207-nabla", - "\x2208-isin", - "\x2209-notin", - "\x220b-ni", - "\x220f-prod", - "\x2211-sum", - "\x2212-minus", - "\x2217-lowast", - "\x221a-radic", - "\x221d-prop", - "\x221e-infin", - "\x2220-ang", - "\x2227-and", - "\x2228-or", - "\x2229-cap", - "\x222a-cup", - "\x222b-int", - "\x2234-there4", - "\x223c-sim", - "\x2245-cong", - "\x2248-asymp", - "\x2260-ne", - "\x2261-equiv", - "\x2264-le", - "\x2265-ge", - "\x2282-sub", - "\x2283-sup", - "\x2284-nsub", - "\x2286-sube", - "\x2287-supe", - "\x2295-oplus", - "\x2297-otimes", - "\x22a5-perp", - "\x22c5-sdot", - "\x2308-lceil", - "\x2309-rceil", - "\x230a-lfloor", - "\x230b-rfloor", - "\x2329-lang", - "\x232a-rang", - "\x25ca-loz", - "\x2660-spades", - "\x2663-clubs", - "\x2665-hearts", - "\x2666-diams", - }; - - private static Dictionary _lookupTable = GenerateLookupTable(); - - private static Dictionary GenerateLookupTable() - { - // e[0] is unicode char, e[1] is '-', e[2+] is entity string - - Dictionary lookupTable = new Dictionary(StringComparer.Ordinal); - foreach (string e in _entitiesList) - { - lookupTable.Add(e.Substring(2), e[0]); - } - - return lookupTable; - } - - public static char Lookup(string entity) - { - char theChar; - _lookupTable.TryGetValue(entity, out theChar); - return theChar; - } - } - -#endregion - - // *** Source: ndp/fx/src/net/system/net/webutility.cs - private static char[] _htmlEntityEndingChars = new char[] { ';', '&' }; -#endregion - } -} diff --git a/src/Sdk/Common/Common/Utility/VssStringComparer.cs b/src/Sdk/Common/Common/Utility/VssStringComparer.cs deleted file mode 100644 index c156da962..000000000 --- a/src/Sdk/Common/Common/Utility/VssStringComparer.cs +++ /dev/null @@ -1,286 +0,0 @@ -// ************************************************************************************************ -// Microsoft Team Foundation -// -// Microsoft Confidential -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// File: VssStringComparer.cs -// Area: Team Foundation -// Classes: VssStringComparer -// Contents: The Team Foundation string comparison class provides inner classes -// that are used to provide semantic-specific Equals and Compare methods -// and a semantic-specific StringComparer instance. New semantics should -// be added on an as-needed basis. -// ************************************************************************************************ -using System; -using System.Diagnostics; - -namespace GitHub.Services.Common -{ - - // NOTE: Since the recommendations are for Ordinal and OrdinalIgnoreCase, no need to explain those, but - // please explain any instances using non-Ordinal comparisons (CurrentCulture, InvariantCulture) - // so that developers following you can understand the choices and verify they are correct. - - // NOTE: please try to keep the semantic-named properties in alphabetical order to ease merges - - // NOTE: do NOT add xml doc comments - everything in here should be a very thin wrapper around String - // or StringComparer. The usage of the methods and properties in this class should be intuitively - // obvious, so please don't add xml doc comments to this class since it should be wholly internal - // by the time we ship. - - // NOTE: Current guidelines from the CLR team (Dave Fetterman) is to stick with the same operation for both - // Compare and Equals for a given semantic inner class. This has the nice side effect that you don't - // get different behavior between calling Equals or calling Compare == 0. This may seem odd given the - // recommendations about using CurrentCulture for UI operations and Compare being used for sorting - // items for user display in many cases, but we need to have the type of string data determine the - // string comparison enum to use instead of the consumer of the comparison operation so that we're - // consistent in how we treat a given semantic. - - // VssStringComparer should act like StringComparer with a few additional methods for usefulness (Contains, - // StartsWith, EndsWith, etc.) so that it can be a "one-stop shop" for string comparisons. - public class VssStringComparer : StringComparer - { - private StringComparison m_stringComparison; - private StringComparer m_stringComparer; - - protected VssStringComparer(StringComparison stringComparison) - : base() - { - m_stringComparison = stringComparison; - } - - // pass-through implementations based on our current StringComparison setting - public override int Compare(string x, string y) { return String.Compare(x, y, m_stringComparison); } - public override bool Equals(string x, string y) { return String.Equals(x, y, m_stringComparison); } - public override int GetHashCode(string x) { return MatchingStringComparer.GetHashCode(x); } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "y")] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "x")] - public int Compare(string x, int indexX, string y, int indexY, int length) { return String.Compare(x, indexX, y, indexY, length, m_stringComparison); } - - // add new useful methods here - public bool Contains(string main, string pattern) - { - ArgumentUtility.CheckForNull(main, "main"); - ArgumentUtility.CheckForNull(pattern, "pattern"); - - return main.IndexOf(pattern, m_stringComparison) >= 0; - } - - public int IndexOf(string main, string pattern) - { - ArgumentUtility.CheckForNull(main, "main"); - ArgumentUtility.CheckForNull(pattern, "pattern"); - - return main.IndexOf(pattern, m_stringComparison); - } - - public bool StartsWith(string main, string pattern) - { - ArgumentUtility.CheckForNull(main, "main"); - ArgumentUtility.CheckForNull(pattern, "pattern"); - - return main.StartsWith(pattern, m_stringComparison); - } - - public bool EndsWith(string main, string pattern) - { - ArgumentUtility.CheckForNull(main, "main"); - ArgumentUtility.CheckForNull(pattern, "pattern"); - - return main.EndsWith(pattern, m_stringComparison); - } - - private StringComparer MatchingStringComparer - { - get - { - if (m_stringComparer == null) - { - switch (m_stringComparison) - { - case StringComparison.CurrentCulture: - m_stringComparer = StringComparer.CurrentCulture; - break; - - case StringComparison.CurrentCultureIgnoreCase: - m_stringComparer = StringComparer.CurrentCultureIgnoreCase; - break; - - case StringComparison.Ordinal: - m_stringComparer = StringComparer.Ordinal; - break; - - case StringComparison.OrdinalIgnoreCase: - m_stringComparer = StringComparer.OrdinalIgnoreCase; - break; - - default: - Debug.Assert(false, "Unknown StringComparison value"); - m_stringComparer = StringComparer.Ordinal; - break; - } - } - return m_stringComparer; - } - } - - protected static VssStringComparer s_ordinal = new VssStringComparer(StringComparison.Ordinal); - protected static VssStringComparer s_ordinalIgnoreCase = new VssStringComparer(StringComparison.OrdinalIgnoreCase); - protected static VssStringComparer s_currentCulture = new VssStringComparer(StringComparison.CurrentCulture); - protected static VssStringComparer s_currentCultureIgnoreCase = new VssStringComparer(StringComparison.CurrentCultureIgnoreCase); - private static VssStringComparer s_dataSourceIgnoreProtocol = new DataSourceIgnoreProtocolComparer(); - - - public static VssStringComparer ActiveDirectoryEntityIdComparer { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ArtifactType { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ArtifactTool { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer AssemblyName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ContentType { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DomainName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DomainNameUI { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer DatabaseCategory { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DatabaseName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DataSource { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DataSourceIgnoreProtocol { get { return s_dataSourceIgnoreProtocol; } } - public static VssStringComparer DirectoryName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DirectoryEntityIdentifierConstants { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DirectoryEntityPropertyComparer { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DirectoryEntityTypeComparer { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DirectoryEntryNameComparer { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer DirectoryKeyStringComparer { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer EncodingName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer EnvVar { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ExceptionSource { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer FilePath { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer FilePathUI { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer Guid { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer Hostname { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer HostnameUI { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer HttpRequestMethod { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityDescriptor { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityDomain { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityOriginId { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityType { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer LinkName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer MachineName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer MailAddress { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer PropertyName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer RegistrationAttributeName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ReservedGroupName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer WMDSchemaClassName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer SamAccountName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer AccountName { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer SocialType { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer ServerUrl { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ServerUrlUI { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer ServiceInterface { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ServicingOperation { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ToolId { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer Url { get { return s_ordinal; } } - public static VssStringComparer UrlPath { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer UriScheme { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer UriAuthority { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer UserId { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer UserName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer UserNameUI { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer XmlAttributeName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer XmlNodeName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer XmlElement { get { return s_ordinal; } } - public static VssStringComparer XmlAttributeValue { get { return s_ordinalIgnoreCase; } } - - //Framework comparers. - public static VssStringComparer RegistryPath { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ServiceType { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer AccessMappingMoniker { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer CatalogNodePath { get { return s_ordinal; } } - public static VssStringComparer CatalogServiceReference { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer CatalogNodeDependency { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ServicingTokenName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityPropertyName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer Collation { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer FeatureAvailabilityName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer TagName { get { return s_currentCultureIgnoreCase; } } - - //Framework Hosting comparers. - public static VssStringComparer HostingAccountPropertyName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer MessageBusName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer MessageBusSubscriptionName { get { return s_ordinalIgnoreCase; } } - - public static VssStringComparer SID { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer FieldName { get { return s_ordinal; } } - public static VssStringComparer FieldNameUI { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer FieldType { get { return s_ordinal; } } - public static VssStringComparer EventType { get { return s_ordinal; } } - public static VssStringComparer EventTypeIgnoreCase { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer RegistrationEntryName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ServerName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer GroupName { get { return s_currentCultureIgnoreCase; } } - public static VssStringComparer RegistrationUtilities { get { return s_ordinal; } } - public static VssStringComparer RegistrationUtilitiesCaseInsensitive { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer IdentityNameOrdinal { get { return s_ordinal; } } - public static VssStringComparer PlugInId { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ExtensionName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer ExtensionType { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer DomainUrl { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer AccountInfoAccount { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer AccountInfoPassword { get { return s_ordinal; } } - public static VssStringComparer AttributesDescriptor { get { return s_ordinalIgnoreCase; } } - - // Converters comparer - public static VssStringComparer VSSServerPath { get { return s_ordinalIgnoreCase; } } - - // Item rename in VSS is case sensitive. - public static VssStringComparer VSSItemName { get { return s_ordinal; } } - // Web Access Comparers - public static VssStringComparer HtmlElementName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer HtmlAttributeName { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer HtmlAttributeValue { get { return s_ordinalIgnoreCase; } } - - public static VssStringComparer StringFieldConditionEquality { get { return s_ordinalIgnoreCase; } } - public static VssStringComparer StringFieldConditionOrdinal { get { return s_ordinal; } } - - // Service Endpoint Comparer - public static VssStringComparer ServiceEndpointTypeCompararer { get { return s_ordinalIgnoreCase; } } - - private class DataSourceIgnoreProtocolComparer : VssStringComparer - { - public DataSourceIgnoreProtocolComparer() - : base(StringComparison.OrdinalIgnoreCase) - { - } - - public override int Compare(string x, string y) - { - return base.Compare(RemoveProtocolPrefix(x), RemoveProtocolPrefix(y)); - } - - public override bool Equals(string x, string y) - { - return base.Equals(RemoveProtocolPrefix(x), RemoveProtocolPrefix(y)); - } - - private static string RemoveProtocolPrefix(string x) - { - if (x != null) - { - if (x.StartsWith(c_tcpPrefix, StringComparison.OrdinalIgnoreCase)) - { - x = x.Substring(c_tcpPrefix.Length); - } - else if (x.StartsWith(c_npPrefix, StringComparison.OrdinalIgnoreCase)) - { - x = x.Substring(c_npPrefix.Length); - } - } - - return x; - } - - private const string c_tcpPrefix = "tcp:"; - private const string c_npPrefix = "np:"; - } - } -} diff --git a/src/Sdk/Common/Common/Utility/XmlUtility.cs b/src/Sdk/Common/Common/Utility/XmlUtility.cs deleted file mode 100644 index 0c66b3a92..000000000 --- a/src/Sdk/Common/Common/Utility/XmlUtility.cs +++ /dev/null @@ -1,1489 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using System.Xml; -using System.Xml.Linq; - -namespace GitHub.Services.Common.Internal -{ - - [EditorBrowsable(EditorBrowsableState.Never)] -#if !NETSTANDARD - [CLSCompliant(false)] -#endif - public static class XmlUtility - { - internal static FileStream OpenFile(String path, FileShare sharing, Boolean saveFile) - { - XmlDocument noXmlDocument; - return OpenFileHelper(path, sharing, saveFile, false, out noXmlDocument); - } - - internal static XmlDocument OpenXmlFile(out FileStream file, String path, FileShare sharing, Boolean saveFile) - { - XmlDocument xmlDocument; - file = OpenFileHelper(path, sharing, saveFile, true, out xmlDocument); - - return xmlDocument; - } - - private static FileStream OpenFileHelper(String path, FileShare sharing, Boolean saveFile, Boolean loadAsXmlDocument, out XmlDocument xmlDocument) - { - const int RetryCount = 10; - FileStream file = null; - xmlDocument = null; - - if (String.IsNullOrEmpty(path)) - { - return null; - } - - // If the file doesn't exist or an exception is thrown while trying to check that, we don't have - // a cache file. - if (!saveFile && !File.Exists(path)) - { - return null; - } - - int retries = 0; - Random random = null; - while (retries <= RetryCount) - { - try - { - // Make sure the user hasn't made the file read-only if we are writing the file. - FileAccess fileAccess = FileAccess.Read; - FileMode fileMode = FileMode.Open; - if (saveFile) - { - fileAccess = FileAccess.ReadWrite; - fileMode = FileMode.OpenOrCreate; - } - - file = new FileStream(path, fileMode, fileAccess, sharing); - - if (loadAsXmlDocument) - { - XmlReaderSettings settings = new XmlReaderSettings() - { - DtdProcessing = DtdProcessing.Prohibit, - XmlResolver = null, - }; - - using (XmlReader xmlReader = XmlReader.Create(file, settings)) - { - xmlDocument = new XmlDocument(); - xmlDocument.Load(xmlReader); - } - } - - return file; - } - catch (Exception exception) - { - if (file != null) - { - file.Dispose(); - file = null; - } - - if (exception is OperationCanceledException) - { - // Do not swallow the CancelException. - throw; - } - else if (exception is IOException || exception is UnauthorizedAccessException || exception is XmlException) - { - // If there was no cache file on disk, optionally create one. - if (saveFile) - { - try - { - // Create the directory if it does not exist. - if (exception is DirectoryNotFoundException) - { - String dir = Path.GetDirectoryName(path); - Directory.CreateDirectory(dir); - } - - // Reset attributes (file might be read-only) - if (exception is UnauthorizedAccessException) - { - File.SetAttributes(path, FileAttributes.Normal); - } - - xmlDocument = null; - return new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); - } - catch (Exception newException) when (newException is IOException || newException is UnauthorizedAccessException) - { - if (retries >= RetryCount) - { - throw new AggregateException(exception, newException); - } - } - } - else - { - return null; - } - } - else if (retries >= RetryCount) - { - throw new VssServiceException(CommonResources.ErrorReadingFile(Path.GetFileName(path), exception.Message), exception); - } - } - - // Wait before trying again. - if (random == null) - { - random = new Random(); - } - - int sleepTime = random.Next(1, 150); - Task.Delay(sleepTime).Wait(); - retries++; - } - - // Should never get to here - Debug.Fail("Code should be unreachable."); - return null; - } - - internal static void AddXmlAttribute(XmlNode node, String attrName, String value) - { - if (value != null) - { - XmlAttribute attr = node.OwnerDocument.CreateAttribute(null, attrName, null); - node.Attributes.Append(attr); - attr.InnerText = value; - } - } - - /// - /// Returns a single shared instance of secured XML reader settings. - /// - /// - /// The main configuration that is set is to "Harden or Disable XML Entity Resolution", - /// which disallows resolving entities during XML parsing. - /// - /// DO NOT USE this method if you need to resolved XML DTD entities. - /// - public static XmlReaderSettings SecureReaderSettings - { - get - { - if (s_safeSettings == null) - { - XmlReaderSettings settings = new XmlReaderSettings() - { - DtdProcessing = DtdProcessing.Prohibit, - XmlResolver = null, - }; - - s_safeSettings = settings; - } - - return s_safeSettings; - } - } - - public static XmlDocument GetDocument(Stream input) - { - XmlDocument doc = new XmlDocument(); - - using (XmlReader xmlReader = XmlReader.Create(input, SecureReaderSettings)) - { - doc.Load(xmlReader); - } - - return doc; - } - - public static XmlDocument GetDocument(string xml) - { - XmlDocument doc = new XmlDocument(); - using (StringReader stringReader = new StringReader(xml)) - using (XmlReader xmlReader = XmlReader.Create(stringReader, SecureReaderSettings)) - { - doc.Load(xmlReader); - } - - return doc; - } - - public static XmlDocument GetDocumentFromPath(string path) - { - XmlDocument doc = new XmlDocument(); - - using (XmlReader xmlReader = XmlReader.Create(path, SecureReaderSettings)) - { - doc.Load(xmlReader); - } - - return doc; - } - - public static DateTime ToDateTime(String s) - { - DateTime time = XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind); - - // As of Dev11, WIT uses TeamFoundationClientProxy when it used to use TeamFoundationSoapProxy. - // In Orcas, the WIT server would return DateTime strings which were UTC over-the-wire, but were not specified as such. - // e.g. "01/28/2011T22:00:00.000" instead of "01/28/2011T22:00:00.000Z" - // We need to handle that case now. If the time is unspecified, we'll assume it to be Utc. - if (time.Kind == DateTimeKind.Unspecified && - time != DateTime.MinValue && - time != DateTime.MaxValue) - { - time = DateTime.SpecifyKind(time, DateTimeKind.Utc); - } - - // Convert all year one values to DateTime.MinValue, a flag value meaning the date is not set. - // We don't want the timezone set on DateTime.MinValue... - if (time.Year == 1) - { - time = DateTime.MinValue; - } - else - { - time = time.ToLocalTime(); - } - - return time; - } - - public static DateTime ToDateOnly(String s) - { - // we intentionally don't want to call ToLocalTime for converting Date only - // because we ignore both Time and TimeZone. - return XmlConvert.ToDateTime(s, XmlDateTimeSerializationMode.RoundtripKind); - } - - public static String ToStringDateOnly(DateTime d) - { - return d.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture); - } - - public static String ToString(DateTime d) - { - Debug.Assert(d == DateTime.MinValue || d == DateTime.MaxValue || d.Kind != DateTimeKind.Unspecified, "DateTime kind is unspecified instead of Local or Utc."); - return XmlConvert.ToString(d, XmlDateTimeSerializationMode.RoundtripKind); - } - - public static void ObjectToXmlElement(XmlWriter writer, String element, Object o) - { - if (o == null) - { - writer.WriteStartElement(element); - writer.WriteAttributeString("nil", "http://www.w3.org/2001/XMLSchema-instance", "true"); - writer.WriteEndElement(); - } - else - { - String clrTypeName = o.GetType().FullName; - String soapType = null, soapValue = null, soapNamespaceUri = null; - switch (clrTypeName) - { - case "System.Boolean": - soapType = "boolean"; - soapValue = XmlConvert.ToString((Boolean)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Byte": - soapType = "unsignedByte"; - soapValue = XmlConvert.ToString((Byte)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Byte[]": - soapType = "base64Binary"; - byte[] array = (byte[])o; - soapValue = Convert.ToBase64String(array, 0, array.Length); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Char": - soapType = "char"; - soapValue = XmlConvert.ToString((UInt16)((Char)o)); - soapNamespaceUri = "http://microsoft.com/wsdl/types/"; - break; - case "System.DateTime": - soapType = "dateTime"; - soapValue = ToString((DateTime)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Decimal": - soapType = "decimal"; - soapValue = XmlConvert.ToString((Decimal)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Double": - soapType = "double"; - soapValue = XmlConvert.ToString((Double)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Guid": - soapType = "guid"; - soapValue = XmlConvert.ToString((Guid)o); - soapNamespaceUri = "http://microsoft.com/wsdl/types/"; - break; - case "System.Int16": - soapType = "short"; - soapValue = XmlConvert.ToString((Int16)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Int32": - soapType = "int"; - soapValue = XmlConvert.ToString((Int32)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Int64": - soapType = "long"; - soapValue = XmlConvert.ToString((Int64)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.Single": - soapType = "float"; - soapValue = XmlConvert.ToString((Single)o); - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - case "System.String": - soapType = "string"; - soapValue = (String)o; - soapNamespaceUri = "http://www.w3.org/2001/XMLSchema"; - break; - default: - if (o.GetType().IsArray) - { - Debug.Assert(o.GetType().GetArrayRank() == 1, "ERROR: Cannot serialize multi-dimensional arrays"); - - writer.WriteStartElement(element); - writer.WriteAttributeString("type", "http://www.w3.org/2001/XMLSchema-instance", "ArrayOfAnyType"); - ArrayOfObjectToXml(writer, (Object[])o, null, "anyType", true, false, ObjectToXmlElement); - writer.WriteEndElement(); - return; - } - else - { - Debug.Fail("Unknown object type for serialization " + clrTypeName); - throw new ArgumentException(CommonResources.UnknownTypeForSerialization(clrTypeName)); - } - } - - writer.WriteStartElement(element); - writer.WriteStartAttribute("type", "http://www.w3.org/2001/XMLSchema-instance"); - writer.WriteQualifiedName(soapType, soapNamespaceUri); - writer.WriteEndAttribute(); - writer.WriteValue(soapValue); - writer.WriteEndElement(); - } - } - - public static Object ObjectFromXmlElement(XmlReader reader) - { - String soapTypeName = reader.GetAttribute("type", "http://www.w3.org/2001/XMLSchema-instance"); - if (!String.IsNullOrEmpty(soapTypeName)) - { - String[] components = soapTypeName.Split(new char[] { ':' }, StringSplitOptions.None); - if (components.Length == 2) - { - soapTypeName = components[1]; -#if DEBUG - String ns = reader.LookupNamespace(components[0]); - if (!String.IsNullOrEmpty(ns) && - !ns.Equals("http://www.w3.org/2001/XMLSchema", StringComparison.OrdinalIgnoreCase) && - !ns.Equals("http://microsoft.com/wsdl/types/", StringComparison.OrdinalIgnoreCase)) - { - Debug.Fail("Unknown namespace encountered for object type " + ns); - reader.ReadOuterXml(); - return null; - } -#endif - } - - switch (soapTypeName) - { - case "base64Binary": - String str = StringFromXmlElement(reader); - if (str != null) - { - return Convert.FromBase64String(str); - } - return ZeroLengthArrayOfByte; - case "boolean": - return XmlConvert.ToBoolean(StringFromXmlElement(reader)); - case "char": - return (Char)XmlConvert.ToInt16(StringFromXmlElement(reader)); // Char goes over the wire as short - case "dateTime": - return ToDateTime(StringFromXmlElement(reader)); - case "decimal": - return XmlConvert.ToDecimal(StringFromXmlElement(reader)); - case "double": - return XmlConvert.ToDouble(StringFromXmlElement(reader)); - case "float": - return XmlConvert.ToSingle(StringFromXmlElement(reader)); - case "int": - return XmlConvert.ToInt32(StringFromXmlElement(reader)); - case "guid": - return XmlConvert.ToGuid(StringFromXmlElement(reader)); - case "long": - return XmlConvert.ToInt64(StringFromXmlElement(reader)); - case "short": - return XmlConvert.ToInt16(StringFromXmlElement(reader)); - case "string": - return StringFromXmlElement(reader); - case "unsignedByte": - return XmlConvert.ToByte(StringFromXmlElement(reader)); - case "ArrayOfAnyType": - return ArrayOfObjectFromXml(reader); - default: - Debug.Fail("Unknown object type encountered " + soapTypeName); - throw new ArgumentException(CommonResources.UnknownTypeForSerialization(soapTypeName)); - } - } - else if (reader.GetAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance") == "true") - { - reader.ReadInnerXml(); - return null; - } - - return null; - } - - public static void ToXml(XmlWriter writer, String element, Object[] array) - { - if (array == null || array.Length == 0) - { - return; - } - - if (!String.IsNullOrEmpty(element)) - { - writer.WriteStartElement(element); - } - - for (int i = 0; i < array.Length; i++) - { - if (array[i] == null) - { - throw new ArgumentNullException("array[" + i + "]"); - } - ObjectToXmlElement(writer, "anyType", array[i]); - } - - if (!String.IsNullOrEmpty(element)) - { - writer.WriteEndElement(); - } - } - - public static Object[] ArrayOfObjectFromXml(XmlReader reader) - { - List list = new List(); - bool empty = reader.IsEmptyElement; - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - if (reader.HasAttributes && - reader.GetAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance") == "true") - { - list.Add(null); - reader.Read(); - } - else - { - list.Add(ObjectFromXmlElement(reader)); - } - } - reader.ReadEndElement(); - } - return list.ToArray(); - } - - public static void ToXmlElement(XmlWriter writer, String elementName, XmlNode node) - { - if (node == null) - { - return; - } - - writer.WriteStartElement(elementName); - node.WriteTo(writer); - writer.WriteEndElement(); - } - - public static XmlNode XmlNodeFromXmlElement(XmlReader reader) - { - // Advance the reader so we are at the contents of the node rather than - // starting at the root node. Typically the root node will be the name of - // a property, parameter, or result, and we should not include this in the - // resulting XML. - reader.Read(); - - XmlDocument document = new XmlDocument - { - PreserveWhitespace = false - }; - document.Load(reader); - - // Call Normalize to ensure that we don't create a whole bunch of additional XmlText elements - // for blobs of, for example, HTML content. - document.Normalize(); - - reader.ReadEndElement(); - return document.DocumentElement; - } - - public static DateTime DateFromXmlAttribute(XmlReader reader) - { - return ToDateOnly(StringFromXmlAttribute(reader)); - } - - public static DateTime DateFromXmlElement(XmlReader reader) - { - return ToDateOnly(StringFromXmlElement(reader)); - } - - public static void DateToXmlAttribute(XmlWriter writer, String name, DateTime value) - { - StringToXmlAttribute(writer, name, ToStringDateOnly(value)); - } - - public static void DateToXmlElement(XmlWriter writer, String name, DateTime value) - { - StringToXmlElement(writer, name, ToStringDateOnly(value)); - } - - public static Boolean BooleanFromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToBoolean(StringFromXmlAttribute(reader)); - } - - public static DateTime DateTimeFromXmlAttribute(XmlReader reader) - { - return ToDateTime(StringFromXmlAttribute(reader)); - } - - public static DateTime DateTimeFromXmlElement(XmlReader reader) - { - return ToDateTime(StringFromXmlElement(reader)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, DateTime value) - { - StringToXmlAttribute(writer, name, ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, DateTime value) - { - StringToXmlElement(writer, name, ToString(value)); - } - - public static void ToXml(XmlWriter writer, String element, byte[] array) - { - // Omit zero-length arrays to save bandwidth. - if (array == null || array.Length == 0) - { - return; - } - writer.WriteElementString(element, Convert.ToBase64String(array, 0, array.Length)); - } - - public static void ToXmlAttribute(XmlWriter writer, String attr, byte[] array) - { - // Omit zero-length arrays to save bandwidth. - if (array == null || array.Length == 0) - { - return; - } - writer.WriteAttributeString(attr, Convert.ToBase64String(array, 0, array.Length)); - } - - private static XmlReaderSettings s_safeSettings; - - public static String ToString(Uri uri) - { - return uri.AbsoluteUri; - } - - public static Uri ToUri(String s) - { - if (String.IsNullOrEmpty(s)) - { - return null; - } - else - { - return new Uri(s); - } - } - - public static T EnumFromXmlText(XmlReader reader) - { - String s = StringFromXmlText(reader); - s = s.Replace(' ', ','); - return (T)Enum.Parse(typeof(T), s, true); - } - - public static void EnumToXmlText(XmlWriter writer, String ignored, T value) - { - String s = Enum.Format(typeof(T), value, "G"); - s = s.Replace(",", ""); - writer.WriteString(s); - } - - public static void EnumToXmlAttribute(XmlWriter writer, String attr, T value) - { - String s = Enum.Format(typeof(T), value, "G"); - s = s.Replace(",", ""); - writer.WriteAttributeString(attr, s); - } - - public static T EnumFromXmlAttribute(XmlReader reader) - { - String s = StringFromXmlAttribute(reader); - s = s.Replace(' ', ','); - return (T)Enum.Parse(typeof(T), s, true); - } - - public static void EnumToXmlElement(XmlWriter writer, String element, T value) - { - String s = Enum.Format(typeof(T), value, "G"); - s = s.Replace(",", ""); - writer.WriteElementString(element, s); - } - - public static T EnumFromXmlElement(XmlReader reader) - { - String s = StringFromXmlElement(reader); - s = s.Replace(' ', ','); - return (T)Enum.Parse(typeof(T), s, true); - } - - public static T[] ArrayOfObjectFromXml( - XmlReader reader, - String arrayElementName, - Boolean inline, - Func objectFromXmlElement) - { - return ArrayOfObjectFromXml(null, reader, arrayElementName, inline, (x, y) => objectFromXmlElement(y)); - } - - public static T[] ArrayOfObjectFromXml( - IServiceProvider serviceProvider, - XmlReader reader, - String arrayElementName, - Boolean inline, - Func objectFromXmlElement) - { - List list = new List(); - bool empty = reader.IsEmptyElement; - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - if (!inline) - { - reader.Read(); - } - - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element && (!inline || reader.Name == arrayElementName)) - { - if (reader.HasAttributes && reader.GetAttribute("nil", "http://www.w3.org/2001/XMLSchema-instance") == "true") - { - list.Add(default(T)); - reader.Read(); - } - else - { - list.Add(objectFromXmlElement(serviceProvider, reader)); - } - } - reader.ReadEndElement(); - } - return list.ToArray(); - } - - /// - /// Writes an array of objects to xml using the provided callback function to serialize individual objects - /// within the array. - /// - /// The type of objects contained in the array - /// The xml writer for serialization - /// The array to be serialized - /// The name of the array root element - /// The name of the array elements - /// True if the array elements should be written inline, or false to create the root node - /// True if an empty array should be serialized, false to omit empty arrays - /// A callback function for serializing an individual array element - public static void ArrayOfObjectToXml( - XmlWriter writer, - T[] array, - String arrayName, - String arrayElementName, - Boolean inline, - Boolean allowEmptyArrays, - Action objectToXmlElement) - { - if (array == null) - { - return; - } - - if (array.Length == 0) - { - if (allowEmptyArrays && !String.IsNullOrEmpty(arrayName)) - { - writer.WriteStartElement(arrayName); - writer.WriteEndElement(); - } - return; - } - - if (!inline) - { - writer.WriteStartElement(arrayName); - - for (Int32 i = 0; i < array.Length; i = i + 1) - { - if (array[i] == null) - { - writer.WriteStartElement(arrayElementName); - writer.WriteAttributeString("nil", "http://www.w3.org/2001/XMLSchema-instance", "true"); - writer.WriteEndElement(); - } - else - { - objectToXmlElement(writer, arrayElementName, array[i]); - } - } - writer.WriteEndElement(); - } - else - { - for (Int32 i = 0; i < array.Length; i = i + 1) - { - if (array[i] == null) - { - writer.WriteStartElement(arrayElementName); - writer.WriteAttributeString("nil", "http://www.w3.org/2001/XMLSchema-instance", "true"); - writer.WriteEndElement(); - } - else - { - objectToXmlElement(writer, arrayElementName, array[i]); - } - } - } - } - - /// - /// Writes an System.Collections.Generic.IEnumerable<T> of objects to xml using the provided - /// callback function to serialize individual objects. - /// - /// The type of objects contained in the array - /// The xml writer for serialization - /// The array to be serialized - /// The name of the array root element - /// The name of the array elements - /// True if the array elements should be written inline, or false to create the root node - /// True if an empty array should be serialized, false to omit empty arrays - /// A callback function for serializing an individual array element - public static void EnumerableOfObjectToXml( - XmlWriter writer, - IEnumerable enumerable, - String arrayName, - String arrayElementName, - Boolean inline, - Boolean allowEmptyArrays, - Action objectToXmlElement) - { - // Optionally omit zero-length enumerables to save bandwidth - if (enumerable == null) - { - return; - } - - if (!enumerable.Any()) - { - if (allowEmptyArrays && !String.IsNullOrEmpty(arrayName)) - { - writer.WriteStartElement(arrayName); - writer.WriteEndElement(); - } - return; - } - - if (!inline) - { - writer.WriteStartElement(arrayName); - - foreach (T item in enumerable) - { - if (item == null) - { - writer.WriteStartElement(arrayElementName); - writer.WriteAttributeString("nil", "http://www.w3.org/2001/XMLSchema-instance", "true"); - writer.WriteEndElement(); - } - else - { - objectToXmlElement(writer, arrayElementName, item); - } - } - writer.WriteEndElement(); - } - else - { - foreach (T item in enumerable) - { - if (item == null) - { - writer.WriteStartElement(arrayElementName); - writer.WriteAttributeString("nil", "http://www.w3.org/2001/XMLSchema-instance", "true"); - writer.WriteEndElement(); - } - else - { - objectToXmlElement(writer, arrayElementName, item); - } - } - } - } - - public static Boolean BooleanFromXmlElement(XmlReader reader) - { - return XmlConvert.ToBoolean(StringFromXmlElement(reader)); - } - - public static Byte ByteFromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToByte(StringFromXmlAttribute(reader)); - } - - public static Byte ByteFromXmlElement(XmlReader reader) - { - return XmlConvert.ToByte(StringFromXmlElement(reader)); - } - - public static Char CharFromXmlAttribute(XmlReader reader) - { - return (Char)XmlConvert.ToInt32(StringFromXmlAttribute(reader)); - } - - public static Char CharFromXmlElement(XmlReader reader) - { - return (Char)XmlConvert.ToInt32(StringFromXmlElement(reader)); - } - - public static Double DoubleFromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToDouble(StringFromXmlAttribute(reader)); - } - - public static Double DoubleFromXmlElement(XmlReader reader) - { - return XmlConvert.ToDouble(StringFromXmlElement(reader)); - } - - public static Guid GuidFromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToGuid(StringFromXmlAttribute(reader)); - } - - public static Guid GuidFromXmlElement(XmlReader reader) - { - return XmlConvert.ToGuid(StringFromXmlElement(reader)); - } - - public static Int16 Int16FromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToInt16(StringFromXmlAttribute(reader)); - } - - public static Int16 Int16FromXmlElement(XmlReader reader) - { - return XmlConvert.ToInt16(StringFromXmlElement(reader)); - } - - public static Int32 Int32FromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToInt32(StringFromXmlAttribute(reader)); - } - - public static Int32 Int32FromXmlElement(XmlReader reader) - { - return XmlConvert.ToInt32(StringFromXmlElement(reader)); - } - - public static Int64 Int64FromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToInt64(StringFromXmlAttribute(reader)); - } - - public static Int64 Int64FromXmlElement(XmlReader reader) - { - return XmlConvert.ToInt64(StringFromXmlElement(reader)); - } - - public static Single SingleFromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToSingle(StringFromXmlAttribute(reader)); - } - - public static Single SingleFromXmlElement(XmlReader reader) - { - return XmlConvert.ToSingle(StringFromXmlElement(reader)); - } - - public static String StringFromXmlAttribute(XmlReader reader) - { - return GetCachedString(reader.Value); - } - - public static String StringFromXmlElement(XmlReader reader) - { - String str = String.Empty; - Boolean isEmpty = reader.IsEmptyElement; - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - reader.Read(); - if (!isEmpty) - { - // We don't expect the server to send back a CDATA section, but the client OM - // may use the FromXml methods to read a hand-edited xml file. - if (reader.NodeType == XmlNodeType.CDATA || - reader.NodeType == XmlNodeType.Text || - reader.NodeType == XmlNodeType.Whitespace) - { - str = GetCachedString(reader.ReadContentAsString().Replace("\n", "\r\n")); - reader.ReadEndElement(); - } - else if (reader.NodeType == XmlNodeType.EndElement) - { - // in the case where the element is empty/whitespace such as , we need to read past the end element - reader.ReadEndElement(); - } - } - - return str; - } - - public static String StringFromXmlText(XmlReader reader) - { - String str = String.Empty; - if (reader.NodeType == XmlNodeType.CDATA || - reader.NodeType == XmlNodeType.Text || - reader.NodeType == XmlNodeType.Whitespace) - { - str = GetCachedString(reader.ReadContentAsString().Replace("\n", "\r\n")); - } - return str; - } - - public static TimeSpan TimeSpanFromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToTimeSpan(StringFromXmlAttribute(reader)); - } - - public static TimeSpan TimeSpanFromXmlElement(XmlReader reader) - { - return XmlConvert.ToTimeSpan(StringFromXmlElement(reader)); - } - - public static UInt16 UInt16FromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToUInt16(StringFromXmlAttribute(reader)); - } - - public static UInt16 UInt16FromXmlElement(XmlReader reader) - { - return XmlConvert.ToUInt16(StringFromXmlElement(reader)); - } - - public static UInt32 UInt32FromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToUInt32(StringFromXmlAttribute(reader)); - } - - public static UInt32 UInt32FromXmlElement(XmlReader reader) - { - return XmlConvert.ToUInt32(StringFromXmlElement(reader)); - } - - public static UInt64 UInt64FromXmlAttribute(XmlReader reader) - { - return XmlConvert.ToUInt64(StringFromXmlAttribute(reader)); - } - - public static UInt64 UInt64FromXmlElement(XmlReader reader) - { - return XmlConvert.ToUInt64(StringFromXmlElement(reader)); - } - - public static Uri UriFromXmlAttribute(XmlReader reader) - { - return ToUri(StringFromXmlAttribute(reader)); - } - - public static Uri UriFromXmlElement(XmlReader reader) - { - return ToUri(StringFromXmlElement(reader)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Boolean value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Byte value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Char value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString((Int32)value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Double value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Guid value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Int16 value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Int32 value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Int64 value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Single value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, String value) - { - StringToXmlAttribute(writer, name, value); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, TimeSpan value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, UInt16 value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, UInt32 value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, UInt64 value) - { - StringToXmlAttribute(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlAttribute(XmlWriter writer, String name, Uri value) - { - StringToXmlAttribute(writer, name, ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Boolean value) - { - StringToXmlElement(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Byte value) - { - StringToXmlElement(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Char value) - { - StringToXmlElement(writer, name, XmlConvert.ToString((Int32)value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Double value) - { - StringToXmlElement(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Guid value) - { - StringToXmlElement(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String element, Int16 value) - { - StringToXmlElement(writer, element, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String element, Int32 value) - { - StringToXmlElement(writer, element, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String element, Int64 value) - { - StringToXmlElement(writer, element, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Single value) - { - StringToXmlElement(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, String value) - { - StringToXmlElement(writer, name, value); - } - - public static void ToXmlElement(XmlWriter writer, String name, TimeSpan value) - { - StringToXmlElement(writer, name, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String element, UInt16 value) - { - StringToXmlElement(writer, element, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String element, UInt32 value) - { - StringToXmlElement(writer, element, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String element, UInt64 value) - { - StringToXmlElement(writer, element, XmlConvert.ToString(value)); - } - - public static void ToXmlElement(XmlWriter writer, String name, Uri value) - { - StringToXmlElement(writer, name, ToString(value)); - } - - public static void StringToXmlAttribute(XmlWriter writer, String name, String value) - { - writer.WriteAttributeString(name, value); - } - - public static void StringToXmlElement(XmlWriter writer, String name, String value) - { - try - { - writer.WriteElementString(name, value); - } - catch (ArgumentException e) - { - Debug.Assert(e.Message.IndexOf("invalid character", StringComparison.OrdinalIgnoreCase) > 0, "Unexpected exception: " + e.ToString()); - throw new VssServiceException(CommonResources.StringContainsIllegalChars(), e); - } - } - - public static void StringToXmlText(XmlWriter writer, String str) - { - if (str == null) - { - return; - } - - try - { - writer.WriteString(str); - } - catch (ArgumentException e) - { - Debug.Assert(e.Message.IndexOf("invalid character", StringComparison.OrdinalIgnoreCase) > 0, "Unexpected exception: " + e.ToString()); - throw new VssServiceException(CommonResources.StringContainsIllegalChars(), e); - } - } - - public static byte[] ArrayOfByteFromXml(XmlReader reader) - { - String str = StringFromXmlElement(reader); - if (str != null) - { - return Convert.FromBase64String(str); - } - return ZeroLengthArrayOfByte; - } - - public static byte[] ArrayOfByteFromXmlAttribute(XmlReader reader) - { - if (reader.Value.Length != 0) - { - return Convert.FromBase64String(reader.Value); - } - return ZeroLengthArrayOfByte; - } - - public static byte[] ZeroLengthArrayOfByte - { - get - { - if (s_zeroLengthArrayOfByte == null) - { - s_zeroLengthArrayOfByte = new byte[0]; - } - return s_zeroLengthArrayOfByte; - } - } - - public static bool CompareXmlDocuments(string xml1, string xml2) - { - if (xml1 == xml2) - { - return true; - } - else if (string.IsNullOrEmpty(xml1) || string.IsNullOrEmpty(xml2)) - { - return false; - } - - XDocument x1 = XDocument.Parse(xml1); - XDocument x2 = XDocument.Parse(xml2); - - return Compare(x1?.Root, x2?.Root); - } - - private static bool Compare(XContainer x1, XContainer x2) - { - if (object.ReferenceEquals(x1, x2)) - { - return true; - } - - XElement e1 = x1 as XElement; - XElement e2 = x2 as XElement; - - if (e1 != null && e2 != null) - { - if (!VssStringComparer.XmlNodeName.Equals(e1.Name.ToString(), e2.Name.ToString()) || - !e1.Attributes().OrderBy(a => a.Name.ToString()).SequenceEqual(e2.Attributes().OrderBy(a => a.Name.ToString()), s_xmlAttributeComparer) || - !VssStringComparer.XmlElement.Equals(e1.Value, e2.Value)) - { - return false; - } - - return x1.Elements().OrderBy(xe => xe.Name.ToString()).SequenceEqual(x2.Elements().OrderBy(xe => xe.Name.ToString()), s_xmlElementComparer); - } - - return false; - } - - #region GetCachedString - - /// - /// Strings are often duplicated in the XML returned by the server. To - /// reduce the number of identical String instances, we keep a small - /// cache of the last N strings to be deserialized off the wire. - /// - /// Send your deserialized strings through this method. If they match a - /// recently deserialized string, the cached value will be returned and - /// your deserialized string will be left in Gen0 for easy collection. - /// - private static String GetCachedString(String fromXml) - { - if (null == fromXml) - { - return null; - } - - int fromXmlLength = fromXml.Length; - - // Don't cache large strings. They take a lot longer to compare. - if (fromXmlLength > 256) - { - return fromXml; - } - - if (fromXmlLength == 0) - { - return String.Empty; - } - - String[] stringList = ts_stringList; - - // Set up the thread-static data structures if they have not yet - // been initialized. - if (null == stringList) - { - stringList = new String[c_stringCacheSize]; - ts_stringList = stringList; - } - - // Check for a cache hit. - for (int i = 0; i < c_stringCacheSize; i++) - { - String cachedString = stringList[i]; - - if (null == cachedString) - { - break; - } - - // If the lengths or first characters are different, this - // is not a hit. - if (cachedString.Length != fromXmlLength || - fromXml[0] != cachedString[0]) - { - continue; - } - - // If the strings are 6 characters or longer, check the character - // 5 characters from the end. Remember at this point we know the - // strings are identical in length. - if (fromXmlLength > 5 && - fromXml[fromXmlLength - 5] != cachedString[fromXmlLength - 5]) - { - continue; - } - - // OK, looks like a potential hit, let's verify with String.Equals. - if (String.Equals(fromXml, cachedString, StringComparison.Ordinal)) - { - // This is a cache hit. Move it to the 0 position and shove - // everything else down. - for (int j = i - 1; j >= 0; j--) - { - stringList[j + 1] = stringList[j]; - } - - stringList[0] = cachedString; - - return cachedString; - } - } - - // This is a cache miss. Evict the nth position, move everything else - // down, and insert this at the 0 position. - for (int i = c_stringCacheSize - 2; i >= 0; i--) - { - stringList[i + 1] = stringList[i]; - } - - stringList[0] = fromXml; - - return fromXml; - } - - [ThreadStatic] - private static String[] ts_stringList; - - // Size of the cache. Larger values mean more memory savings - // but more time spent in GetCachedString. - private const int c_stringCacheSize = 16; - - #endregion GetCachedString - - private class AttributeComparer : IEqualityComparer - { - public bool Equals(XAttribute x, XAttribute y) - { - if (x == y) - { - return true; - } - - if (x == null || y == null) - { - return false; - } - - return VssStringComparer.XmlAttributeName.Equals(x.Name.ToString(), y.Name.ToString()) && - VssStringComparer.XmlAttributeValue.Equals(x.Value, y.Value); - } - - public int GetHashCode(XAttribute obj) - { - if (obj == null) - { - return 0; - } - return obj.GetHashCode(); - } - } - - private class ElementComparer : IEqualityComparer - { - public bool Equals(XElement x, XElement y) - { - if (x == y) - { - return true; - } - if (x == null || y == null) - { - return false; - } - return XmlUtility.Compare(x, y); - } - - public int GetHashCode(XElement obj) - { - if (obj == null) - { - return 0; - } - return obj.GetHashCode(); - } - } - - private static byte[] s_zeroLengthArrayOfByte; - private static readonly AttributeComparer s_xmlAttributeComparer = new AttributeComparer(); - private static readonly ElementComparer s_xmlElementComparer = new ElementComparer(); - } - - /// - /// XML element writer class that automatically makes the closing WriteEndElement call - /// during dispose. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public class XmlElementWriterUtility : IDisposable - { - private XmlWriter m_xmlWriter; - - /// - /// Constructor. - /// - public XmlElementWriterUtility(string elementName, XmlWriter xmlWriter) - { - m_xmlWriter = xmlWriter; - m_xmlWriter.WriteStartElement(elementName); - } - - /// - /// Dispose. - /// - public void Dispose() - { - m_xmlWriter.WriteEndElement(); - } - } -} diff --git a/src/Sdk/Common/Common/VssCommonConstants.cs b/src/Sdk/Common/Common/VssCommonConstants.cs deleted file mode 100644 index 7de2e3fb9..000000000 --- a/src/Sdk/Common/Common/VssCommonConstants.cs +++ /dev/null @@ -1,1054 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; - -namespace GitHub.Services.Common -{ - public static class AdminConstants - { - /// - /// Each incoming web request is assigned a server process id, this constant defines - /// an element within the Context.Items[] to hold that value. - /// - public const String ServerProcessID = "serverProcessID"; - public const String ApplicationName = "ApplicationName"; - } - - [GenerateSpecificConstants] - public static class IdentityConstants - { - static IdentityConstants() - { - // For the normalization of incoming IdentityType strings. - // This is an optimization; it is not required that any particular IdentityType values - // appear in this list, but it helps performance to have common values here - var identityTypeMap = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { IdentityConstants.WindowsType, IdentityConstants.WindowsType }, - { IdentityConstants.TeamFoundationType, IdentityConstants.TeamFoundationType }, - { IdentityConstants.ClaimsType, IdentityConstants.ClaimsType }, - { IdentityConstants.BindPendingIdentityType, IdentityConstants.BindPendingIdentityType }, - { IdentityConstants.UnauthenticatedIdentityType, IdentityConstants.UnauthenticatedIdentityType }, - { IdentityConstants.ServiceIdentityType, IdentityConstants.ServiceIdentityType }, - { IdentityConstants.AggregateIdentityType, IdentityConstants.AggregateIdentityType }, - { IdentityConstants.ServerTestIdentity, IdentityConstants.ServerTestIdentity }, - { IdentityConstants.ImportedIdentityType, IdentityConstants.ImportedIdentityType }, - { IdentityConstants.GroupScopeType, IdentityConstants.GroupScopeType }, - { IdentityConstants.CspPartnerIdentityType, IdentityConstants.CspPartnerIdentityType }, - { IdentityConstants.System_ServicePrincipal, IdentityConstants.System_ServicePrincipal }, - { IdentityConstants.System_License, IdentityConstants.System_License }, - { IdentityConstants.System_Scope, IdentityConstants.System_Scope }, - { IdentityConstants.PermissionLevelDefinitionType, IdentityConstants.PermissionLevelDefinitionType} - }; - - IdentityTypeMap = identityTypeMap; - } - - public const string WindowsType = "System.Security.Principal.WindowsIdentity"; // hard coding to make PCL compliant. typeof(WindowsIdentity).FullName - public const string TeamFoundationType = "GitHub.Identity"; - public const string ClaimsType = "Microsoft.IdentityModel.Claims.ClaimsIdentity"; - // In WIF 4.5, Microsoft.IdentityModel.Claims.ClaimsIdentity was moved to System.Security.Claims namespace - [EditorBrowsable(EditorBrowsableState.Never)] - public const string Wif45ClaimsIdentityType = "System.Security.Claims.ClaimsIdentity"; - public const string AlternateLoginType = "GitHub.Services.Cloud.AlternateLoginIdentity"; - public const string BindPendingIdentityType = "GitHub.BindPendingIdentity"; - public const string ServerTestIdentity = "GitHub.Services.Identity.ServerTestIdentity"; - public const string UnauthenticatedIdentityType = "GitHub.UnauthenticatedIdentity"; - public const string ServiceIdentityType = "GitHub.ServiceIdentity"; - public const string AggregateIdentityType = "GitHub.AggregateIdentity"; - public const string ImportedIdentityType = "GitHub.ImportedIdentity"; - public const string UnknownIdentityType = "GitHub.Services.Identity.UnknownIdentity"; - public const string CspPartnerIdentityType = "GitHub.Claims.CspPartnerIdentity"; - public const string PermissionLevelDefinitionType = "GitHub.Services.PermissionLevel.PermissionLevelIdentity"; - - // this is used to represent scopes in the new Graph Rest Api - public const string GroupScopeType = "GitHub.Services.Graph.GraphScope"; - - // These are used with the System Subject Store - public const string SystemPrefix = "System:"; - public const string System_ServicePrincipal = SystemPrefix + "ServicePrincipal"; - public const string System_WellKnownGroup = SystemPrefix + "WellKnownGroup"; - public const string System_License = SystemPrefix + "License"; - public const string System_Scope = SystemPrefix + "Scope"; - public const string System_CspPartner = SystemPrefix + "CspPartner"; - public const string System_PublicAccess = SystemPrefix + "PublicAccess"; - - // This is used to convey an ACE via an IdentityDescriptor - public const string System_AccessControl = SystemPrefix + "AccessControl"; - - public const int MaxIdLength = 256; - public const int MaxTypeLength = 128; - public const byte UnknownIdentityTypeId = byte.MaxValue; - - // Social type for identity - public const byte UnknownSocialTypeId = byte.MaxValue; - - /// - /// Special value for the unique user ID for active (non-deleted) users. - /// - public const int ActiveUniqueId = 0; - - /// - /// Value of attribute that denotes whether user or group. - /// - public const string SchemaClassGroup = "Group"; - public const string SchemaClassUser = "User"; - - public const string BindPendingSidPrefix = "upn:"; - [GenerateConstant] - public const string MsaDomain = "Windows Live ID"; - [GenerateConstant] - public const string GitHubDomain = "github.com"; - public const string DomainQualifiedAccountNameFormat = "{0}\\{1}"; - public const string MsaSidSuffix = "@Live.com"; - public const string AadOidPrefix = "oid:"; - public const string FrameworkIdentityIdentifierDelimiter = ":"; - public const string IdentityDescriptorPartsSeparator = ";"; - public const string IdentityMinimumResourceVersion = "IdentityMinimumResourceVersion"; - public const int DefaultMinimumResourceVersion = -1; - public const char DomainAccountNameSeparator = '\\'; - public const bool DefaultUseAccountNameAsDirectoryAlias = true; - - /// - /// Values used in switch_hint query parameter to force sign in with personal or work account - /// - public const string SwitchHintQueryKey = "switch_hint"; - public const char SwitchToPersonal = 'P'; - public const char SwitchToWork = 'W'; - - public const string AllowNonServiceIdentitiesInDeploymentAdminsGroup = - nameof(AllowNonServiceIdentitiesInDeploymentAdminsGroup); - - /// - /// The DB layer only supports byte, even though the data layer contracts suggests a - /// 32-bit integer. Note: changing this constant implies that every new identity object - /// that is created, going forward will have this resource version set. Existing identites - /// will need to be updated to the current resource version level manually. - /// - /// This is created for rolling out of a feature based on identity not service host. - /// This value must be greater than 0. Otherwise, IMS won't update tbl_identityextension for - /// identity extended properties. - /// - public const byte DefaultResourceVersion = 2; - - // Identity ResourceVersions - [Obsolete] - public const byte ScopeManifestIssuance = 2; - [Obsolete] - public const byte ScopeManifestEnforcementWithInitialGrace = 3; - [Obsolete] - public const byte ScopeManifestEnforcementWithoutInitialGrace = 4; - - /// - /// The Global scope, [SERVER], represents the highest group Scope ID in the given request context. - /// For example, [SERVER] at a Deployment context would represent the deployment Scope ID. When - /// using the global scope in a search, a search for [SERVER]\Team Foundation Administrators - /// at the deployment level would return the deployment administrators group, while the same call - /// at the Application host level would return the Account Administrators group. The search will - /// not recurse down into sub-scopes. - /// - /// [SERVER] is a deprecated concept, introduced before TFS 2010. We recommend using either the - /// collection name in square brackets (i.e. [DefaultCollection] or the scope ID in square brackets - /// (i.e. [SCOPE_GUID]) instead. - /// - public const string GlobalScope = "[SERVER]"; - - public static readonly Guid LinkedId = new Guid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"); - - public static class EtwIdentityProviderName - { - public const string Aad = nameof(Aad); - public const string Msa = nameof(Msa); - public const string Vsts = nameof(Vsts); - } - - public static class EtwIdentityCategory - { - public const string AuthenticatedIdentity = nameof(AuthenticatedIdentity); - public const string UnauthenticatedIdentity = nameof(UnauthenticatedIdentity); - public const string ServiceIdentity = nameof(ServiceIdentity); - public const string UnexpectedIdentityType = nameof(UnexpectedIdentityType); - } - - public static readonly IReadOnlyDictionary IdentityTypeMap; - } - - /// - /// Common attributes tags used in the collection of properties of TeamFoundationIdentity. - /// - public static class IdentityAttributeTags - { - public const string WildCard = "*"; - - public const string AccountName = "Account"; - public const string Alias = "Alias"; - public const string CrossProject = "CrossProject"; - public const string Description = "Description"; - public const string Disambiguation = "Disambiguation"; - public const string DistinguishedName = "DN"; - public const string Domain = "Domain"; - public const string GlobalScope = "GlobalScope"; - public const string MailAddress = "Mail"; - public const string RestrictedVisible = "RestrictedVisible"; - public const string SchemaClassName = "SchemaClassName"; - public const string ScopeName = "ScopeName"; - public const string SecurityGroup = "SecurityGroup"; - public const string SpecialType = "SpecialType"; - public const string ScopeId = "ScopeId"; - public const string ScopeType = "ScopeType"; - public const string LocalScopeId = "LocalScopeId"; - public const string SecuringHostId = "SecuringHostId"; - public const string VirtualPlugin = "VirtualPlugin"; - public const string ProviderDisplayName = "ProviderDisplayName"; - public const string IsGroupDeleted = "IsGroupDeleted"; - - public const string Cuid = "CUID"; - public const string CuidState = "CUIDState"; - public const string Puid = "PUID"; - public const string Oid = "http://schemas.microsoft.com/identity/claims/objectidentifier"; - public const string ConsumerPuid = "ConsumerPUID"; - public const string ComplianceValidated = "ComplianceValidated"; - public const string AuthenticationCredentialValidFrom = "AuthenticationCredentialValidFrom"; - public const string MetadataUpdateDate = "MetadataUpdateDate"; - public const string DirectoryAlias = "DirectoryAlias"; - public const string CacheMaxAge = "CacheMaxAge"; - // temporary used in the ServiceIdentity and CspIdentity - public const string ServiceStorageKey = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid"; - public const string ProvData = "prov_data"; - - public const string AadRefreshToken = "vss:AadRefreshToken"; - public const string AadRefreshTokenUpdated = "GitHub.Aad.AadRefreshTokenUpdateDate"; - public const string AadUserPrincipalName = "AadUserPrincipalName"; - public const string AcsIdentityProvider = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"; - public const string AadIdentityProvider = "http://schemas.microsoft.com/identity/claims/identityprovider"; - public const string IdentityProviderClaim = "http://schemas.microsoft.com/teamfoundationserver/2010/12/claims/identityprovider"; - public const string NameIdentifierClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"; - public const string TenantIdentifierClaim = "http://schemas.microsoft.com/identity/claims/tenantid"; - public const string AadTenantDisambiguationClaim = "tenant_disambiguate"; - public const string AadMsaPassthroughClaim = "msapt"; - public const string AppidClaim = "appid"; - - public const string IdentityTypeClaim = "IdentityTypeClaim"; - public const string IsClientClaim = "IsClient"; - - // tbl_IdentityExtension properties. No longer stored in PropertyService - public const string ConfirmedNotificationAddress = "ConfirmedNotificationAddress"; - public const string CustomNotificationAddresses = "CustomNotificationAddresses"; - public const string IsDeletedInOrigin = "IsDeletedInOrigin"; - - // Extended properties, currently used only for Group images - public const string ImageId = "GitHub.Identity.Image.Id"; - public const string ImageData = @"GitHub.Identity.Image.Data"; - public const string ImageType = @"GitHub.Identity.Image.Type"; - public const string ImageUploadDate = @"GitHub.Identity.Image.UploadDate"; - public const string CandidateImageData = @"GitHub.Identity.CandidateImage.Data"; - public const string CandidateImageUploadDate = @"GitHub.Identity.CandidateImage.UploadDate"; - - // Extended Properties used On Prem - public const string LastAccessedTime = "LastAccessedTime"; - - // Extended Property used by Profile to get the MasterId of an identity. - // DO NOT USE without consulting with and getting permission from the - // Identity team. This is a bad pattern that we are currently supporting - // for compat with Profile, and the whole concept of MasterIds may be - // changing with our Sharding work. - public const string UserId = "UserId"; - - // Obsolete extended properties, which should be removed with the next major version (whichever version follows Dev15/TFS 2017) - [Obsolete] public const string EmailConfirmationSendDates = "EmailConfirmationSendDates"; - [Obsolete] public const string MsdnLicense = "MSDNLicense"; - [Obsolete] public const string BasicAuthPwdKey = "GitHub.Identity.BasicAuthPwd"; - [Obsolete] public const string BasicAuthSaltKey = "GitHub.Identity.BasicAuthSalt"; - [Obsolete] public const string BasicAuthAlgorithm = "Microsoft.TeaFoundation.Identity.BasicAuthAlgorithm"; - [Obsolete] public const string BasicAuthFailures = "Microsoft.TeaFoundation.Identity.BasicAuthFailures"; - [Obsolete] public const string BasicAuthDisabled = "Microsoft.TeaFoundation.Identity.BasicAuthDisabled"; - [Obsolete] public const string BasicAuthPasswordChanges = "GitHub.Identity.BasicAuthSettingsChanges"; - - - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "When the target .NET framework is revisioned to 4, change return to ISet")] - public static readonly HashSet ReadOnlyProperties = new HashSet( - new[] - { - AccountName, - Alias, - ComplianceValidated, - CrossProject, - Description, - Disambiguation, - DistinguishedName, - Domain, - GlobalScope, - MailAddress, - RestrictedVisible, - SchemaClassName, - ScopeName, - SecurityGroup, - SpecialType, - ScopeId, - ScopeType, - LocalScopeId, - SecuringHostId, - Cuid, - CuidState, - Puid, - VirtualPlugin, - Oid, - AcsIdentityProvider, - AadIdentityProvider, - AadTenantDisambiguationClaim, - AadMsaPassthroughClaim, - IdentityProviderClaim, - NameIdentifierClaim, - IsClientClaim, - UserId, - CacheMaxAge, - IsGroupDeleted, - }, - StringComparer.OrdinalIgnoreCase - ); - - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "When the target .NET framework is revisioned to 4, change return to ISet")] - public static readonly HashSet GroupReadOnlyProperties = new HashSet( - new[] - { - Alias, - ComplianceValidated, - CrossProject, - Disambiguation, - DistinguishedName, - Domain, - GlobalScope, - MailAddress, - RestrictedVisible, - SchemaClassName, - ScopeName, - SecurityGroup, - SpecialType, - ScopeId, - ScopeType, - LocalScopeId, - SecuringHostId, - Cuid, - CuidState, - Puid, - VirtualPlugin, - Oid, - AcsIdentityProvider, - AadIdentityProvider, - AadTenantDisambiguationClaim, - AadMsaPassthroughClaim, - IdentityProviderClaim, - NameIdentifierClaim, - IsClientClaim, - UserId, - CacheMaxAge, - IsGroupDeleted, - }, - StringComparer.OrdinalIgnoreCase - ); - - [Obsolete] - public static readonly ISet WhiteListedProperties = new HashSet(StringComparer.OrdinalIgnoreCase); - } - - public static class DirectoryRoleConstants - { - /// Name of the directory role that represents "Company Administrator/Global Admin" - public const string CompanyAdministrator = "Company Administrator"; - } - - // Used with Registration entries - [GenerateSpecificConstants] - public static class ToolNames - { - public const string Framework = "Framework"; - [GenerateConstant] - public const string VersionControl = "VersionControl"; - [GenerateConstant] - public const string WorkItemTracking = "WorkItemTracking"; - [GenerateConstant] - public const string RemoteWorkItemTracking = "RemoteWorkItemTracking"; - public const string CoreServices = "vstfs"; - public const string Warehouse = "Reports"; - [GenerateConstant] - public const string TeamBuild = "Build"; - public const string ProxyServer = "ps"; - public const string TeamFoundation = "vstfs"; - public const string SharePoint = "Wss"; - [GenerateConstant] - public const string TestManagement = "TestManagement"; - public const string LabManagement = "LabManagement"; - public const string ReleaseManagement = "ReleaseManagement"; - public const string SyncService = "SyncService"; - public const string TestRig = "TestRig"; - public const string TSWebAccess = "TSWebAccess"; - public const string ProjectServer = "ProjectServer"; - public const string DeploymentRig = "DeploymentRig"; - public const string TeamProjects = "TeamProjects"; // contains specific project registration entries (project portal, process guidance and doc url) - public const string Discussion = "Discussion"; - [GenerateConstant] - public const string Requirements = "Requirements"; - [GenerateConstant] - public const string Hyperlink = "Hyperlink"; - public const string Classification = "Classification"; - [GenerateConstant] - public const string Legacy = "Legacy"; - [GenerateConstant] - public const string CodeSense = "CodeSense"; - [GenerateConstant] - public const string Git = "Git"; - [GenerateConstant] - public const string CodeReview = "CodeReview"; - [GenerateConstant] - public const string ProjectDownload = "ProjectDownload"; - public const string DistributedTask = "DistributedTask"; - [GenerateConstant] - public const string Wiki = "Wiki"; - - public const string Search = "Search"; - [GenerateConstant] - public const string GitHub = "GitHub"; - } - - // Artifact types - [GenerateSpecificConstants] - public static class ArtifactTypeNames - { - public const string Project = "TeamProject"; - public const string Node = "Node"; - public const string Collector = "Collector"; - public const string TestResult = "TestResult"; - [GenerateConstant] - public const string TcmResult = "TcmResult"; - [GenerateConstant] - public const string TcmResultAttachment = "TcmResultAttachment"; - [GenerateConstant] - public const string TcmTest = "TcmTest"; - [GenerateConstant] - public const string Build = "Build"; - public const string BuildAgent = "Agent"; - public const string BuildDefinition = "Definition"; - public const string BuildController = "Controller"; - public const string BuildGroup = "Group"; - public const string BuildRequest = "Request"; - public const string BuildServiceHost = "ServiceHost"; - [GenerateConstant] - public const string VersionedItem = "VersionedItem"; - [GenerateConstant] - public const string LatestItemVersion = "LatestItemVersion"; - [GenerateConstant] - public const string Changeset = "Changeset"; - public const string Label = "Label"; - [GenerateConstant] - public const string Shelveset = "Shelveset"; - public const string ShelvedItem = "ShelvedItem"; - [GenerateConstant] - public const string WorkItem = "WorkItem"; - public const string Query = "Query"; - public const string Results = "Results"; - public const string LabEnvironment = "LabEnvironment"; - public const string LabTemplate = "LabTemplate"; - public const string LabSystem = "LabSystem"; - public const string TeamProjectHostGroup = "TeamProjectHostGroup"; - public const string TeamProjectLibraryShare = "TeamProjectLibraryShare"; - public const string TeamProjectCollectionLibraryShare = "TeamProjectCollectionLibraryShare"; - public const string TeamProjectCollectionHostGroup = "TeamProjectCollectionHostGroup"; - public const string TestMachine = "TestMachine"; - [GenerateConstant] - public const string Storyboard = "Storyboard"; - [GenerateConstant] - public const string Commit = "Commit"; - public const string LaunchLatestVersionedItem = "LaunchLatestVersionedItem"; - [GenerateConstant] - public const string CodeReviewId = "CodeReviewId"; - [GenerateConstant] - public const string CodeReviewSdkId = "ReviewId"; - [GenerateConstant] - public const string PullRequestId = "PullRequestId"; - [GenerateConstant] - public const string ProjectDownloadProject = "Project"; - /// - /// A Git Ref - /// - [GenerateConstant] - public const string Ref = "Ref"; - - public const string TaskAgentPoolMaintenance = "PoolMaintenance"; - [GenerateConstant] - public const string WikiPage = "WikiPage"; - - // GitHub - [GenerateConstant] - public const string PullRequest = "PullRequest"; - [GenerateConstant] - public const string Issue = "Issue"; - } - - /// - /// Constant strings used in Notifications - /// - public static class NotificationConstants - { - /// - /// Macro used in subscriptions which will be replaced by the project name when evaluated - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.MyProjectNameMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String MyProjectNameMacro = "@@MyProjectName@@"; - - /// - /// Macro used in subscriptions which will be replaced by the subscriber's Display Name when evaluated - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.MyDisplayNameMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String MyDisplayNameMacro = "@@MyDisplayName@@"; - - /// - /// Macro used in subscriptions which will be replaced by the subscriber's Unique User Name when evaluated - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.MyUniqueNameMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String MyUniqueNameMacro = "@@MyUniqueName@@"; - - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.SingleQuoteNameMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String SingleQuoteNameMacro = "@@SQBDQ@@"; //SingleQuoteBetweenDoubleQuotes - - [Obsolete] - public const String SingleQuoteValue = "\"'\""; //"'" - - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.DoubleQuoteNameMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String DoubleQuoteNameMacro = "@@DQBSQ@@"; //DoubleQuoteBetweenSingleQuotes - - [Obsolete] - public const String DoubleQuoteValue = "'\"'"; //'"' - - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.SingleQuoteCharMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String SingleQuoteCharMacro = "@@SingleQuote@@"; - - [Obsolete] - public const String SingleQuoteCharValue = "'"; - - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.DoubleQuoteCharMacro in assembly MS.VS.Services.Notifications.WebApi")] - public const String DoubleQuoteCharMacro = "@@DoubleQuote@@"; - - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.DoubleQuoteCharValue in assembly MS.VS.Services.Notifications.WebApi")] - public const String DoubleQuoteCharValue = "\""; - - /// - /// Token used in subscription addresses to identify dynamic delivery targets computed from the source event - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.DynamicTargetsToken in assembly MS.VS.Services.Notifications.WebApi")] - public const String DynamicTargetsToken = "@@"; - - /// - /// TeamFoundationIdentity property name for a user's custom list of Email addresses to receive notifications at - /// - public const String CustomNotificationAddressesIdentityProperty = "CustomNotificationAddresses"; - - /// - /// TeamFoundationIdentity propery name for a user's confirmed Email address to receive notifications. This is used in Hosted environments only. - /// - public const string ConfirmedNotificationAddressIdentityProperty = "ConfirmedNotificationAddress"; - - /// - /// The name of the WorkItemChangedEvent - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.WorkItemChangedEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const string WorkItemChangedEventTypeName = "WorkItemChangedEvent"; - - /// - /// The name of the BuildStatusChangedEvent type - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.BuildStatusChangeEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const String BuildStatusChangeEventName = "BuildStatusChangeEvent"; - - /// - /// The name of the BuildCompletedEvent type - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.BuildCompletedEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const String BuildCompletedEventName = "BuildCompletedEvent"; - - /// - /// The name of the CheckinEvent type - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.CheckinEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const String CheckinEventName = "CheckinEvent"; - - /// - /// The name of the CodeReviewChangedEvent type - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.CodeReviewChangedEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const String CodeReviewChangedEventName = "CodeReviewChangedEvent"; - - /// - /// The name of the GitPushEvent type - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.GitPushEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const String GitPushEventName = "GitPushEvent"; - - /// - /// The name of the GitPullRequestEvent type - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.LegacyNames.GitPullRequestEvent in assembly MS.VS.Services.Notifications.WebApi")] - public const String GitPullRequestEventName = "GitPullRequestEvent"; - - /// - /// The relative path to the alerts admin web page - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationUrlConstants.AlertsPageRelativePath in assembly MS.VS.Services.Notifications.WebApi")] - public const String AlertsPageRelativePath = "{0}#id={1}&showteams={2}"; - - /// - /// The alerts page name - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationUrlConstants.AlertsPage in assembly MS.VS.Services.Notifications.WebApi")] - public const String AlertsPage = "_Alerts"; - - /// - /// The admin alerts page - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationUrlConstants.AlertsAdminPage in assembly MS.VS.Services.Notifications.WebApi")] - public const String AlertsAdminPage = "_admin/_Alerts"; - - /// - /// Property used to keep track of how many confirmations were sent for this user. Used to limit the number - /// of confirmations a single user is allowed to send out for their account. - /// The value is updated and monitored by the SendEmailConfirmationJob. - /// - public const string EmailConfirmationSendDates = "EmailConfirmationSendDates"; - - /// - /// Prefix to denote that identity field value have been processed - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.ProcessedFlagCharacter in assembly MS.VS.Services.Notifications.WebApi")] - public const Char ProcessedFlagCharacter = (Char)7; - - /// - /// Prefix to denote that identity field value have been processed and converted to TFID - /// - /// [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.ProcessedTfIdFlagCharacter in assembly MS.VS.Services.Notifications.WebApi")] - public const Char ProcessedTfIdFlagCharacter = (Char)11; - - /// - /// Prefix to denote that this is the start of displayname value for this identity field - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.DisplayNameFlagCharacter in assembly MS.VS.Services.Notifications.WebApi")] - public const Char DisplayNameFlagCharacter = '|'; - - /// - /// Prefix to denote that this is the start of TFID value for this identity field - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.TfIdFlagCharacter in assembly MS.VS.Services.Notifications.WebApi")] - public const Char TfIdFlagCharacter = '%'; - - /// - /// Optional Feature flag to enable escaping Regex expressions when creating Notification subscriptions. - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.FeatureFlags.AllowUserRegexInMatchConditionFeatureFlag in assembly MS.VS.Services.Notifications.WebApi")] - public const string AllowUserRegexInMatchConditionFeatureFlag = "VisualStudio.Services.Notifications.AllowUserRegexInMatchCondition"; - - /// - /// The MDM scope name for the notification job - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.MDMNotificationJobScope in assembly MS.VS.Services.Notifications.WebApi")] - public const string MDMNotificationJobScope = "NotificationJob"; - - /// - /// Event processing delay KPI name - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.EventProcessingDelayKPI in assembly MS.VS.Services.Notifications.WebApi")] - public const string EventProcessingDelayKPI = "EventProcessingDelayInMs"; - - /// - /// Event processing delay KPI description - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.EventProcessingDelayKPIDesc in assembly MS.VS.Services.Notifications.WebApi")] - public const string EventProcessingDelayKPIDesc = "Time taken to start processing an event"; - - /// - /// The MDM scope name for the delivery job - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.MDMDeliveryJobscope in assembly MS.VS.Services.Notifications.WebApi")] - public const string MDMDeliveryJobscope = "NotificationDeliveryJob"; - - /// - /// Notification delivery delay KPI name - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.DeliveryDelayKPI in assembly MS.VS.Services.Notifications.WebApi")] - public const string DeliveryDelayKPI = "NotificationDeliveryDelayInMs"; - - /// - /// Notification delivery delay with retries KPI name - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.DeliveryDelayWithRetriesKPI in assembly MS.VS.Services.Notifications.WebApi")] - public const string DeliveryDelayWithRetriesKPI = "NotificationDeliveryDelayWithRetriesInMs"; - - /// - /// Total time taken between the event creation till the notification delivery - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.TotalProcessingTimeKPI in assembly MS.VS.Services.Notifications.WebApi")] - public const string TotalProcessingTimeKPI = "EventProcessingTimeInMs"; - - /// - /// Total time taken between the event creation till the notification delivery - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.TotalProcessingTimeWithRetriesKPI in assembly MS.VS.Services.Notifications.WebApi")] - public const string TotalProcessingTimeWithRetriesKPI = "EventProcessingTimeWithRetriesInMs"; - - /// - /// Notification delivery delay KPI description - /// - [Obsolete("Moved to GitHub.Services.Notifications.Common.MDMConstants.DeliveryDelayKPIDesc in assembly MS.VS.Services.Notifications.WebApi")] - public const string DeliveryDelayKPIDesc = "Time taken to start deliverying a notification"; - - // caching key for our notification bridge interface - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.BridgeKey in assembly MS.VS.Services.Notifications.WebApi")] - public const String BridgeKey = "@NotifBridge"; - - // delivery retry count registryKey - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.RetryCountRegistryKey in assembly MS.VS.Services.Notifications.WebApi")] - public const string RetryCountRegistryKey = "NotificationRetryCount"; - - // delivery retry count default value - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.RetryCountDefaultValue in assembly MS.VS.Services.Notifications.WebApi")] - public const Int32 RetryCountDefaultValue = 5; - - // the collection scope Guid - [Obsolete("Moved to GitHub.Services.Notifications.Common.NotificationFrameworkConstants.CollectionScope in assembly MS.VS.Services.Notifications.WebApi")] - public static Guid CollectionScope = new Guid("00000000-0000-636f-6c6c-656374696f6e"); - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public class LocationSecurityConstants - { - public static readonly Guid NamespaceId = new Guid("2725D2BC-7520-4AF4-B0E3-8D876494731F"); - public static readonly Char PathSeparator = '/'; - public static readonly string NamespaceRootToken = PathSeparator.ToString(); - public static readonly string ServiceDefinitionsToken = String.Concat(NamespaceRootToken, "ServiceDefinitions"); - public static readonly string AccessMappingsToken = String.Concat(NamespaceRootToken, "AccessMappings"); - - // Read for ServiceDefinitions and AccessMappings - public const Int32 Read = 1; - // Create/Update/Delete for ServiceDefinitions and AccessMappings - public const Int32 Write = 2; - public const Int32 AllPermissions = Read | Write; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public class SecuritySecurityConstants - { - public static readonly Guid NamespaceId = new Guid("9A82C708-BFBE-4F31-984C-E860C2196781"); - public const char Separator = '/'; - public const String RootToken = ""; - - public const int Read = 1; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public class GraphSecurityConstants - { - public static readonly Guid NamespaceId = new Guid("C2EE56C9-E8FA-4CDD-9D48-2C44F697A58E"); - public static readonly string RefsToken = "Refs"; - public static readonly string SubjectsToken = "Subjects"; - - public const int ReadByPublicIdentifier = 1; - public const int ReadByPersonalIdentifier = 2; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static class TeamProjectSecurityConstants - { - public static readonly Guid NamespaceId = new Guid("52D39943-CB85-4d7f-8FA8-C6BAAC873819"); - - // Existed in Orcas - public static readonly Int32 GenericRead = 1; - public static readonly Int32 GenericWrite = 2; - public static readonly Int32 Delete = 4; - public static readonly Int32 PublishTestResults = 8; - public static readonly Int32 AdministerBuild = 16; - public static readonly Int32 StartBuild = 32; - public static readonly Int32 EditBuildStatus = 64; - public static readonly Int32 UpdateBuild = 128; - public static readonly Int32 DeleteTestResults = 256; - public static readonly Int32 ViewTestResults = 512; - - // Dev10 Beta1 - public static readonly Int32 ManageTestEnvironments = 2048; - - // Dev10 Beta2 - public static readonly Int32 ManageTestConfigurations = 4096; - - // Dev14 Update 2 / VSO (M91) - public static readonly Int32 WorkItemDelete = 8192; - - // Dev14 Update 2 / VSO (M92) - public static readonly Int32 WorkItemMove = 16384; - - // Dev14 Update 2 / VSO (M94) - public static readonly Int32 WorkItemPermanentlyDelete = 32768; - - // Dev15 / VSO (M99) - public static readonly Int32 Rename = 65536; - - /// - /// The permission required for setting project properties. - /// Introduced in Dev15 Update 2 / VSO (M116). - /// - public static readonly Int32 ManageProperties = 131072; - - /// - /// The permission required for setting system project properties. - /// Introduced in Dev15 Update 2 / VSO (M116). - /// - /// - /// This permission was excluded from AllPermissions to avoid being unintentionally granted. - /// - public static readonly Int32 ManageSystemProperties = 262144; - - /// - /// The permission required for bypassing the project property cache. - /// Introduced in Dev16 / VSO (M118). - /// - /// - /// This permission was excluded from AllPermissions to avoid being unintentionally granted. - /// - public static readonly Int32 BypassPropertyCache = 524288; - - /// - /// The permission required for bypassing the rules while updating work items. - /// Introduced in Dev16 / VSO (M126). - /// - public static readonly Int32 BypassRules= 1048576; - - /// - /// The permission required for suppressing notifications for work item updates. - /// Introduced in Dev16 / VSO (M126). - /// - public static readonly Int32 SuppressNotifications= 2097152; - - /// - /// The permission required for updating project visibility. - /// Introduced in Dev16 / VSO (M131). - /// - public static readonly Int32 UpdateVisibility = 4194304; - - /// - /// The permission required for changing the process of the team project - /// Introduced in Dev17 / VSO (M136). - /// - public static readonly Int32 ChangeProjectsProcess = 8388608; - - /// - /// The permission required for granting access to backlog management. For stakeholder, this would disabled for private project and enabled for public project. - /// Introduced in Dev17 / VSO (M137). - /// - /// - /// This permission was excluded from AllPermissions to avoid being unintentionally granted. - /// - public static readonly Int32 AgileToolsBacklogManagement = 16777216; - - /// - /// The permission required for granting access to backlog management. For stakeholder, this is always disabled. - /// Introduced in Dev17 / VSO (M150). - /// - /// - /// This permission was excluded from AllPermissions to avoid being unintentionally granted. - /// - public static readonly Int32 AgileToolsPlans = 33554432; - - public static readonly Int32 AllPermissions = - GenericRead | - GenericWrite | - Delete | - PublishTestResults | - AdministerBuild | - StartBuild | - EditBuildStatus | - UpdateBuild | - DeleteTestResults | - ViewTestResults | - ManageTestEnvironments | - ManageTestConfigurations | - WorkItemDelete | - WorkItemMove | - WorkItemPermanentlyDelete | - Rename | - ManageProperties | - BypassRules | - SuppressNotifications | - UpdateVisibility | - ChangeProjectsProcess; - - public const String ProjectTokenPrefix = "$PROJECT:"; - - public static String GetToken(String projectUri) - { - if (String.IsNullOrEmpty(projectUri) || !projectUri.StartsWith(ProjectTokenPrefix, StringComparison.OrdinalIgnoreCase)) - { - if (projectUri == null) - { - projectUri = String.Empty; - } - - return ProjectTokenPrefix + projectUri + ":"; - } - - return projectUri + ":"; - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static class ContentValidationSecurityConstants - { - public static readonly Guid NamespaceId = new Guid("B1982126-CB90-4479-BDFD-CBF193241CB8"); - public static readonly string ViolationsToken = "Violations"; - - public const int Read = 1; - public const int Write = 2; - } - - public enum WinHttpErrorCode - { - WINHTTP_ERROR_BASE = 12000, - WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 188, - - ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1, - ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2, - ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4, - ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5, - ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6, - ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7, - ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9, - ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11, - ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12, - ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15, - ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17, - ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18, - ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19, - ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29, - ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30, - ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32, - ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37, - ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38, - ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44, - ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45, - ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57, - ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100, - ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101, - ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102, - ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103, - ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150, - ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152, - ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153, - ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154, - ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155, - ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156, - ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157, - ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166, - ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167, - ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169, - ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170, - ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172, - ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175, - ERROR_WINHTTP_UNHANDLED_SCRIPT_TYPE = WINHTTP_ERROR_BASE + 176, - ERROR_WINHTTP_SCRIPT_EXECUTION_ERROR = WINHTTP_ERROR_BASE + 177, - ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178, - ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179, - ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180, - ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181, - ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182, - ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183, - ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184, - ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185, - ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186, - ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED_PROXY = WINHTTP_ERROR_BASE + 187, - ERROR_WINHTTP_SECURE_FAILURE_PROXY = WINHTTP_ERROR_BASE + 188 - } - - public enum CurlErrorCode - { - CURLE_OK = 0, - CURLE_UNSUPPORTED_PROTOCOL = 1, - CURLE_FAILED_INIT = 2, - CURLE_URL_MALFORMAT = 3, - CURLE_NOT_BUILT_IN = 4, - CURLE_COULDNT_RESOLVE_PROXY = 5, - CURLE_COULDNT_RESOLVE_HOST = 6, - CURLE_COULDNT_CONNECT = 7, - CURLE_FTP_WEIRD_SERVER_REPLY = 8, - CURLE_REMOTE_ACCESS_DENIED = 9, - CURLE_FTP_ACCEPT_FAILED = 10, - CURLE_FTP_WEIRD_PASS_REPLY = 11, - CURLE_FTP_ACCEPT_TIMEOUT = 12, - CURLE_FTP_WEIRD_PASV_REPLY = 13, - CURLE_FTP_WEIRD_227_FORMAT = 14, - CURLE_FTP_CANT_GET_HOST = 15, - CURLE_HTTP2 = 16, - CURLE_FTP_COULDNT_SET_TYPE = 17, - CURLE_PARTIAL_FILE = 18, - CURLE_FTP_COULDNT_RETR_FILE = 19, - CURLE_QUOTE_ERROR = 21, - CURLE_HTTP_RETURNED_ERROR = 22, - CURLE_WRITE_ERROR = 23, - CURLE_UPLOAD_FAILED = 25, - CURLE_READ_ERROR = 26, - CURLE_OUT_OF_MEMORY = 27, - CURLE_OPERATION_TIMEDOUT = 28, - CURLE_FTP_PORT_FAILED = 30, - CURLE_FTP_COULDNT_USE_REST = 31, - CURLE_RANGE_ERROR = 33, - CURLE_HTTP_POST_ERROR = 34, - CURLE_SSL_CONNECT_ERROR = 35, - CURLE_BAD_DOWNLOAD_RESUME = 36, - CURLE_FILE_COULDNT_READ_FILE = 37, - CURLE_LDAP_CANNOT_BIND = 38, - CURLE_LDAP_SEARCH_FAILED = 39, - CURLE_FUNCTION_NOT_FOUND = 41, - CURLE_ABORTED_BY_CALLBACK = 42, - CURLE_BAD_FUNCTION_ARGUMENT = 43, - CURLE_INTERFACE_FAILED = 45, - CURLE_TOO_MANY_REDIRECTS = 47, - CURLE_UNKNOWN_OPTION = 48, - CURLE_TELNET_OPTION_SYNTAX = 49, - CURLE_PEER_FAILED_VERIFICATION = 51, - CURLE_GOT_NOTHING = 52, - CURLE_SSL_ENGINE_NOTFOUND = 53, - CURLE_SSL_ENGINE_SETFAILED = 54, - CURLE_SEND_ERROR = 55, - CURLE_RECV_ERROR = 56, - CURLE_SSL_CERTPROBLEM = 58, - CURLE_SSL_CIPHER = 59, - CURLE_SSL_CACERT = 60, - CURLE_BAD_CONTENT_ENCODING = 61, - CURLE_LDAP_INVALID_URL = 62, - CURLE_FILESIZE_EXCEEDED = 63, - CURLE_USE_SSL_FAILED = 64, - CURLE_SEND_FAIL_REWIND = 65, - CURLE_SSL_ENGINE_INITFAILED = 66, - CURLE_LOGIN_DENIED = 67, - CURLE_TFTP_NOTFOUND = 68, - CURLE_TFTP_PERM = 69, - CURLE_REMOTE_DISK_FULL = 70, - CURLE_TFTP_ILLEGAL = 71, - CURLE_TFTP_UNKNOWNID = 72, - CURLE_REMOTE_FILE_EXISTS = 73, - CURLE_TFTP_NOSUCHUSER = 74, - CURLE_CONV_FAILED = 75, - CURLE_CONV_REQD = 76, - CURLE_SSL_CACERT_BADFILE = 77, - CURLE_REMOTE_FILE_NOT_FOUND = 78, - CURLE_SSH = 79, - CURLE_SSL_SHUTDOWN_FAILED = 80, - CURLE_AGAIN = 81, - CURLE_SSL_CRL_BADFILE = 82, - CURLE_SSL_ISSUER_ERROR = 83, - CURLE_FTP_PRET_FAILED = 84, - CURLE_RTSP_CSEQ_ERROR = 85, - CURLE_RTSP_SESSION_ERROR = 86, - CURLE_FTP_BAD_FILE_LIST = 87, - CURLE_CHUNK_FAILED = 88, - CURLE_NO_CONNECTION_AVAILABLE = 89, - CURLE_SSL_PINNEDPUBKEYNOTMATCH = 90, - CURLE_SSL_INVALIDCERTSTATUS = 91, - CURLE_HTTP2_STREAM = 92, - CURLE_RECURSIVE_API_CALL = 93 - } -} diff --git a/src/Sdk/Common/Common/VssException.cs b/src/Sdk/Common/Common/VssException.cs deleted file mode 100644 index c711c0ed4..000000000 --- a/src/Sdk/Common/Common/VssException.cs +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Reflection; -using System.Runtime.Serialization; -using System.Security; - -namespace GitHub.Services.Common -{ - /// - /// Base class for all custom exceptions thrown from Vss and Tfs code. - /// - /// - /// All Exceptions in the VSS space -- any exception that flows across - /// a REST API boudary -- should derive from VssServiceException. This is likely - /// almost ALL new exceptions. Legacy TFS exceptions that do not flow through rest - /// derive from TeamFoundationServerException or TeamFoundationServiceException - /// - [Serializable] - [SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")] - [ExceptionMapping("0.0", "3.0", "VssException", "GitHub.Services.Common.VssException, GitHub.Services.Common, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public abstract class VssException : ApplicationException - { - /// - /// No-arg constructor that sumply defers to the base class. - /// - public VssException() : base() - { - } - - /// - /// Initializes an exception with the specified error message. - /// - /// Application-defined error code for this exception - public VssException(int errorCode) : this(errorCode, false) - { - } - - /// - /// Initializes an exception with the specified error message. - /// - /// Application-defined error code for this exception - /// Indicate whether this exception should be logged - public VssException(int errorCode, bool logException) - { - ErrorCode = errorCode; - LogException = logException; - } - - /// - /// Initializes an exception with the specified error message. - /// - /// A human readable message that describes the error - public VssException(string message) : base(SecretUtility.ScrubSecrets(message)) - { - } - - /// - /// Initializes an exception with the specified error message and an inner exception that caused this exception to be raised. - /// - /// A human readable message that describes the error - /// - public VssException(string message, Exception innerException) : base(SecretUtility.ScrubSecrets(message), innerException) - { - } - - /// - /// Initializes an exception with the specified error message and an inner exception that caused this exception to be raised. - /// - /// A human readable message that describes the error - /// Application defined error code - /// - public VssException(string message, int errorCode, Exception innerException) : this(message, innerException) - { - ErrorCode = errorCode; - LogException = false; - } - - /// - /// Initializes an exception with the specified error message and an inner exception that caused this exception to be raised. - /// - /// A human readable message that describes the error - /// Application defined error code - public VssException(string message, int errorCode) : this(message, errorCode, false) - { - } - - /// - /// Initializes an exception with the specified error message and an inner exception that caused this exception to be raised. - /// - /// A human readable message that describes the error - /// Application defined error code - /// Indicate whether this exception should be logged - public VssException(string message, int errorCode, bool logException) : this(message) - { - ErrorCode = errorCode; - LogException = logException; - } - - /// - /// Initializes an exception with the specified error message and an inner exception that caused this exception to be raised. - /// - /// A human readable message that describes the error - /// Application defined error code - /// - /// - public VssException(string message, int errorCode, bool logException, Exception innerException) : this(message, innerException) - { - ErrorCode = errorCode; - LogException = logException; - } - - /// - /// Initializes an exception from serialized data - /// - /// object holding the serialized data - /// context info about the source or destination - protected VssException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - LogException = (bool)info.GetValue("m_logException", typeof(bool)); - ReportException = (bool)info.GetValue("m_reportException", typeof(bool)); - ErrorCode = (int)info.GetValue("m_errorCode", typeof(int)); -#if !NETSTANDARD - LogLevel = (EventLogEntryType)info.GetValue("m_logLevel", typeof(EventLogEntryType)); -#endif - EventId = (int)info.GetValue("m_eventId", typeof(int)); - } - - [SecurityCritical] - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - info.AddValue("m_logException", LogException); - info.AddValue("m_reportException", ReportException); - info.AddValue("m_errorCode", ErrorCode); -#if !NETSTANDARD - info.AddValue("m_logLevel", LogLevel); -#endif - info.AddValue("m_eventId", EventId); - } - - /// Indicate whether this exception instance should be logged - /// True (false) if the exception should (should not) be logged - public bool LogException - { - get - { - return m_logException; - } - set - { - m_logException = value; - } - } - -#if !NETSTANDARD - /// The event log entry type to use when logging the exception - /// One of the event log entry types: - public EventLogEntryType LogLevel - { - get - { - return m_logLevel; - } - set - { - m_logLevel = value; - } - } -#endif - - /// A user-defined error code. - public int ErrorCode - { - get - { - return m_errorCode; - } - set - { - m_errorCode = value; - } - } - - /// The event ID to report if the exception is marked for the event log - /// The event ID used in the entry added to the event log - public int EventId - { - get - { - return m_eventId; - } - set - { - m_eventId = value; - } - } - - /// Indicate whether the exception should be reported through Dr. Watson - /// True (false) if the exception should (should not) be reported - public bool ReportException - { - get - { - return m_reportException; - } - set - { - m_reportException = value; - } - } - - /// - /// Gets the default serialized type name and type key for the given exception type. - /// - internal static void GetTypeNameAndKeyForExceptionType(Type exceptionType, Version restApiVersion, out String typeName, out String typeKey) - { - typeName = null; - typeKey = exceptionType.Name; - if (restApiVersion != null) - { - IEnumerable exceptionAttributes = exceptionType.GetTypeInfo().GetCustomAttributes().Where(ea => ea.MinApiVersion <= restApiVersion && ea.ExclusiveMaxApiVersion > restApiVersion); - if (exceptionAttributes.Any()) - { - ExceptionMappingAttribute exceptionAttribute = exceptionAttributes.First(); - typeName = exceptionAttribute.TypeName; - typeKey = exceptionAttribute.TypeKey; - } - else if (restApiVersion < s_backCompatExclusiveMaxVersion) //if restApiVersion < 3 we send the assembly qualified name with the current binary version switched out to 14 - { - typeName = GetBackCompatAssemblyQualifiedName(exceptionType); - } - } - - if (typeName == null) - { - - AssemblyName asmName = exceptionType.GetTypeInfo().Assembly.GetName(); - if (asmName != null) - { - //going forward we send "FullName" and simple assembly name which includes no version. - typeName = exceptionType.FullName + ", " + asmName.Name; - } - else - { - String assemblyString = exceptionType.GetTypeInfo().Assembly.FullName; - assemblyString = assemblyString.Substring(0, assemblyString.IndexOf(',')); - typeName = exceptionType.FullName + ", " + assemblyString; - } - } - } - - internal static String GetBackCompatAssemblyQualifiedName(Type type) - { - AssemblyName current = type.GetTypeInfo().Assembly.GetName(); - if (current != null) - { - AssemblyName old = current; - old.Version = new Version(c_backCompatVersion, 0, 0, 0); - return Assembly.CreateQualifiedName(old.ToString(), type.FullName); - } - else - { - //this is probably not necessary... - return type.AssemblyQualifiedName.Replace(c_currentAssemblyMajorVersionString, c_backCompatVersionString); - } - } - - private const String c_currentAssemblyMajorVersionString = "Version=" + GeneratedVersionInfo.AssemblyMajorVersion; - private const String c_backCompatVersionString = "Version=14"; - private const int c_backCompatVersion = 14; - - private static Version s_backCompatExclusiveMaxVersion = new Version(3, 0); - private bool m_logException; - private bool m_reportException; - private int m_errorCode; - -#if !NETSTANDARD - private EventLogEntryType m_logLevel = EventLogEntryType.Warning; -#endif - - private int m_eventId = DefaultExceptionEventId; - - //From EventLog.cs in Framework. - public const int DefaultExceptionEventId = 3000; - } -} diff --git a/src/Sdk/Common/Common/VssHttpMessageHandler.cs b/src/Sdk/Common/Common/VssHttpMessageHandler.cs deleted file mode 100644 index f51c3553b..000000000 --- a/src/Sdk/Common/Common/VssHttpMessageHandler.cs +++ /dev/null @@ -1,682 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common.Diagnostics; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// Provides authentication for Visual Studio Services. - /// - public class VssHttpMessageHandler : HttpMessageHandler - { - /// - /// Initializes a new VssHttpMessageHandler instance with default credentials and request - /// settings. - /// - public VssHttpMessageHandler() - : this(new VssCredentials(), new VssHttpRequestSettings()) - { - } - - /// - /// Initializes a new VssHttpMessageHandler instance with the specified credentials and request - /// settings. - /// - /// The credentials which should be used - /// The request settings which should be used - public VssHttpMessageHandler( - VssCredentials credentials, - VssHttpRequestSettings settings) - : this(credentials, settings, -#if !NETSTANDARD - new WebRequestHandler() -#else - new HttpClientHandler() -#endif - ) - { - } - - /// - /// Initializes a new VssHttpMessageHandler instance with the specified credentials and request - /// settings. - /// - /// The credentials which should be used - /// The request settings which should be used - /// - public VssHttpMessageHandler( - VssCredentials credentials, - VssHttpRequestSettings settings, - HttpMessageHandler innerHandler) - { - this.Credentials = credentials; - this.Settings = settings; - this.ExpectContinue = settings.ExpectContinue; - - m_credentialWrapper = new CredentialWrapper(); - m_messageInvoker = new HttpMessageInvoker(innerHandler); - - // If we were given a pipeline make sure we find the inner-most handler to apply our settings as this - // will be the actual outgoing transport. - { - HttpMessageHandler transportHandler = innerHandler; - DelegatingHandler delegatingHandler = transportHandler as DelegatingHandler; - while (delegatingHandler != null) - { - transportHandler = delegatingHandler.InnerHandler; - delegatingHandler = transportHandler as DelegatingHandler; - } - - m_transportHandler = transportHandler; - } - -#if NETSTANDARD - //.Net Core does not recognize CredentialCache.DefaultCredentials if we wrap them with CredentialWrapper - bool isDefaultCredentials = credentials != null && credentials.Windows != null && credentials.Windows.UseDefaultCredentials; - ApplySettings(m_transportHandler, isDefaultCredentials ? CredentialCache.DefaultCredentials : m_credentialWrapper, this.Settings); -#else - ApplySettings(m_transportHandler, m_credentialWrapper, this.Settings); -#endif - } - - /// - /// Gets the credentials associated with this handler. - /// - public VssCredentials Credentials - { - get; - private set; - } - - /// - /// Gets the settings associated with this handler. - /// - public VssHttpRequestSettings Settings - { - get; - private set; - } - - private Boolean ExpectContinue - { - get; - set; - } - - protected override void Dispose(Boolean disposing) - { - base.Dispose(disposing); - - if (disposing) - { - if (m_messageInvoker != null) - { - m_messageInvoker.Dispose(); - } - } - } - - internal static readonly String PropertyName = "MS.VS.MessageHandler"; - - /// - /// Handles the authentication hand-shake for a Visual Studio service. - /// - /// The HTTP request message - /// The cancellation token used for cooperative cancellation - /// A new Task<HttpResponseMessage> which wraps the response from the remote service - protected override async Task SendAsync( - HttpRequestMessage request, - CancellationToken cancellationToken) - { - VssTraceActivity traceActivity = VssTraceActivity.Current; - - var traceInfo = VssHttpMessageHandlerTraceInfo.GetTraceInfo(request); - traceInfo?.TraceHandlerStartTime(); - -#if !NETSTANDARD - // This action is deferred from ApplySettings because we want don't want to do it if we aren't - // talking to an HTTPS endpoint. - if (!m_appliedClientCertificatesToTransportHandler && - request.RequestUri.Scheme == "https") - { - WebRequestHandler webRequestHandler = m_transportHandler as WebRequestHandler; - if (webRequestHandler != null && - this.Settings.ClientCertificateManager != null && - this.Settings.ClientCertificateManager.ClientCertificates != null && - this.Settings.ClientCertificateManager.ClientCertificates.Count > 0) - { - webRequestHandler.ClientCertificates.AddRange(this.Settings.ClientCertificateManager.ClientCertificates); - } - m_appliedClientCertificatesToTransportHandler = true; - } - - if (!m_appliedServerCertificateValidationCallbackToTransportHandler && - request.RequestUri.Scheme == "https") - { - WebRequestHandler webRequestHandler = m_transportHandler as WebRequestHandler; - if (webRequestHandler != null && - this.Settings.ServerCertificateValidationCallback != null) - { - webRequestHandler.ServerCertificateValidationCallback = this.Settings.ServerCertificateValidationCallback; - } - m_appliedServerCertificateValidationCallbackToTransportHandler = true; - } -#else - if (!m_appliedClientCertificatesToTransportHandler && - request.RequestUri.Scheme == "https") - { - HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler; - if (httpClientHandler != null && - this.Settings.ClientCertificateManager != null && - this.Settings.ClientCertificateManager.ClientCertificates != null && - this.Settings.ClientCertificateManager.ClientCertificates.Count > 0) - { - httpClientHandler.ClientCertificates.AddRange(this.Settings.ClientCertificateManager.ClientCertificates); - } - m_appliedClientCertificatesToTransportHandler = true; - } - - if (!m_appliedServerCertificateValidationCallbackToTransportHandler && - request.RequestUri.Scheme == "https") - { - HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler; - if (httpClientHandler != null && - this.Settings.ServerCertificateValidationCallback != null) - { - httpClientHandler.ServerCertificateCustomValidationCallback = this.Settings.ServerCertificateValidationCallback; - } - m_appliedServerCertificateValidationCallbackToTransportHandler = true; - } - - // The .NET Core 2.1 runtime switched its HTTP default from HTTP 1.1 to HTTP 2. - // This causes problems with some versions of the Curl handler on Linux. - // See GitHub issue https://github.com/dotnet/corefx/issues/32376 - if (Settings.UseHttp11) - { - request.Version = HttpVersion.Version11; - } -#endif - - IssuedToken token = null; - IssuedTokenProvider provider; - if (this.Credentials.TryGetTokenProvider(request.RequestUri, out provider)) - { - token = provider.CurrentToken; - } - - // Add ourselves to the message so the underlying token issuers may use it if necessary - request.Properties[VssHttpMessageHandler.PropertyName] = this; - - Boolean succeeded = false; - Boolean lastResponseDemandedProxyAuth = false; - Int32 retries = m_maxAuthRetries; - HttpResponseMessage response = null; - HttpResponseMessageWrapper responseWrapper; - CancellationTokenSource tokenSource = null; - - try - { - tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - - if (this.Settings.SendTimeout > TimeSpan.Zero) - { - tokenSource.CancelAfter(this.Settings.SendTimeout); - } - - do - { - if (response != null) - { - response.Dispose(); - } - - ApplyHeaders(request); - - // In the case of a Windows token, only apply it to the web proxy if it - // returned a 407 Proxy Authentication Required. If we didn't get this - // status code back, then the proxy (if there is one) is clearly working fine, - // so we shouldn't mess with its credentials. - ApplyToken(request, token, applyICredentialsToWebProxy: lastResponseDemandedProxyAuth); - lastResponseDemandedProxyAuth = false; - - // The WinHttpHandler will chunk any content that does not have a computed length which is - // not what we want. By loading into a buffer up-front we bypass this behavior and there is - // no difference in the normal HttpClientHandler behavior here since this is what they were - // already doing. - await BufferRequestContentAsync(request, tokenSource.Token).ConfigureAwait(false); - - traceInfo?.TraceBufferedRequestTime(); - - // ConfigureAwait(false) enables the continuation to be run outside any captured - // SyncronizationContext (such as ASP.NET's) which keeps things from deadlocking... - response = await m_messageInvoker.SendAsync(request, tokenSource.Token).ConfigureAwait(false); - - traceInfo?.TraceRequestSendTime(); - - // Now buffer the response content if configured to do so. In general we will be buffering - // the response content in this location, except in the few cases where the caller has - // specified HttpCompletionOption.ResponseHeadersRead. - // Trace content type in case of error - await BufferResponseContentAsync(request, response, () => $"[ContentType: {response.Content.GetType().Name}]", tokenSource.Token).ConfigureAwait(false); - - traceInfo?.TraceResponseContentTime(); - - responseWrapper = new HttpResponseMessageWrapper(response); - - if (!this.Credentials.IsAuthenticationChallenge(responseWrapper)) - { - // Validate the token after it has been successfully authenticated with the server. - if (provider != null) - { - provider.ValidateToken(token, responseWrapper); - } - - // Make sure that once we can authenticate with the service that we turn off the - // Expect100Continue behavior to increase performance. - this.ExpectContinue = false; - succeeded = true; - break; - } - else - { - // In the case of a Windows token, only apply it to the web proxy if it - // returned a 407 Proxy Authentication Required. If we didn't get this - // status code back, then the proxy (if there is one) is clearly working fine, - // so we shouldn't mess with its credentials. - lastResponseDemandedProxyAuth = responseWrapper.StatusCode == HttpStatusCode.ProxyAuthenticationRequired; - - // Invalidate the token and ensure that we have the correct token provider for the challenge - // which we just received - VssHttpEventSource.Log.AuthenticationFailed(traceActivity, response); - - if (provider != null) - { - provider.InvalidateToken(token); - } - - // Ensure we have an appropriate token provider for the current challenge - provider = this.Credentials.CreateTokenProvider(request.RequestUri, responseWrapper, token); - - // Make sure we don't invoke the provider in an invalid state - if (provider == null) - { - VssHttpEventSource.Log.IssuedTokenProviderNotFound(traceActivity); - break; - } - else if (provider.GetTokenIsInteractive && this.Credentials.PromptType == CredentialPromptType.DoNotPrompt) - { - VssHttpEventSource.Log.IssuedTokenProviderPromptRequired(traceActivity, provider); - break; - } - - // If the user has already tried once but still unauthorized, stop retrying. The main scenario for this condition - // is a user typed in a valid credentials for a hosted account but the associated identity does not have - // access. We do not want to continually prompt 3 times without telling them the failure reason. In the - // next release we should rethink about presenting user the failure and options between retries. - IEnumerable headerValues; - Boolean hasAuthenticateError = - response.Headers.TryGetValues(HttpHeaders.VssAuthenticateError, out headerValues) && - !String.IsNullOrEmpty(headerValues.FirstOrDefault()); - - if (retries == 0 || (retries < m_maxAuthRetries && hasAuthenticateError)) - { - break; - } - - // Now invoke the provider and await the result - token = await provider.GetTokenAsync(token, tokenSource.Token).ConfigureAwait(false); - - // I always see 0 here, but the method above could take more time so keep for now - traceInfo?.TraceGetTokenTime(); - - // If we just received a token, lets ask the server for the VSID - request.Headers.Add(HttpHeaders.VssUserData, String.Empty); - - retries--; - } - } - while (retries >= 0); - - if (traceInfo != null) - { - traceInfo.TokenRetries = m_maxAuthRetries - retries; - } - - // We're out of retries and the response was an auth challenge -- then the request was unauthorized - // and we will throw a strongly-typed exception with a friendly error message. - if (!succeeded && response != null && this.Credentials.IsAuthenticationChallenge(responseWrapper)) - { - String message = null; - IEnumerable serviceError; - - if (response.Headers.TryGetValues(HttpHeaders.TfsServiceError, out serviceError)) - { - message = UriUtility.UrlDecode(serviceError.FirstOrDefault()); - } - else - { - message = CommonResources.VssUnauthorized(request.RequestUri.GetLeftPart(UriPartial.Authority)); - } - - // Make sure we do not leak the response object when raising an exception - if (response != null) - { - response.Dispose(); - } - - VssHttpEventSource.Log.HttpRequestUnauthorized(traceActivity, request, message); - VssUnauthorizedException unauthorizedException = new VssUnauthorizedException(message); - - if (provider != null) - { - unauthorizedException.Data.Add(CredentialsType, provider.CredentialType); - } - - throw unauthorizedException; - } - - return response; - } - catch (OperationCanceledException ex) - { - if (cancellationToken.IsCancellationRequested) - { - VssHttpEventSource.Log.HttpRequestCancelled(traceActivity, request); - throw; - } - else - { - VssHttpEventSource.Log.HttpRequestTimedOut(traceActivity, request, this.Settings.SendTimeout); - throw new TimeoutException(CommonResources.HttpRequestTimeout(this.Settings.SendTimeout), ex); - } - } - finally - { - // We always dispose of the token source since otherwise we leak resources if there is a timer pending - if (tokenSource != null) - { - tokenSource.Dispose(); - } - - traceInfo?.TraceTrailingTime(); - } - } - - private static async Task BufferRequestContentAsync( - HttpRequestMessage request, - CancellationToken cancellationToken) - { - if (request.Content != null && - request.Headers.TransferEncodingChunked != true) - { - Int64? contentLength = request.Content.Headers.ContentLength; - if (contentLength == null) - { - await request.Content.LoadIntoBufferAsync().EnforceCancellation(cancellationToken).ConfigureAwait(false); - } - - // Explicitly turn off chunked encoding since we have computed the request content size - request.Headers.TransferEncodingChunked = false; - } - } - - protected virtual async Task BufferResponseContentAsync( - HttpRequestMessage request, - HttpResponseMessage response, - Func makeErrorMessage, - CancellationToken cancellationToken) - { - // Determine whether or not we should go ahead and buffer the output under our timeout scope. If - // we do not perform this action here there is a potential network stack hang since we override - // the HttpClient.SendTimeout value and the cancellation token for monitoring request timeout does - // not survive beyond this scope. - if (response == null || response.StatusCode == HttpStatusCode.NoContent || response.Content == null) - { - return; - } - - // Do not try to buffer with a size of 0. This forces all calls to effectively use the behavior of - // HttpCompletionOption.ResponseHeadersRead if that is desired. - if (this.Settings.MaxContentBufferSize == 0) - { - return; - } - - // Read the completion option provided by the caller. If we don't find the property then we - // assume it is OK to buffer by default. - HttpCompletionOption completionOption; - if (!request.Properties.TryGetValue(VssHttpRequestSettings.HttpCompletionOptionPropertyName, out completionOption)) - { - completionOption = HttpCompletionOption.ResponseContentRead; - } - - // If the caller specified that response content should be read then we need to go ahead and - // buffer it all up to the maximum buffer size specified by the settings. Anything larger than - // the maximum will trigger an error in the underlying stack. - if (completionOption == HttpCompletionOption.ResponseContentRead) - { - await response.Content.LoadIntoBufferAsync(this.Settings.MaxContentBufferSize).EnforceCancellation(cancellationToken, makeErrorMessage).ConfigureAwait(false); - } - } - - private void ApplyHeaders(HttpRequestMessage request) - { - if (this.Settings.ApplyTo(request)) - { - VssTraceActivity activity = request.GetActivity(); - if (activity != null && - activity != VssTraceActivity.Empty && - !request.Headers.Contains(HttpHeaders.TfsSessionHeader)) - { - request.Headers.Add(HttpHeaders.TfsSessionHeader, activity.Id.ToString("D")); - } - - request.Headers.ExpectContinue = this.ExpectContinue; - } - } - - private void ApplyToken( - HttpRequestMessage request, - IssuedToken token, - bool applyICredentialsToWebProxy = false) - { - if (token == null) - { - return; - } - - ICredentials credentialsToken = token as ICredentials; - if (credentialsToken != null) - { - if (applyICredentialsToWebProxy) - { - HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler; - - if (httpClientHandler != null && - httpClientHandler.Proxy != null) - { - httpClientHandler.Proxy.Credentials = credentialsToken; - } - } - - m_credentialWrapper.InnerCredentials = credentialsToken; - } - else - { - token.ApplyTo(new HttpRequestMessageWrapper(request)); - } - } - - private static void ApplySettings( - HttpMessageHandler handler, - ICredentials defaultCredentials, - VssHttpRequestSettings settings) - { - HttpClientHandler httpClientHandler = handler as HttpClientHandler; - if (httpClientHandler != null) - { - httpClientHandler.AllowAutoRedirect = settings.AllowAutoRedirect; - httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual; - //Setting httpClientHandler.UseDefaultCredentials to false in .Net Core, clears httpClientHandler.Credentials if - //credentials is already set to defaultcredentials. Therefore httpClientHandler.Credentials must be - //set after httpClientHandler.UseDefaultCredentials. - httpClientHandler.UseDefaultCredentials = false; - httpClientHandler.Credentials = defaultCredentials; - httpClientHandler.PreAuthenticate = false; - httpClientHandler.Proxy = DefaultWebProxy; - httpClientHandler.UseCookies = false; - httpClientHandler.UseProxy = true; - - if (settings.CompressionEnabled) - { - httpClientHandler.AutomaticDecompression = DecompressionMethods.GZip; - } - } - } - - private static IWebProxy s_defaultWebProxy = -#if !NETSTANDARD - WebRequest.DefaultWebProxy; -#else - // setting this to WebRequest.DefaultWebProxy in NETSTANDARD is causing a System.PlatformNotSupportedException - //.in System.Net.SystemWebProxy.IsBypassed. Comment in IsBypassed method indicates ".NET Core and .NET Native - // code will handle this exception and call into WinInet/WinHttp as appropriate to use the system proxy." - // This needs to be investigated further. - null; -#endif - - /// - /// Allows you to set a proxy to be used by all VssHttpMessageHandler requests without affecting the global WebRequest.DefaultWebProxy. If not set it returns the WebRequest.DefaultWebProxy. - /// - public static IWebProxy DefaultWebProxy - { - get - { - var toReturn = WebProxyWrapper.Wrap(s_defaultWebProxy); - - if (null != toReturn && - toReturn.Credentials == null) - { - toReturn.Credentials = CredentialCache.DefaultCredentials; - } - - return toReturn; - } - set - { - // requested by Insights team to be able to set a default Proxy that only affects this handler. - // see following bug for details: https://mseng.visualstudio.com/DefaultCollection/VSOnline/_workitems#_a=edit&id=425575&triage=true - s_defaultWebProxy = value; - } - } - - internal const String CredentialsType = nameof(CredentialsType); - - private const Int32 m_maxAuthRetries = 3; - private HttpMessageInvoker m_messageInvoker; - private CredentialWrapper m_credentialWrapper; - private bool m_appliedClientCertificatesToTransportHandler; - private bool m_appliedServerCertificateValidationCallbackToTransportHandler; - private readonly HttpMessageHandler m_transportHandler; - -#if NETSTANDARD - //.Net Core does not attempt NTLM schema on Linux, unless ICredentials is a CredentialCache instance - //This workaround may not be needed after this corefx fix is consumed: https://github.com/dotnet/corefx/pull/7923 - private sealed class CredentialWrapper : CredentialCache, ICredentials -#else - private sealed class CredentialWrapper : ICredentials -#endif - { - public ICredentials InnerCredentials - { - get; - set; - } - - NetworkCredential ICredentials.GetCredential( - Uri uri, - String authType) - { - return InnerCredentials != null ? InnerCredentials.GetCredential(uri, authType) : null; - } - } - - private sealed class WebProxyWrapper : IWebProxy - { - private WebProxyWrapper(IWebProxy toWrap) - { - m_wrapped = toWrap; - m_credentials = null; - } - - public static WebProxyWrapper Wrap(IWebProxy toWrap) - { - if (null == toWrap) - { - return null; - } - - return new WebProxyWrapper(toWrap); - } - - public ICredentials Credentials - { - get - { - ICredentials credentials = m_credentials; - - if (null == credentials) - { - // This means to fall back to the Credentials from the wrapped - // IWebProxy. - credentials = m_wrapped.Credentials; - } - else if (Object.ReferenceEquals(credentials, m_nullCredentials)) - { - // This sentinel value means we have explicitly had our credentials - // set to null. - credentials = null; - } - - return credentials; - } - - set - { - if (null == value) - { - // Use this as a sentinel value to distinguish the case when someone has - // explicitly set our credentials to null. We don't want to fall back to - // m_wrapped.Credentials when we have credentials that are explicitly null. - m_credentials = m_nullCredentials; - } - else - { - m_credentials = value; - } - } - } - - public Uri GetProxy(Uri destination) - { - return m_wrapped.GetProxy(destination); - } - - public bool IsBypassed(Uri host) - { - return m_wrapped.IsBypassed(host); - } - - private readonly IWebProxy m_wrapped; - private ICredentials m_credentials; - - private static readonly ICredentials m_nullCredentials = new CredentialWrapper(); - } - } -} diff --git a/src/Sdk/Common/Common/VssHttpMessageHandlerTraceInfo.cs b/src/Sdk/Common/Common/VssHttpMessageHandlerTraceInfo.cs deleted file mode 100644 index 3b5d63af6..000000000 --- a/src/Sdk/Common/Common/VssHttpMessageHandlerTraceInfo.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using System.Net.Http; - -namespace GitHub.Services.Common -{ - /// - /// This class is used by the message handler, if injected as a request property, to trace additional - /// timing details for outgoing requests. This information is added to the HttpOutgoingRequest logs - /// - public class VssHttpMessageHandlerTraceInfo - { - DateTime _lastTime; - - static readonly String TfsTraceInfoKey = "TFS_TraceInfo"; - - public int TokenRetries { get; internal set; } - - public TimeSpan HandlerStartTime { get; private set; } - public TimeSpan BufferedRequestTime { get; private set; } - public TimeSpan RequestSendTime { get; private set; } - public TimeSpan ResponseContentTime { get; private set; } - public TimeSpan GetTokenTime { get; private set; } - public TimeSpan TrailingTime { get; private set; } - - public VssHttpMessageHandlerTraceInfo() - { - _lastTime = DateTime.UtcNow; - } - - internal void TraceHandlerStartTime() - { - var previous = _lastTime; - _lastTime = DateTime.UtcNow; - HandlerStartTime += (_lastTime - previous); - } - - internal void TraceBufferedRequestTime() - { - var previous = _lastTime; - _lastTime = DateTime.UtcNow; - BufferedRequestTime += (_lastTime - previous); - } - - internal void TraceRequestSendTime() - { - var previous = _lastTime; - _lastTime = DateTime.UtcNow; - RequestSendTime += (_lastTime - previous); - } - - internal void TraceResponseContentTime() - { - var previous = _lastTime; - _lastTime = DateTime.UtcNow; - ResponseContentTime += (_lastTime - previous); - } - - internal void TraceGetTokenTime() - { - var previous = _lastTime; - _lastTime = DateTime.UtcNow; - GetTokenTime += (_lastTime - previous); - } - - internal void TraceTrailingTime() - { - var previous = _lastTime; - _lastTime = DateTime.UtcNow; - TrailingTime += (_lastTime - previous); - } - - /// - /// Set the provided traceInfo as a property on a request message (if not already set) - /// - /// - /// - public static void SetTraceInfo(HttpRequestMessage message, VssHttpMessageHandlerTraceInfo traceInfo) - { - object existingTraceInfo; - if (!message.Properties.TryGetValue(TfsTraceInfoKey, out existingTraceInfo)) - { - message.Properties.Add(TfsTraceInfoKey, traceInfo); - } - } - - /// - /// Get VssHttpMessageHandlerTraceInfo from request message, or return null if none found - /// - /// - /// - public static VssHttpMessageHandlerTraceInfo GetTraceInfo(HttpRequestMessage message) - { - VssHttpMessageHandlerTraceInfo traceInfo = null; - - if (message.Properties.TryGetValue(TfsTraceInfoKey, out object traceInfoObject)) - { - traceInfo = traceInfoObject as VssHttpMessageHandlerTraceInfo; - } - - return traceInfo; - } - - public override string ToString() - { - return $"R:{TokenRetries}, HS:{HandlerStartTime.Ticks}, BR:{BufferedRequestTime.Ticks}, RS:{RequestSendTime.Ticks}, RC:{ResponseContentTime.Ticks}, GT:{GetTokenTime.Ticks}, TT={TrailingTime.Ticks}"; - } - } - -} diff --git a/src/Sdk/Common/Common/VssHttpRequestSettings.cs b/src/Sdk/Common/Common/VssHttpRequestSettings.cs deleted file mode 100644 index 18f4c26d6..000000000 --- a/src/Sdk/Common/Common/VssHttpRequestSettings.cs +++ /dev/null @@ -1,416 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; - -namespace GitHub.Services.Common -{ - /// - /// Provides common settings for a VssHttpMessageHandler instance. - /// - public class VssHttpRequestSettings - { - /// - /// Initializes a new VssHttpRequestSettings instance with compression enabled. - /// - public VssHttpRequestSettings() - : this(Guid.NewGuid()) - { - } - - /// - /// Initializes a new VssHttpRequestSettings instance with compression enabled. - /// - public VssHttpRequestSettings(Guid sessionId) - { - this.AllowAutoRedirect = false; - this.CompressionEnabled = true; - this.ExpectContinue = true; - this.BypassProxyOnLocal = true; - this.MaxContentBufferSize = c_defaultContentBufferSize; - this.SendTimeout = s_defaultTimeout; - if (!String.IsNullOrEmpty(CultureInfo.CurrentUICulture.Name)) // InvariantCulture for example has an empty name. - { - this.AcceptLanguages.Add(CultureInfo.CurrentUICulture); - } - this.SessionId = sessionId; - this.SuppressFedAuthRedirects = true; - this.ClientCertificateManager = null; - this.ServerCertificateValidationCallback = null; -#if NETSTANDARD - this.UseHttp11 = false; -#endif - - // If different, we'll also add CurrentCulture to the request headers, - // but UICulture was added first, so it gets first preference - if (!CultureInfo.CurrentCulture.Equals(CultureInfo.CurrentUICulture) && !String.IsNullOrEmpty(CultureInfo.CurrentCulture.Name)) - { - this.AcceptLanguages.Add(CultureInfo.CurrentCulture); - } - - this.MaxRetryRequest = c_defaultMaxRetry; - -#if DEBUG - string customClientRequestTimeout = Environment.GetEnvironmentVariable("VSS_Client_Request_Timeout"); - if (!string.IsNullOrEmpty(customClientRequestTimeout) && int.TryParse(customClientRequestTimeout, out int customTimeout)) - { - // avoid disrupting a debug session due to the request timing out by setting a custom timeout. - this.SendTimeout = TimeSpan.FromSeconds(customTimeout); - } -#endif - } - - /// - /// Initializes a new VssHttpRequestSettings instance with compression enabled. - /// - /// The e2eId argument is not used. - [Obsolete] - [EditorBrowsable(EditorBrowsableState.Never)] - public VssHttpRequestSettings(Guid sessionId, Guid e2eId) - : this(sessionId) - { - } - - /// - /// Copy Constructor - /// - /// - protected VssHttpRequestSettings(VssHttpRequestSettings copy) - { - this.AllowAutoRedirect = copy.AllowAutoRedirect; - this.CompressionEnabled = copy.CompressionEnabled; - this.ExpectContinue = copy.ExpectContinue; - this.BypassProxyOnLocal = copy.BypassProxyOnLocal; - this.MaxContentBufferSize = copy.MaxContentBufferSize; - this.SendTimeout = copy.SendTimeout; - this.m_acceptLanguages = new List(copy.AcceptLanguages); - this.SessionId = copy.SessionId; - this.AgentId = copy.AgentId; - this.SuppressFedAuthRedirects = copy.SuppressFedAuthRedirects; - this.UserAgent = new List(copy.UserAgent); - this.OperationName = copy.OperationName; - this.ClientCertificateManager = copy.ClientCertificateManager; - this.ServerCertificateValidationCallback = copy.ServerCertificateValidationCallback; - this.MaxRetryRequest = copy.MaxRetryRequest; -#if NETSTANDARD - this.UseHttp11 = copy.UseHttp11; -#endif - } - - /// - /// Gets or sets a value indicating whether or not HttpClientHandler should follow redirect on outgoing requests. - /// - public Boolean AllowAutoRedirect - { - get; - set; - } - - /// - /// Gets or sets a value indicating whether or not compression should be used on outgoing requests. - /// The default value is true. - /// - [DefaultValue(true)] - public Boolean CompressionEnabled - { - get; - set; - } - - /// - /// Gets or sets a value indicating whether or not the Expect: 100-continue header should be sent on - /// outgoing requess. The default value is true. - /// - [DefaultValue(true)] - public Boolean ExpectContinue - { - get; - set; - } - - /// - /// Sets whether to bypass web proxies if the call is local - /// - public Boolean BypassProxyOnLocal - { - get; - set; - } - -#if NETSTANDARD - /// - /// The .NET Core 2.1 runtime switched its HTTP default from HTTP 1.1 to HTTP 2. - /// This causes problems with some versions of the Curl handler on Linux. - /// See GitHub issue https://github.com/dotnet/corefx/issues/32376 - /// If true, requests generated by this client will use HTTP 1.1. - /// - public Boolean UseHttp11 - { - get; - set; - } -#endif - - /// - /// Gets or sets the maximum size allowed for response content buffering. - /// - [DefaultValue(c_defaultContentBufferSize)] - public Int32 MaxContentBufferSize - { - get - { - return m_maxContentBufferSize; - } - set - { - ArgumentUtility.CheckForOutOfRange(value, nameof(value), 0, c_maxAllowedContentBufferSize); - m_maxContentBufferSize = value; - } - } - - /// - /// Timespan to wait before timing out a request. Defaults to 100 seconds - /// - public TimeSpan SendTimeout - { - get; - set; - } - - /// - /// Provides a hint to the server requesting that rather than getting 302 redirects as part of FedAuth flows 401 and 403 are passed through. - /// - [DefaultValue(true)] - public Boolean SuppressFedAuthRedirects - { - get; - set; - } - - /// - /// User-Agent header passed along in the request, - /// For multiple values, the order in the list is the order - /// in which they will appear in the header - /// - public List UserAgent - { - get; - set; - } - - /// - /// The name of the culture is passed in the Accept-Language header - /// - public ICollection AcceptLanguages - { - get - { - return m_acceptLanguages; - } - } - - /// - /// A unique identifier for the user session - /// - public Guid SessionId - { - get; - set; - } - - /// - /// End to End ID which gets propagated everywhere unchanged - /// - public Guid E2EId - { - get; - set; - } - - /// - /// This is a kind of combination between SessionId and UserAgent. - /// If supplied, the value should be a string that uniquely identifies - /// this application running on this particular machine. - /// The server will then use this value - /// to correlate user requests, even if the process restarts. - /// - public String AgentId - { - get; - set; - } - - /// - /// An optional string that is sent in the SessionId header used to group a set of operations together - /// - public String OperationName - { - get; - set; - } - - /// - /// Optional implementation used to gather client certificates - /// for connections that require them - /// - public IVssClientCertificateManager ClientCertificateManager - { - get; - set; - } - -#if !NETSTANDARD - /// - /// Optional implementation used to validate server certificate validation - /// - public RemoteCertificateValidationCallback ServerCertificateValidationCallback - { - get; set; - } -#else - /// - /// Optional implementation used to validate server certificate validation - /// - public Func ServerCertificateValidationCallback - { - get; - set; - } -#endif - - /// - /// Number of times to retry a request that has an ambient failure - /// - /// - /// This property is only used by VssConnection, so only relevant on the client - /// - [DefaultValue(c_defaultMaxRetry)] - public Int32 MaxRetryRequest - { - get; - set; - } - - protected internal virtual Boolean IsHostLocal(String hostName) - { - //base class always returns false. See VssClientHttpRequestSettings for override - return false; - } - - protected internal virtual Boolean ApplyTo(HttpRequestMessage request) - { - // Make sure we only apply the settings to the request once - if (request.Properties.ContainsKey(PropertyName)) - { - return false; - } - - request.Properties.Add(PropertyName, this); - - if (this.AcceptLanguages != null && this.AcceptLanguages.Count > 0) - { - // An empty or null CultureInfo name will cause an ArgumentNullException in the - // StringWithQualityHeaderValue constructor. CultureInfo.InvariantCulture is an example of - // a CultureInfo that has an empty name. - foreach (CultureInfo culture in this.AcceptLanguages.Where(a => !String.IsNullOrEmpty(a.Name))) - { - request.Headers.AcceptLanguage.Add(new StringWithQualityHeaderValue(culture.Name)); - } - } - - if (this.UserAgent != null) - { - foreach (var headerVal in this.UserAgent) - { - if (!request.Headers.UserAgent.Contains(headerVal)) - { - request.Headers.UserAgent.Add(headerVal); - } - } - } - - if (this.SuppressFedAuthRedirects) - { - request.Headers.Add(Internal.HttpHeaders.TfsFedAuthRedirect, "Suppress"); - } - - // Record the command, if we have it. Otherwise, just record the session ID. - if (!request.Headers.Contains(Internal.HttpHeaders.TfsSessionHeader)) - { - if (!String.IsNullOrEmpty(this.OperationName)) - { - request.Headers.Add(Internal.HttpHeaders.TfsSessionHeader, String.Concat(this.SessionId.ToString("D"), ", ", this.OperationName)); - } - else - { - request.Headers.Add(Internal.HttpHeaders.TfsSessionHeader, this.SessionId.ToString("D")); - } - } - - if (!String.IsNullOrEmpty(this.AgentId)) - { - request.Headers.Add(Internal.HttpHeaders.VssAgentHeader, this.AgentId); - } - -#if NETSTANDARD - // Content is being sent as chunked by default in dotnet5.4, which differs than the .net 4.5 behaviour. - if (request.Content != null && !request.Content.Headers.ContentLength.HasValue && !request.Headers.TransferEncodingChunked.HasValue) - { - request.Content.Headers.ContentLength = request.Content.ReadAsByteArrayAsync().Result.Length; - } -#endif - - return true; - } - - /// - /// Gets the encoding used for outgoing requests. - /// - public static Encoding Encoding - { - get - { - return s_encoding.Value; - } - } - - /// - /// Gets the property name used to reference this object. - /// - public const String PropertyName = "MS.VS.RequestSettings"; - - /// - /// Gets the property name used to reference the completion option for a specific request. - /// - public const String HttpCompletionOptionPropertyName = "MS.VS.HttpCompletionOption"; - - /// - /// Header to include the light weight response client option. - /// - public const string LightweightHeader = "lightweight"; - - /// - /// Header to include the exclude urls client option. - /// - public const string ExcludeUrlsHeader = "excludeUrls"; - - private Int32 m_maxContentBufferSize; - private ICollection m_acceptLanguages = new List(); - private static Lazy s_encoding = new Lazy(() => new UTF8Encoding(false), LazyThreadSafetyMode.PublicationOnly); - private static readonly TimeSpan s_defaultTimeout = TimeSpan.FromSeconds(100); //default WebAPI timeout - private const Int32 c_defaultMaxRetry = 3; - - // We will buffer a maximum of 1024MB in the message handler - private const Int32 c_maxAllowedContentBufferSize = 1024 * 1024 * 1024; - - // We will buffer, by default, up to 512MB in the message handler - private const Int32 c_defaultContentBufferSize = 1024 * 1024 * 512; - } -} diff --git a/src/Sdk/Common/Common/VssHttpRetryMessageHandler.cs b/src/Sdk/Common/Common/VssHttpRetryMessageHandler.cs deleted file mode 100644 index 69c6dacf2..000000000 --- a/src/Sdk/Common/Common/VssHttpRetryMessageHandler.cs +++ /dev/null @@ -1,232 +0,0 @@ -using GitHub.Services.Common.Diagnostics; -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Net; -using System.Net.Http; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using System.Collections.Generic; -using System.Linq; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Common -{ - /// - /// Handles automatic replay of HTTP requests when errors are encountered based on a configurable set of options. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public class VssHttpRetryMessageHandler : DelegatingHandler - { - public VssHttpRetryMessageHandler(Int32 maxRetries) - : this(new VssHttpRetryOptions { MaxRetries = maxRetries }) - { - } - - public VssHttpRetryMessageHandler(Int32 maxRetries, string clientName) - : this(new VssHttpRetryOptions { MaxRetries = maxRetries }) - { - m_clientName = clientName; - } - - public VssHttpRetryMessageHandler(VssHttpRetryOptions options) - { - m_retryOptions = options; - } - - public VssHttpRetryMessageHandler( - VssHttpRetryOptions options, - HttpMessageHandler innerHandler) - : base(innerHandler) - { - m_retryOptions = options; - } - - protected override async Task SendAsync( - HttpRequestMessage request, - CancellationToken cancellationToken) - { - Int32 attempt = 1; - HttpResponseMessage response = null; - HttpRequestException exception = null; - VssTraceActivity traceActivity = VssTraceActivity.Current; - - // Allow overriding default retry options per request - VssHttpRetryOptions retryOptions = m_retryOptions; - object retryOptionsObject; - if (request.Properties.TryGetValue(HttpRetryOptionsKey, out retryOptionsObject)) // NETSTANDARD compliant, TryGetValue is not - { - // Fallback to default options if object of unexpected type was passed - retryOptions = retryOptionsObject as VssHttpRetryOptions ?? m_retryOptions; - } - - TimeSpan minBackoff = retryOptions.MinBackoff; - Int32 maxAttempts = retryOptions.MaxRetries + 1; - - IVssHttpRetryInfo retryInfo = null; - object retryInfoObject; - if (request.Properties.TryGetValue(HttpRetryInfoKey, out retryInfoObject)) // NETSTANDARD compliant, TryGetValue is not - { - retryInfo = retryInfoObject as IVssHttpRetryInfo; - } - - if (IsLowPriority(request)) - { - // Increase the backoff and retry count, low priority requests can be retried many times if the server is busy. - minBackoff = TimeSpan.FromSeconds(minBackoff.TotalSeconds * 2); - maxAttempts = maxAttempts * 10; - } - - TimeSpan backoff = minBackoff; - - while (attempt <= maxAttempts) - { - // Reset the exception so we don't have a lingering variable - exception = null; - - Boolean canRetry = false; - SocketError? socketError = null; - HttpStatusCode? statusCode = null; - WebExceptionStatus? webExceptionStatus = null; - WinHttpErrorCode? winHttpErrorCode = null; - CurlErrorCode? curlErrorCode = null; - string afdRefInfo = null; - try - { - if (attempt == 1) - { - retryInfo?.InitialAttempt(request); - } - - response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false); - - if (attempt > 1) - { - TraceHttpRequestSucceededWithRetry(traceActivity, response, attempt); - } - - // Verify the response is successful or the status code is one that may be retried. - if (response.IsSuccessStatusCode) - { - break; - } - else - { - statusCode = response.StatusCode; - afdRefInfo = response.Headers.TryGetValues(HttpHeaders.AfdResponseRef, out var headers) ? headers.First() : null; - canRetry = m_retryOptions.IsRetryableResponse(response); - } - } - catch (HttpRequestException ex) - { - exception = ex; - canRetry = VssNetworkHelper.IsTransientNetworkException(exception, m_retryOptions, out statusCode, out webExceptionStatus, out socketError, out winHttpErrorCode, out curlErrorCode); - } - catch (TimeoutException) - { - throw; - } - - if (attempt < maxAttempts && canRetry) - { - backoff = BackoffTimerHelper.GetExponentialBackoff(attempt, minBackoff, m_retryOptions.MaxBackoff, m_retryOptions.BackoffCoefficient); - retryInfo?.Retry(backoff); - TraceHttpRequestRetrying(traceActivity, request, attempt, backoff, statusCode, webExceptionStatus, socketError, winHttpErrorCode, curlErrorCode, afdRefInfo); - } - else - { - if (attempt < maxAttempts) - { - if (exception == null) - { - TraceHttpRequestFailed(traceActivity, request, statusCode != null ? statusCode.Value : (HttpStatusCode)0, afdRefInfo); - } - else - { - TraceHttpRequestFailed(traceActivity, request, exception); - } - } - else - { - TraceHttpRequestFailedMaxAttempts(traceActivity, request, attempt, statusCode, webExceptionStatus, socketError, winHttpErrorCode, curlErrorCode, afdRefInfo); - } - break; - } - - // Make sure to dispose of this so we don't keep the connection open - if (response != null) - { - response.Dispose(); - } - - attempt++; - TraceRaw(request, 100011, TraceLevel.Error, - "{{ \"Client\":\"{0}\", \"Endpoint\":\"{1}\", \"Attempt\":{2}, \"MaxAttempts\":{3}, \"Backoff\":{4} }}", - m_clientName, - request.RequestUri.Host, - attempt, - maxAttempts, - backoff.TotalMilliseconds); - await Task.Delay(backoff, cancellationToken).ConfigureAwait(false); - } - - if (exception != null) - { - throw exception; - } - - return response; - } - - protected virtual void TraceRaw(HttpRequestMessage request, int tracepoint, TraceLevel level, string message, params object[] args) - { - // implement in Server so retries are recorded in ProductTrace - } - - protected virtual void TraceHttpRequestFailed(VssTraceActivity activity, HttpRequestMessage request, HttpStatusCode statusCode, string afdRefInfo) - { - VssHttpEventSource.Log.HttpRequestFailed(activity, request, statusCode, afdRefInfo); - } - - protected virtual void TraceHttpRequestFailed(VssTraceActivity activity, HttpRequestMessage request, Exception exception) - { - VssHttpEventSource.Log.HttpRequestFailed(activity, request, exception); - } - - protected virtual void TraceHttpRequestFailedMaxAttempts(VssTraceActivity activity, HttpRequestMessage request, Int32 attempt, HttpStatusCode? httpStatusCode, WebExceptionStatus? webExceptionStatus, SocketError? socketErrorCode, WinHttpErrorCode? winHttpErrorCode, CurlErrorCode? curlErrorCode, string afdRefInfo) - { - VssHttpEventSource.Log.HttpRequestFailedMaxAttempts(activity, request, attempt, httpStatusCode, webExceptionStatus, socketErrorCode, winHttpErrorCode, curlErrorCode, afdRefInfo); - } - - protected virtual void TraceHttpRequestSucceededWithRetry(VssTraceActivity activity, HttpResponseMessage response, Int32 attempt) - { - VssHttpEventSource.Log.HttpRequestSucceededWithRetry(activity, response, attempt); - } - - protected virtual void TraceHttpRequestRetrying(VssTraceActivity activity, HttpRequestMessage request, Int32 attempt, TimeSpan backoffDuration, HttpStatusCode? httpStatusCode, WebExceptionStatus? webExceptionStatus, SocketError? socketErrorCode, WinHttpErrorCode? winHttpErrorCode, CurlErrorCode? curlErrorCode, string afdRefInfo) - { - VssHttpEventSource.Log.HttpRequestRetrying(activity, request, attempt, backoffDuration, httpStatusCode, webExceptionStatus, socketErrorCode, winHttpErrorCode, curlErrorCode, afdRefInfo); - } - - private static bool IsLowPriority(HttpRequestMessage request) - { - bool isLowPriority = false; - - IEnumerable headers; - - if (request.Headers.TryGetValues(HttpHeaders.VssRequestPriority, out headers) && headers != null) - { - string header = headers.FirstOrDefault(); - isLowPriority = string.Equals(header, "Low", StringComparison.OrdinalIgnoreCase); - } - - return isLowPriority; - } - - private VssHttpRetryOptions m_retryOptions; - public const string HttpRetryInfoKey = "HttpRetryInfo"; - public const string HttpRetryOptionsKey = "VssHttpRetryOptions"; - private string m_clientName = ""; - } -} diff --git a/src/Sdk/Common/Common/VssHttpRetryOptions.cs b/src/Sdk/Common/Common/VssHttpRetryOptions.cs deleted file mode 100644 index 6f3b9c6cd..000000000 --- a/src/Sdk/Common/Common/VssHttpRetryOptions.cs +++ /dev/null @@ -1,200 +0,0 @@ -using GitHub.Services.Common.Internal; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading; - -namespace GitHub.Services.Common -{ - /// - /// Defines the options used for configuring the retry policy. - /// - public class VssHttpRetryOptions - { - public VssHttpRetryOptions() - : this (new VssHttpRetryableStatusCodeFilter[] { s_hostShutdownFilter } ) - { - } - - public VssHttpRetryOptions(IEnumerable filters) - { - this.BackoffCoefficient = s_backoffCoefficient; - this.MinBackoff = s_minBackoff; - this.MaxBackoff = s_maxBackoff; - this.MaxRetries = 5; - this.RetryableStatusCodes = new HashSet - { - HttpStatusCode.BadGateway, - HttpStatusCode.GatewayTimeout, - HttpStatusCode.ServiceUnavailable, - }; - - this.m_retryFilters = new HashSet(filters); - } - - /// - /// Gets a singleton read-only instance of the default settings. - /// - public static VssHttpRetryOptions Default - { - get - { - return s_defaultOptions.Value; - } - } - - /// - /// Gets or sets the coefficient which exponentially increases the backoff starting at . - /// - public TimeSpan BackoffCoefficient - { - get - { - return m_backoffCoefficient; - } - set - { - ThrowIfReadonly(); - m_backoffCoefficient = value; - } - } - - /// - /// Gets or sets the minimum backoff interval to be used. - /// - public TimeSpan MinBackoff - { - get - { - return m_minBackoff; - } - set - { - ThrowIfReadonly(); - m_minBackoff = value; - } - } - - /// - /// Gets or sets the maximum backoff interval to be used. - /// - public TimeSpan MaxBackoff - { - get - { - return m_maxBackoff; - } - set - { - ThrowIfReadonly(); - m_maxBackoff = value; - } - } - - /// - /// Gets or sets the maximum number of retries allowed. - /// - public Int32 MaxRetries - { - get - { - return m_maxRetries; - } - set - { - ThrowIfReadonly(); - m_maxRetries = value; - } - } - - /// - /// Gets a set of HTTP status codes which should be retried. - /// - public ICollection RetryableStatusCodes - { - get - { - return m_retryableStatusCodes; - } - private set - { - ThrowIfReadonly(); - m_retryableStatusCodes = value; - } - } - - /// - /// How to verify that the response can be retried. - /// - /// Response message from a request - /// True if the request can be retried, false otherwise. - public Boolean IsRetryableResponse(HttpResponseMessage response) - { - if (m_retryableStatusCodes.Contains(response.StatusCode)) - { - foreach (VssHttpRetryableStatusCodeFilter filter in m_retryFilters) - { - if (filter(response)) - { - return false; - } - } - - return true; - } - - return false; - } - - /// - /// Ensures that no further modifications may be made to the retry options. - /// - /// A read-only instance of the retry options - public VssHttpRetryOptions MakeReadonly() - { - if (Interlocked.CompareExchange(ref m_isReadOnly, 1, 0) == 0) - { - m_retryableStatusCodes = new ReadOnlyCollection(m_retryableStatusCodes.ToList()); - m_retryFilters = new ReadOnlyCollection(m_retryFilters.ToList()); - } - return this; - } - - - - /// - /// Throws an InvalidOperationException if this is marked as ReadOnly. - /// - private void ThrowIfReadonly() - { - if (m_isReadOnly > 0) - { - throw new InvalidOperationException(); - } - } - - /// - /// Returns false if we should continue retrying based on the response, and true if we should not, even though - /// this is technically a retryable status code. - /// - /// The response to check if we should retry the request. - /// False if we should retry, true if we should not based on the response. - public delegate Boolean VssHttpRetryableStatusCodeFilter(HttpResponseMessage response); - - private Int32 m_isReadOnly; - private Int32 m_maxRetries; - private TimeSpan m_minBackoff; - private TimeSpan m_maxBackoff; - private TimeSpan m_backoffCoefficient; - private ICollection m_retryableStatusCodes; - private ICollection m_retryFilters; - private static TimeSpan s_minBackoff = TimeSpan.FromSeconds(10); - private static TimeSpan s_maxBackoff = TimeSpan.FromMinutes(10); - private static TimeSpan s_backoffCoefficient = TimeSpan.FromSeconds(1); - private static Lazy s_defaultOptions = new Lazy(() => new VssHttpRetryOptions().MakeReadonly()); - private static VssHttpRetryableStatusCodeFilter s_hostShutdownFilter = new VssHttpRetryableStatusCodeFilter(response => response.Headers.Contains(HttpHeaders.VssHostOfflineError)); - } -} diff --git a/src/Sdk/Common/Common/VssNetworkHelper.cs b/src/Sdk/Common/Common/VssNetworkHelper.cs deleted file mode 100644 index 49d69d99d..000000000 --- a/src/Sdk/Common/Common/VssNetworkHelper.cs +++ /dev/null @@ -1,236 +0,0 @@ -using System; -using System.ComponentModel; -using System.IO; -using System.Net; -using System.Net.Sockets; - -namespace GitHub.Services.Common -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public static class VssNetworkHelper - { - /// - /// Heuristic used to determine whether an exception is a transient network - /// failure that should be retried. - /// - public static bool IsTransientNetworkException(Exception ex) - { - return IsTransientNetworkException(ex, new VssHttpRetryOptions()); - } - - /// - /// Heuristic used to determine whether an exception is a transient network - /// failure that should be retried. - /// - public static bool IsTransientNetworkException( - Exception ex, - VssHttpRetryOptions options) - { - HttpStatusCode? httpStatusCode; - WebExceptionStatus? webExceptionStatus; - SocketError? socketErrorCode; - WinHttpErrorCode? winHttpErrorCode; - CurlErrorCode? curlErrorCode; - return IsTransientNetworkException(ex, options, out httpStatusCode, out webExceptionStatus, out socketErrorCode, out winHttpErrorCode, out curlErrorCode); - } - - /// - /// Heuristic used to determine whether an exception is a transient network - /// failure that should be retried. - /// - public static bool IsTransientNetworkException( - Exception ex, - out HttpStatusCode? httpStatusCode, - out WebExceptionStatus? webExceptionStatus, - out SocketError? socketErrorCode, - out WinHttpErrorCode? winHttpErrorCode, - out CurlErrorCode? curlErrorCode) - { - return IsTransientNetworkException(ex, VssHttpRetryOptions.Default, out httpStatusCode, out webExceptionStatus, out socketErrorCode, out winHttpErrorCode, out curlErrorCode); - } - - /// - /// Heuristic used to determine whether an exception is a transient network - /// failure that should be retried. - /// - public static bool IsTransientNetworkException( - Exception ex, - VssHttpRetryOptions options, - out HttpStatusCode? httpStatusCode, - out WebExceptionStatus? webExceptionStatus, - out SocketError? socketErrorCode, - out WinHttpErrorCode? winHttpErrorCode, - out CurlErrorCode? curlErrorCode) - { - httpStatusCode = null; - webExceptionStatus = null; - socketErrorCode = null; - winHttpErrorCode = null; - curlErrorCode = null; - - while (ex != null) - { - if (IsTransientNetworkExceptionHelper(ex, options, out httpStatusCode, out webExceptionStatus, out socketErrorCode, out winHttpErrorCode, out curlErrorCode)) - { - return true; - } - - ex = ex.InnerException; - } - - return false; - } - - /// - /// Helper which checks a particular Exception instance (non-recursive). - /// - private static bool IsTransientNetworkExceptionHelper( - Exception ex, - VssHttpRetryOptions options, - out HttpStatusCode? httpStatusCode, - out WebExceptionStatus? webExceptionStatus, - out SocketError? socketErrorCode, - out WinHttpErrorCode? winHttpErrorCode, - out CurlErrorCode? curlErrorCode) - { - ArgumentUtility.CheckForNull(ex, "ex"); - - httpStatusCode = null; - webExceptionStatus = null; - socketErrorCode = null; - winHttpErrorCode = null; - curlErrorCode = null; - - if (ex is WebException) - { - WebException webEx = (WebException)ex; - - if (webEx.Response != null && webEx.Response is HttpWebResponse) - { - var httpResponse = (HttpWebResponse)webEx.Response; - httpStatusCode = httpResponse.StatusCode; - - // If the options include this status code as a retryable error then we report the exception - // as transient to the caller - if (options.RetryableStatusCodes.Contains(httpResponse.StatusCode)) - { - return true; - } - } - - webExceptionStatus = webEx.Status; - - if (webEx.Status == WebExceptionStatus.ConnectFailure || - webEx.Status == WebExceptionStatus.ConnectionClosed || - webEx.Status == WebExceptionStatus.KeepAliveFailure || - webEx.Status == WebExceptionStatus.NameResolutionFailure || - webEx.Status == WebExceptionStatus.ReceiveFailure || - webEx.Status == WebExceptionStatus.SendFailure || - webEx.Status == WebExceptionStatus.Timeout) - { - return true; - } - } - else if (ex is SocketException) - { - SocketException sockEx = (SocketException)ex; - - socketErrorCode = sockEx.SocketErrorCode; - - if (sockEx.SocketErrorCode == SocketError.Interrupted || - sockEx.SocketErrorCode == SocketError.NetworkDown || - sockEx.SocketErrorCode == SocketError.NetworkUnreachable || - sockEx.SocketErrorCode == SocketError.NetworkReset || - sockEx.SocketErrorCode == SocketError.ConnectionAborted || - sockEx.SocketErrorCode == SocketError.ConnectionReset || - sockEx.SocketErrorCode == SocketError.TimedOut || - sockEx.SocketErrorCode == SocketError.HostDown || - sockEx.SocketErrorCode == SocketError.HostUnreachable || - sockEx.SocketErrorCode == SocketError.TryAgain) - { - return true; - } - } - else if (ex is Win32Exception) // WinHttpException when use WinHttp (dotnet core) - { - Win32Exception winHttpEx = (Win32Exception)ex; - - Int32 errorCode = winHttpEx.NativeErrorCode; - if (errorCode > (Int32)WinHttpErrorCode.WINHTTP_ERROR_BASE && - errorCode <= (Int32)WinHttpErrorCode.WINHTTP_ERROR_LAST) - { - winHttpErrorCode = (WinHttpErrorCode)errorCode; - - if (winHttpErrorCode == WinHttpErrorCode.ERROR_WINHTTP_CANNOT_CONNECT || - winHttpErrorCode == WinHttpErrorCode.ERROR_WINHTTP_CONNECTION_ERROR || - winHttpErrorCode == WinHttpErrorCode.ERROR_WINHTTP_INTERNAL_ERROR || - winHttpErrorCode == WinHttpErrorCode.ERROR_WINHTTP_NAME_NOT_RESOLVED || - winHttpErrorCode == WinHttpErrorCode.ERROR_WINHTTP_TIMEOUT) - { - return true; - } - } - } - else if (ex is IOException) - { - if (null != ex.InnerException && - ex.InnerException is Win32Exception) - { - String stackTrace = ex.StackTrace; - - if (null != stackTrace && - stackTrace.IndexOf("System.Net.Security._SslStream.StartWriting(", StringComparison.Ordinal) >= 0) - { - // HACK: There is an underlying HRESULT code for this error which is not set on the exception which - // bubbles from the underlying stack. The top of the stack trace will be in the _SslStream class - // and will have an exception chain of HttpRequestException -> IOException -> Win32Exception. - - // Check for SEC_E_CONTEXT_EXPIRED as this occurs at random in the underlying stack. Retrying the - // request should get a new connection and work correctly, so we ignore this particular error. - - return true; - } - } - } - else if (ex.GetType().Name == "CurlException") // CurlException when use libcurl (dotnet core) - { - // Valid curl error code should in range (0, 93] - if (ex.HResult > 0 && ex.HResult < 94) - { - curlErrorCode = (CurlErrorCode)ex.HResult; - if (curlErrorCode == CurlErrorCode.CURLE_COULDNT_RESOLVE_PROXY || - curlErrorCode == CurlErrorCode.CURLE_COULDNT_RESOLVE_HOST || - curlErrorCode == CurlErrorCode.CURLE_COULDNT_CONNECT || - curlErrorCode == CurlErrorCode.CURLE_HTTP2 || - curlErrorCode == CurlErrorCode.CURLE_PARTIAL_FILE || - curlErrorCode == CurlErrorCode.CURLE_WRITE_ERROR || - curlErrorCode == CurlErrorCode.CURLE_UPLOAD_FAILED || - curlErrorCode == CurlErrorCode.CURLE_READ_ERROR || - curlErrorCode == CurlErrorCode.CURLE_OPERATION_TIMEDOUT || - curlErrorCode == CurlErrorCode.CURLE_INTERFACE_FAILED || - curlErrorCode == CurlErrorCode.CURLE_GOT_NOTHING || - curlErrorCode == CurlErrorCode.CURLE_SEND_ERROR || - curlErrorCode == CurlErrorCode.CURLE_RECV_ERROR) - { - return true; - } - } - } -#if !NETSTANDARD - else if (ex is System.Data.Services.Client.DataServiceRequestException || - ex is System.Data.Services.Client.DataServiceClientException) - { - // WCF exceptions - return true; - } -#endif - - return false; - } - - /// - /// Gets the HttpStatusCode which represents a throttling error. - /// - public const HttpStatusCode TooManyRequests = (HttpStatusCode)429; - } -} diff --git a/src/Sdk/Common/Common/VssPerformanceEventSource.cs b/src/Sdk/Common/Common/VssPerformanceEventSource.cs deleted file mode 100644 index dd65becb4..000000000 --- a/src/Sdk/Common/Common/VssPerformanceEventSource.cs +++ /dev/null @@ -1,498 +0,0 @@ -using System; -using System.Diagnostics.Tracing; - -namespace GitHub.Services.Common -{ - /// - /// Note: This is our perfview event source which is used for performance troubleshooting - /// Sadly, EventSource has few overloads so anything that isn't in http://msdn.microsoft.com/en-us/library/system.diagnostics.tracing.eventsource.writeevent.aspx - /// will cause a bunch of allocations - so we use manual interop for anything non trivial. - /// - /// - public sealed class VssPerformanceEventSource : EventSource - { - public static VssPerformanceEventSource Log = new VssPerformanceEventSource(); - - #region WriteEvent PInvoke Overrides - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u1, Guid u2, string st) - { - if (IsEnabled()) - { - st = st ?? String.Empty; - const int parameters = 3; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].Size = sizeof(Guid); - dataDesc[0].DataPointer = (IntPtr)(&u1); - dataDesc[1].Size = sizeof(Guid); - dataDesc[1].DataPointer = (IntPtr)(&u2); - dataDesc[2].Size = (st.Length + 1) * sizeof(char); - - fixed (char* pcst = st) - { - dataDesc[2].DataPointer = (IntPtr)pcst; - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u1, Guid u2, string st, long duration) - { - if (IsEnabled()) - { - st = st ?? String.Empty; - const int parameters = 4; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].Size = sizeof(Guid); - dataDesc[0].DataPointer = (IntPtr)(&u1); - dataDesc[1].Size = sizeof(Guid); - dataDesc[1].DataPointer = (IntPtr)(&u2); - dataDesc[2].Size = (st.Length + 1) * sizeof(char); - dataDesc[3].Size = sizeof(long); - dataDesc[3].DataPointer = (IntPtr)(&duration); - - fixed (char* pcst = st) - { - dataDesc[2].DataPointer = (IntPtr)pcst; - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u, string st) - { - if (IsEnabled()) - { - st = st ?? String.Empty; - const int parameters = 2; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&u); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st.Length + 1) * sizeof(char); - - fixed (char* pcSt = st) - { - dataDesc[1].DataPointer = (IntPtr)(pcSt); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u, string st, long duration) - { - if (IsEnabled()) - { - st = st ?? String.Empty; - const int parameters = 3; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&u); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st.Length + 1) * sizeof(char); - dataDesc[2].Size = sizeof(long); - dataDesc[2].DataPointer = (IntPtr)(&duration); - - fixed (char* pcSt = st) - { - dataDesc[1].DataPointer = (IntPtr)(pcSt); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u) - { - if (IsEnabled()) - { - EventData dataDesc = new EventData(); // this is a struct so no allocation here - - dataDesc.DataPointer = (IntPtr)(&u); - dataDesc.Size = sizeof(Guid); - WriteEventCore(eventId, 1, &dataDesc); - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u, long duration) - { - if (IsEnabled()) - { - const int parameters = 2; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&u); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].DataPointer = (IntPtr)(&duration); - dataDesc[1].Size = sizeof(long); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u1, string st1, DateTime dt1, DateTime dt2, Guid u2) // Guid uniqueIdentifier, string name, string validFrom, string validTo, Guid contextId - { - if (IsEnabled()) - { - st1 = st1 ?? String.Empty; - long ft1 = dt1.ToFileTimeUtc(); - long ft2 = dt2.ToFileTimeUtc(); - - const int parameters = 5; - - EventData* dataDesc = stackalloc EventData[parameters]; - dataDesc[0].DataPointer = (IntPtr)(&u1); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st1.Length + 1) * sizeof(char); - dataDesc[2].DataPointer = (IntPtr)(&ft1); - dataDesc[2].Size = sizeof(long); - dataDesc[3].DataPointer = (IntPtr)(&ft2); - dataDesc[3].Size = sizeof(long); - dataDesc[4].DataPointer = (IntPtr)(&u2); - dataDesc[4].Size = sizeof(Guid); - - fixed (char* pcst1 = st1) - { - dataDesc[1].DataPointer = (IntPtr)(pcst1); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid u1, string st1, string st2, string st3, Guid u2, long duration) // Guid uniqueIdentifier, string name, string validFrom, string validTo, Guid contextId - { - if (IsEnabled()) - { - st1 = st1 ?? String.Empty; - st2 = st2 ?? String.Empty; - st3 = st3 ?? String.Empty; - - const int parameters = 6; - - EventData* dataDesc = stackalloc EventData[parameters]; - dataDesc[0].DataPointer = (IntPtr)(&u1); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st1.Length + 1) * sizeof(char); - dataDesc[2].Size = (st2.Length + 1) * sizeof(char); - dataDesc[3].Size = (st3.Length + 1) * sizeof(char); - dataDesc[4].DataPointer = (IntPtr)(&u2); - dataDesc[4].Size = sizeof(Guid); - dataDesc[5].DataPointer = (IntPtr)(&duration); - dataDesc[5].Size = sizeof(long); - - fixed (char* pcst1 = st1, pcst2 = st2, pcst3 = st3) - { - dataDesc[1].DataPointer = (IntPtr)(pcst1); - dataDesc[2].DataPointer = (IntPtr)(pcst2); - dataDesc[3].DataPointer = (IntPtr)(pcst3); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid uniqueIdentifier, string st1, string st2, string st3) - { - if (IsEnabled()) - { - st1 = st1 ?? String.Empty; - st2 = st2 ?? String.Empty; - st3 = st3 ?? String.Empty; - - const int parameters = 4; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&uniqueIdentifier); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st1.Length + 1) * sizeof(char); - dataDesc[2].Size = (st2.Length + 1) * sizeof(char); - dataDesc[3].Size = (st3.Length + 1) * sizeof(char); - - fixed (char* pcst1 = st1, pcst2 = st2, pcst3 = st3) - { - dataDesc[1].DataPointer = (IntPtr)(pcst1); - dataDesc[2].DataPointer = (IntPtr)(pcst2); - dataDesc[3].DataPointer = (IntPtr)(pcst3); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid uniqueIdentifier, string st1, string st2, string st3, long duration) - { - if (IsEnabled()) - { - st1 = st1 ?? String.Empty; - st2 = st2 ?? String.Empty; - st3 = st3 ?? String.Empty; - - const int parameters = 5; - - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&uniqueIdentifier); - dataDesc[0].Size = sizeof(Guid); - - dataDesc[1].Size = (st1.Length + 1) * sizeof(char); - dataDesc[2].Size = (st2.Length + 1) * sizeof(char); - dataDesc[3].Size = (st3.Length + 1) * sizeof(char); - - dataDesc[4].DataPointer = (IntPtr)(&duration); - dataDesc[4].Size = sizeof(long); - - fixed (char* pcst1 = st1, pcst2 = st2, pcst3 = st3) - { - dataDesc[1].DataPointer = (IntPtr)(pcst1); - dataDesc[2].DataPointer = (IntPtr)(pcst2); - dataDesc[3].DataPointer = (IntPtr)(pcst3); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid uniqueIdentifier, string st1, string st2) - { - if (IsEnabled()) - { - st1 = st1 ?? String.Empty; - st2 = st2 ?? String.Empty; - - const int parameters = 3; - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&uniqueIdentifier); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st1.Length + 1) * sizeof(char); - dataDesc[2].Size = (st2.Length + 1) * sizeof(char); - - fixed (char* pcst1 = st1, pcst2 = st2) - { - dataDesc[1].DataPointer = (IntPtr)(pcst1); - dataDesc[2].DataPointer = (IntPtr)(pcst2); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, Guid uniqueIdentifier, string st1, string st2, long duration) - { - if (IsEnabled()) - { - st1 = st1 ?? String.Empty; - st2 = st2 ?? String.Empty; - - const int parameters = 4; - - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].DataPointer = (IntPtr)(&uniqueIdentifier); - dataDesc[0].Size = sizeof(Guid); - dataDesc[1].Size = (st1.Length + 1) * sizeof(char); - dataDesc[2].Size = (st2.Length + 1) * sizeof(char); - dataDesc[3].DataPointer = (IntPtr)(&duration); - dataDesc[3].Size = sizeof(long); - - fixed (char* pcst1 = st1, pcst2 = st2) - { - dataDesc[1].DataPointer = (IntPtr)(pcst1); - dataDesc[2].DataPointer = (IntPtr)(pcst2); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - - [NonEvent] - public unsafe void WriteEvent(int eventId, string st, int i1, long duration) - { - if (IsEnabled()) - { - const int parameters = 3; - st = st ?? String.Empty; - - EventData* dataDesc = stackalloc EventData[parameters]; - - dataDesc[0].Size = (st.Length + 1) * sizeof(char); - dataDesc[1].DataPointer = (IntPtr)(&i1); - dataDesc[1].Size = sizeof(Int32); - dataDesc[2].DataPointer = (IntPtr)(&duration); - dataDesc[2].Size = sizeof(int); - - fixed (char* pcst = st) - { - dataDesc[0].DataPointer = (IntPtr)(pcst); - - WriteEventCore(eventId, parameters, dataDesc); - } - } - } - #endregion - - public void MethodStart(Guid uniqueIdentifier, Guid hostId, string methodName) - { - WriteEvent(1, uniqueIdentifier, hostId, methodName); - } - - public void MethodStop(Guid uniqueIdentifier, Guid hostId, string methodName, long duration) - { - WriteEvent(2, uniqueIdentifier, hostId, methodName, duration); - } - - public void NotificationCallbackStart(Guid hostId, string callback) - { - WriteEvent(3, hostId, callback); - } - - public void NotificationCallbackStop(Guid hostId, string callback, long duration) - { - WriteEvent(4, hostId, callback, duration); - } - - public void TaskCallbackStart(Guid hostId, string callback) - { - WriteEvent(5, hostId, callback); - } - - public void TaskCallbackStop(Guid hostId, string callback, long duration) - { - WriteEvent(6, hostId, callback, duration); - } - - public void StopHostTaskStart(Guid hostId) - { - WriteEvent(7, hostId); - } - - public void StopHostTaskStop(Guid hostId, long duration) - { - WriteEvent(8, hostId, duration); - } - - public void RefreshSecurityTokenStart(Guid uniqueIdentifier, string name) - { - WriteEvent(9, uniqueIdentifier, name); - } - - public void RefreshSecurityTokenStop(Guid uniqueIdentifier, string name, DateTime validFrom, DateTime validTo, Guid contextId, long duration) - { - WriteEvent(10, uniqueIdentifier, name, validFrom, validTo, contextId, duration); - } - - public void SQLStart(Guid uniqueIdentifier, string query, string server, string databaseName) - { - WriteEvent(11, uniqueIdentifier, query, server, databaseName); - } - - public void SQLStop(Guid uniqueIdentifier, string query, string server, string databaseName, long duration) - { - WriteEvent(12, uniqueIdentifier, query, server, databaseName, duration); - } - - public void RESTStart(Guid uniqueIdentifier, string message) - { - WriteEvent(13, uniqueIdentifier, message); - } - - public void RESTStop(Guid uniqueIdentifier, Guid originalActivityId, string message, long duration) - { - WriteEvent(14, uniqueIdentifier, originalActivityId, message, duration); - } - - public void WindowsAzureStorageStart(Guid uniqueIdentifier, string accountName, string methodName) - { - WriteEvent(15, uniqueIdentifier, accountName, methodName); - } - - public void WindowsAzureStorageStop(Guid uniqueIdentifier, string accountName, string methodName, long duration) - { - WriteEvent(16, uniqueIdentifier, accountName, methodName, duration); - } - - public void LoadHostStart(Guid hostId) - { - WriteEvent(17, hostId); - } - - public void LoadHostStop(Guid hostId, long duration) - { - WriteEvent(18, hostId, duration); - } - - /// - /// This method is intentionally called Begin, not Start(), since it's a recursive event - /// Service Profiler cannot deal with recursive events unless you have the - /// [Event(EventActivityOptions.Recursive)] however that is not supported in 4.5 currently - /// - /// - /// - /// - public void CreateServiceInstanceBegin(Guid uniqueIdentifier, Guid hostId, string serviceType) - { - WriteEvent(19, uniqueIdentifier, hostId, serviceType); - } - - /// - /// This method is intentionally called Begin, not Start(), since it's a recursive event - /// Service Profiler cannot deal with recursive events unless you have the - /// [Event(EventActivityOptions.Recursive)] however that is not supported in 4.5 currently - /// - /// - /// - /// - /// - public void CreateServiceInstanceEnd(Guid uniqueIdentifier, Guid hostId, string serviceType, long duration) - { - WriteEvent(20, uniqueIdentifier, hostId, serviceType, duration); - } - - public void DetectedLockReentryViolation(string lockName) - { - WriteEvent(21, lockName); - } - - public void DetectedLockUsageViolation(string lockName, string locksHeld) - { - WriteEvent(22, lockName, locksHeld); - } - - public void RedisStart(Guid uniqueIdentifier, string operation, string ciArea, string cacheArea) - { - WriteEvent(23, uniqueIdentifier, operation, ciArea, cacheArea); - } - - public void RedisStop(Guid uniqueIdentifier, string operation, string ciArea, string cacheArea, long duration) - { - WriteEvent(24, uniqueIdentifier, operation, ciArea, cacheArea, duration); - } - - public void MessageBusSendBatchStart(Guid uniqueIdentifier, string messageBusName, int numberOfMessages) - { - WriteEvent(25, uniqueIdentifier, messageBusName, numberOfMessages); - } - - public void MessageBusSendBatchStop(Guid uniqueIdentifier, string messageBusName, int numberOfMessages, long duration) - { - WriteEvent(26, uniqueIdentifier, messageBusName, numberOfMessages, duration); - } - - } -} diff --git a/src/Sdk/Common/EmbeddedVersionInfo.cs b/src/Sdk/Common/EmbeddedVersionInfo.cs deleted file mode 100644 index ee0363567..000000000 --- a/src/Sdk/Common/EmbeddedVersionInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Runtime.CompilerServices; - -namespace GitHub.Services.Common -{ - [CompilerGenerated] - internal static class GeneratedVersionInfo - { - // Legacy values which preserve semantics from prior to the Assembly / File version split. - // See Toolsets\Version\Version.props for more details. - public const String MajorVersion = "16"; - public const String MinorVersion = "0"; - public const String BuildVersion = "65000"; - public const String PatchVersion = "0"; - public const String ProductVersion = MajorVersion + "." + MinorVersion; - - // Assembly version (i.e. strong name) - public const String AssemblyMajorVersion = "16"; - public const String AssemblyMinorVersion = "0"; - public const String AssemblyBuildVersion = "0"; - public const String AssemblyPatchVersion = "0"; - public const String AssemblyVersion = AssemblyMajorVersion + "." + AssemblyMinorVersion + "." + AssemblyBuildVersion + "." + AssemblyPatchVersion; - - // File version - public const String FileMajorVersion = "16"; - public const String FileMinorVersion = "255"; - public const String FileBuildVersion = "65000"; - public const String FilePatchVersion = "0"; - public const String FileVersion = FileMajorVersion + "." + FileMinorVersion + "." + FileBuildVersion + "." + FilePatchVersion; - - // Derived versions - public const String TfsMajorVersion = "8"; - public const String TfsMinorVersion = "0"; - public const String TfsProductVersion = TfsMajorVersion + "." + TfsMinorVersion; - - // On-premises TFS install folder - public const String TfsInstallDirectory = "Azure DevOps Server 2019"; - } -} diff --git a/src/Sdk/DTWebApi/WebApi/TaskHttpClient.cs b/src/Sdk/DTWebApi/WebApi/TaskHttpClient.cs index d700f19dc..fcc1ab6ce 100644 --- a/src/Sdk/DTWebApi/WebApi/TaskHttpClient.cs +++ b/src/Sdk/DTWebApi/WebApi/TaskHttpClient.cs @@ -1,5 +1,4 @@ -using GitHub.DistributedTask.Pipelines.Runtime; -using GitHub.Services.Common; +using GitHub.Services.Common; using GitHub.Services.WebApi; using System; using System.Collections.Generic; diff --git a/src/Sdk/Namespaces.cs b/src/Sdk/Namespaces.cs index d2b8143cd..e71d84f41 100644 --- a/src/Sdk/Namespaces.cs +++ b/src/Sdk/Namespaces.cs @@ -1,8 +1,16 @@ -namespace AsyncFixer +namespace AsyncFixer { } -namespace GitHub.DistributedTask.Common.Contracts +namespace GitHub.Actions.Pipelines.WebApi +{ +} + +namespace GitHub.Actions.Pipelines.WebApi.Contracts +{ +} + +namespace GitHub.Build.WebApi { } @@ -10,7 +18,23 @@ namespace GitHub.DistributedTask.Expressions { } -namespace GitHub.DistributedTask.Expressions.CollectionAccessors +namespace GitHub.DistributedTask.Expressions2 +{ +} + +namespace GitHub.DistributedTask.Expressions2.Sdk +{ +} + +namespace GitHub.DistributedTask.Expressions2.Sdk.Functions +{ +} + +namespace GitHub.DistributedTask.Expressions2.Sdk.Operators +{ +} + +namespace GitHub.DistributedTask.Expressions2.Tokens { } @@ -30,18 +54,10 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens { } -namespace GitHub.DistributedTask.Orchestration.Server.Artifacts -{ -} - namespace GitHub.DistributedTask.Pipelines { } -namespace GitHub.DistributedTask.Pipelines.Artifacts -{ -} - namespace GitHub.DistributedTask.Pipelines.ContextData { } @@ -54,10 +70,6 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating { } -namespace GitHub.DistributedTask.Pipelines.Runtime -{ -} - namespace GitHub.DistributedTask.Pipelines.Validation { } @@ -70,6 +82,10 @@ namespace GitHub.GraphProfile.WebApi { } +namespace GitHub.Services +{ +} + namespace GitHub.Services.Account { } @@ -90,10 +106,6 @@ namespace GitHub.Services.CentralizedFeature { } -namespace GitHub.Services.Client -{ -} - namespace GitHub.Services.ClientNotification { } @@ -142,6 +154,10 @@ namespace GitHub.Services.FileContainer { } +namespace GitHub.Services.FileContainer.Client +{ +} + namespace GitHub.Services.FormInput { } @@ -282,6 +298,10 @@ namespace GitHub.Services.WebApi { } +namespace GitHub.Services.WebApi.Exceptions +{ +} + namespace GitHub.Services.WebApi.Internal { } diff --git a/src/Sdk/WebApi/WebApi/Attributes.cs b/src/Sdk/WebApi/WebApi/Attributes.cs deleted file mode 100644 index 375d8debe..000000000 --- a/src/Sdk/WebApi/WebApi/Attributes.cs +++ /dev/null @@ -1,177 +0,0 @@ -using System; -using GitHub.Services.WebApi.Internal; - -namespace GitHub.Services.WebApi -{ - /// - /// This attribute provides the location service area identifier in order to target the location service - /// instance which has the service definitions for the HTTP resources in the specified service area. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] - public sealed class ResourceAreaAttribute : Attribute - { - public ResourceAreaAttribute(String areaId) - { - this.AreaId = new Guid(areaId); - } - - public readonly Guid AreaId; - } - - /// - /// Use in conjunction with JsonCompatConverter. This attribute describes a model property or field change at a particular API version. - /// - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)] - public sealed class CompatPropertyAttribute : Attribute - { - /// - /// This attribute describes a model property or field change at a particular API version. - /// - /// Old name of the serialized property. - /// The major version component of the max version of the api to support the old property name. - /// The minor version component of the max version of the api to support the old property name. - public CompatPropertyAttribute(String oldName, Int32 majorApiVersion, Int32 minorApiVersion = 0) - { - OldName = oldName; - MaxApiVersion = new Version(majorApiVersion, minorApiVersion); - } - - /// - /// Old name of the serialized property. - /// - public String OldName { get; private set; } - - /// - /// The max version of the api to support the old property name. - /// - public Version MaxApiVersion { get; private set; } - } - - /// - /// This tells the client generator to set this property to the content of the repsonse - /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] - public sealed class ClientResponseContentAttribute : Attribute - { - public ClientResponseContentAttribute() - { - } - } - - /// - /// This tells the client generator to set this property to the header value from the response. This should only be added to types of IEnumerable<String> - /// - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] - public sealed class ClientResponseHeaderAttribute : Attribute - { - public ClientResponseHeaderAttribute(string headerName) - { - HeaderName = headerName; - } - - public string HeaderName { get; private set; } - } - - /// - /// Tells the client generator to create meta data for this model, even if it is not referenced directly or indirectly from the client. - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct, AllowMultiple = false)] - public sealed class ClientIncludeModelAttribute : Attribute - { - public ClientIncludeModelAttribute() - { - Languages = RestClientLanguages.All; - } - - public ClientIncludeModelAttribute(RestClientLanguages languages) - { - Languages = languages; - } - - public RestClientLanguages Languages { get; } - } - - /// - /// Marks a class, method or property for internal use only. This attribute ensures the item - /// does not show up in public documentation, adds EditorBrowsableState.Never in C# clients - /// to hide the item, and optionaly adds @internal in TypeScript clients which removes the - /// item from the TypeScript declare (d.ts) file. This does not exempt this API from the - /// formal REST Api review process. Our internal APIs must meet the same standards and - /// guidelines as our public APIs. - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] - public sealed class ClientInternalUseOnlyAttribute : Attribute - { - /// - /// Marks a class, method or property for internal use only. This attribute ensures the item - /// does not show up in public documentation, adds EditorBrowsableState.Never in C# clients - /// to hide the item, and optionaly adds @internal in TypeScript clients which removes the - /// item from the TypeScript declare (d.ts) file. This does not exempt this API from the - /// formal REST Api review process. Our internal APIs must meet the same standards and - /// guidelines as our public APIs. - /// - /// Default is true. Set to false if you need the item to appear in the TypeScript declare (d.ts) file for use by extensions. - public ClientInternalUseOnlyAttribute(bool omitFromTypeScriptDeclareFile = true) - { - OmitFromTypeScriptDeclareFile = omitFromTypeScriptDeclareFile; - } - - /// - /// Set to false if you need the item to appear in the TypeScript declare (d.ts) file for use by extensions. - /// - public bool OmitFromTypeScriptDeclareFile { get; set; } - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] - public sealed class ClientCircuitBreakerSettingsAttribute : Attribute - { - public ClientCircuitBreakerSettingsAttribute(int timeoutSeconds, int failurePercentage) - { - Timeout = TimeSpan.FromSeconds(timeoutSeconds); - ErrorPercentage = failurePercentage; - } - - /// - /// Timeout in seconds - /// - public TimeSpan Timeout { get; private set; } - - /// - /// Percentage of failed commands - /// - public int ErrorPercentage { get; private set; } - - /// - /// Number of max concurrent requests - /// - public int MaxConcurrentRequests { get; set; } - } - - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false)] - public sealed class ClientCancellationTimeoutAttribute : Attribute - { - public ClientCancellationTimeoutAttribute(int timeoutSeconds) - { - Timeout = TimeSpan.FromSeconds(timeoutSeconds); - } - - /// - /// Timeout in seconds for request cancellation - /// - public TimeSpan Timeout { get; private set; } - } - - /// - /// Indicates which headers are considered to contain sensitive information by a particular HttpClient. - /// - [AttributeUsage(AttributeTargets.Class)] - public sealed class ClientSensitiveHeaderAttribute : Attribute - { - public string HeaderName { get; set; } - - public ClientSensitiveHeaderAttribute(string headerName) - { - HeaderName = headerName; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Constants.cs b/src/Sdk/WebApi/WebApi/Constants.cs deleted file mode 100644 index a94c76230..000000000 --- a/src/Sdk/WebApi/WebApi/Constants.cs +++ /dev/null @@ -1,101 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.ComponentModel; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // This will not be like MS.TF.Framework.Common! - // If your service does not ship in SPS or the Framework SDK you cannot put your stuff here! - // It goes in your own assembly! - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - [GenerateAllConstants] - public static class ServiceInstanceTypes - { - // !!!!!!!!!!!!!!!!!! - // This class is sealed to new guids -- please define your instance type constant in your own assembly - // !!!!!!!!!!!!!!!!!! - - public const String MPSString = "00000000-0000-8888-8000-000000000000"; - public static readonly Guid MPS = new Guid(MPSString); - - public const String SPSString = "951917AC-A960-4999-8464-E3F0AA25B381"; - public static readonly Guid SPS = new Guid(SPSString); - - public const String TFSString = "00025394-6065-48CA-87D9-7F5672854EF7"; - public static readonly Guid TFS = new Guid(TFSString); - - public const String TFSOnPremisesString = "87966EAA-CB2A-443F-BE3C-47BD3B5BF3CB"; - public static readonly Guid TFSOnPremises = new Guid(TFSOnPremisesString); - - [Obsolete] - public const String SpsExtensionString = "00000024-0000-8888-8000-000000000000"; - [Obsolete] - public static readonly Guid SpsExtension = new Guid(SpsExtensionString); - - public const String SDKSampleString = "FFFFFFFF-0000-8888-8000-000000000000"; - public static readonly Guid SDKSample = new Guid(SDKSampleString); - - // !!!!!!!!!!!!!!!!!! - // This class is sealed to new guids -- please define your instance type constant in your own assembly - // !!!!!!!!!!!!!!!!!! - } - - /// - /// Enumeration of the options that can be passed in on Connect. - /// - [DataContract] - [Flags] - public enum ConnectOptions - { - /// - /// Retrieve no optional data. - /// - [EnumMember] - None = 0, - - /// - /// Includes information about AccessMappings and ServiceDefinitions. - /// - [EnumMember] - IncludeServices = 1, - - /// - /// Includes the last user access for this host. - /// - [EnumMember] - IncludeLastUserAccess = 2, - - /// - /// This is only valid on the deployment host and when true. Will only return - /// inherited definitions. - /// - [EnumMember] - [EditorBrowsable(EditorBrowsableState.Never)] - IncludeInheritedDefinitionsOnly = 4, - - /// - /// When true will only return non inherited definitions. - /// Only valid at non-deployment host. - /// - [EnumMember] - [EditorBrowsable(EditorBrowsableState.Never)] - IncludeNonInheritedDefinitionsOnly = 8, - } - - [DataContract] - [Flags] - public enum DeploymentFlags - { - [EnumMember] - None = 0x0, - - [EnumMember] - Hosted = 0x1, - - [EnumMember] - OnPremises = 0x2 - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Common/SocialDescriptor.cs b/src/Sdk/WebApi/WebApi/Contracts/Common/SocialDescriptor.cs deleted file mode 100644 index ea7daa83d..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Common/SocialDescriptor.cs +++ /dev/null @@ -1,345 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using GitHub.Services.Graph; -using System.Xml.Serialization; -using System.Xml; -using System.Xml.Schema; -using GitHub.Services.WebApi; -using System.Linq; -using System.Reflection; -using System.ComponentModel; -using System.Globalization; - -namespace GitHub.Services.Common -{ - [TypeConverter(typeof(SocialDescriptorConverter))] - public struct SocialDescriptor : IEquatable, IXmlSerializable - { - public SocialDescriptor(string socialType, string identifier) - { - ValidateSocialType(socialType); - ValidateIdentifier(identifier); - - SocialType = NormalizeSocialType(socialType); - Identifier = identifier; - } - - [DataMember] - public string SocialType { get; private set; } - - [DataMember] - public string Identifier { get; private set; } - - public override string ToString() - { - if (this == default(SocialDescriptor)) - { - return null; - } - - return string.Concat( - Constants.SocialDescriptorPrefix, - SocialType, - Constants.SocialDescriptorPartsSeparator, - PrimitiveExtensions.ToBase64StringNoPaddingFromString(Identifier)); - } - - public static SocialDescriptor FromString(string socialDescriptorString) - { - if (string.IsNullOrEmpty(socialDescriptorString)) - { - return default(SocialDescriptor); - } - - if (!socialDescriptorString.StartsWith(Constants.SocialDescriptorPrefix)) - { - return new SocialDescriptor(Constants.SocialType.Unknown, socialDescriptorString); - } - - if (socialDescriptorString.Length < Constants.SocialDescriptorPolicies.MinSocialDescriptorStringLength) - { - return new SocialDescriptor(Constants.SocialType.Unknown, socialDescriptorString); - } - - var tokens = socialDescriptorString.Split(new char[] { Constants.SocialDescriptorPartsSeparator }, 3); - if (tokens.Length != 2) - { - return new SocialDescriptor(Constants.SocialType.Unknown, socialDescriptorString); - } - - string moniker = tokens[0].Substring(1); - string identifier = tokens[1]; - - try - { - return new SocialDescriptor(moniker, PrimitiveExtensions.FromBase64StringNoPaddingToString(identifier)); - } - catch { } - - return new SocialDescriptor(Constants.SocialType.Unknown, socialDescriptorString); - } - - /// - /// Parses a string of comma separated social descriptors into a enumerable list of objects. - /// - /// empty enumerable if parameter 'descriptors' is null or empty - public static IEnumerable FromCommaSeperatedStrings(string descriptors) - { - if (string.IsNullOrEmpty(descriptors)) - { - return Enumerable.Empty(); - } - - return descriptors.Split(Constants.SocialListSeparator).Where(descriptor => !string.IsNullOrEmpty(descriptor)).Select(descriptor => FromString(descriptor)); - } - - #region Equality and Compare - - #region Implement IEquatable to avoid boxing - public bool Equals(SocialDescriptor socialDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(SocialType, socialDescriptor.SocialType) && - StringComparer.Ordinal.Equals(Identifier, socialDescriptor.Identifier); // The Social Identifier can be case sensitive, hence avoiding the case ignore check - } - #endregion - - public override bool Equals(object obj) - { - return obj is SocialDescriptor && this == (SocialDescriptor)obj; - } - - public override int GetHashCode() - { - if (this == default(SocialDescriptor)) - { - return 0; - } - - int hashCode = 7443; // "large" prime to start the seed - - // Bitshifting and subtracting once is an efficient way to multiply by our second "large" prime, 0x7ffff = 524287 - hashCode = (hashCode << 19) - hashCode + StringComparer.OrdinalIgnoreCase.GetHashCode(SocialType); - hashCode = (hashCode << 19) - hashCode + StringComparer.Ordinal.GetHashCode(Identifier); - - return hashCode; - } - - public static bool operator ==(SocialDescriptor left, SocialDescriptor right) - { - return left.Equals(right); - } - - public static bool operator !=(SocialDescriptor left, SocialDescriptor right) - { - return !left.Equals(right); - } - - public static implicit operator string(SocialDescriptor socialDescriptor) - { - return socialDescriptor.ToString(); - } - - internal static int Compare(SocialDescriptor left, SocialDescriptor right) - { - int retValue = StringComparer.OrdinalIgnoreCase.Compare(left.SocialType, right.SocialType); - - if (0 == retValue) - { - retValue = StringComparer.Ordinal.Compare(left.Identifier, right.Identifier); - } - - return retValue; - } - - private static string NormalizeSocialType(String socialType) - { - // Look up the string in the static dictionary. If we get a hit, then - // we'll use that string for the social type instead. This saves memory - // as well as improves compare/equals performance when comparing descriptors, - // since Object.ReferenceEquals will return true a lot more often - if (!Constants.SocialTypeMap.TryGetValue(socialType, out string normalizedSocialType)) - { - normalizedSocialType = socialType; - } - - return normalizedSocialType; - } - #endregion - - #region Validation - //Copied from TFCommonUtil.cs - private static void ValidateSocialType(string socialType) - { - if (string.IsNullOrEmpty(socialType)) - { - throw new ArgumentNullException(nameof(socialType)); - } - - if (socialType.Length < Constants.SocialDescriptorPolicies.MinSocialTypeLength || socialType.Length > Constants.SocialDescriptorPolicies.MaxSocialTypeLength) - { - throw new ArgumentOutOfRangeException(nameof(socialType), socialType, GraphResources.SubjectTypeLengthOutOfRange()); - } - } - - private static void ValidateIdentifier(string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - throw new ArgumentNullException(nameof(identifier)); - } - } - - #endregion - - #region XML Serialization - XmlSchema IXmlSerializable.GetSchema() { return null; } - - void IXmlSerializable.ReadXml(XmlReader reader) - { - ArgumentUtility.CheckForNull(reader, nameof(reader)); - - var isEmptyElement = reader.IsEmptyElement; - - reader.ReadStartElement(); - - if (isEmptyElement) - { - return; - } - - if (reader.NodeType == XmlNodeType.Text) - { - var sourceDescriptor = FromString(reader.ReadContentAsString()); - SocialType = sourceDescriptor.SocialType; - Identifier = sourceDescriptor.Identifier; - } - else - { - while (reader.IsStartElement()) - { - switch (reader.Name) - { - case nameof(SocialType): - var socialType = reader.ReadElementContentAsString(); - ValidateSocialType(socialType); - SocialType = socialType; - break; - case nameof(Identifier): - var identifier = reader.ReadElementContentAsString(); - ValidateIdentifier(identifier); - Identifier = identifier; - break; - default: - reader.ReadOuterXml(); - break; - } - } - } - - reader.ReadEndElement(); - } - - void IXmlSerializable.WriteXml(XmlWriter writer) - { - ArgumentUtility.CheckForNull(writer, nameof(writer)); - - if (Equals(default(SocialDescriptor))) - { - return; - } - - writer.WriteElementString(nameof(SocialType), SocialType); - writer.WriteElementString(nameof(Identifier), Identifier); - } - #endregion - } - - public class SocialDescriptorComparer : IComparer, IEqualityComparer - { - private SocialDescriptorComparer() { } - - public int Compare(SocialDescriptor left, SocialDescriptor right) - { - return SocialDescriptor.Compare(left, right); - } - - public bool Equals(SocialDescriptor left, SocialDescriptor right) - { - return left == right; - } - - public int GetHashCode(SocialDescriptor socialDescriptor) - { - return socialDescriptor.GetHashCode(); - } - - public static SocialDescriptorComparer Instance { get; } = new SocialDescriptorComparer(); - } - - public static class SocialDescriptorExtensions - { - public static bool IsGitHubSocialType(this SocialDescriptor socialDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(socialDescriptor.SocialType ?? String.Empty, Constants.SocialType.GitHub); - } - - public static bool IsSocialType(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.ToString().StartsWith(Constants.SocialDescriptorPrefix); - } - } - - /// - /// Converter to support data contract serialization. - /// - /// - /// This class should only be used to convert a descriptor string from the client back into a string - /// tuple SocialDescriptor type on the server. The client should be unaware that this tuple relationship exists - /// and this should not permit that relationship to leak to the client. - /// - /// Specifically, this is provided so that the MVC router can convert a string => SocialDescriptor so - /// that we can use the [ClientParameterType(typeof(string))] SocialDescriptor socialDescriptor) convenience in each - /// controller method. - /// - public class SocialDescriptorConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string) - { - return SocialDescriptor.FromString((string)value); - } - - return base.ConvertFrom(context, culture, value); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType == typeof(string) && value is SocialDescriptor) - { - SocialDescriptor socialDescriptor = (SocialDescriptor)value; - if (socialDescriptor == default(SocialDescriptor)) - { - // socialDescriptor.ToString() returns null in the case of default(SocialDescriptor) - // and null can not be deserialized when the object is a struct. - return string.Empty; - } - - return socialDescriptor.ToString(); - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Common/SubjectDescriptor.cs b/src/Sdk/WebApi/WebApi/Contracts/Common/SubjectDescriptor.cs deleted file mode 100644 index b931f222a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Common/SubjectDescriptor.cs +++ /dev/null @@ -1,519 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using GitHub.Services.Graph; -using System.Xml.Serialization; -using System.Xml; -using System.Xml.Schema; -using GitHub.Services.WebApi; -using System.Linq; -using System.Reflection; -using System.ComponentModel; -using System.Globalization; - -namespace GitHub.Services.Common -{ - [TypeConverter(typeof(SubjectDescriptorConverter))] - public struct SubjectDescriptor : IEquatable, IXmlSerializable - { - public SubjectDescriptor(string subjectType, string identifier) - { - ValidateSubjectType(subjectType); - ValidateIdentifier(identifier); - - SubjectType = NormalizeSubjectType(subjectType); - Identifier = identifier; - } - - [DataMember] - public string SubjectType { get; private set; } - - [DataMember] - public string Identifier { get; private set; } - - public override string ToString() - { - if (this == default(SubjectDescriptor)) - { - return null; - } - - return string.Concat( - SubjectType, - Constants.SubjectDescriptorPartsSeparator, - PrimitiveExtensions.ToBase64StringNoPaddingFromString(Identifier)); - } - - public static SubjectDescriptor FromString(string subjectDescriptorString) - { - if (string.IsNullOrEmpty(subjectDescriptorString)) - { - return default(SubjectDescriptor); - } - - if (subjectDescriptorString.Length < Constants.SubjectDescriptorPolicies.MinSubjectDescriptorStringLength) - { - return new SubjectDescriptor(Constants.SubjectType.Unknown, subjectDescriptorString); - } - - int splitIndex = subjectDescriptorString.IndexOf(Constants.SubjectDescriptorPartsSeparator, Constants.SubjectDescriptorPolicies.MinSubjectTypeLength, 3); - - // Either the separator is not there, or it's before the MinSubjectTypeLength or it's at the end the string; either way it's wrong. - if (splitIndex < 3 || splitIndex == subjectDescriptorString.Length - 1) - { - return new SubjectDescriptor(Constants.SubjectType.Unknown, subjectDescriptorString); - } - - string moniker = subjectDescriptorString.Substring(0, splitIndex); - string identifier = subjectDescriptorString.Substring(splitIndex + 1); - - try - { - return new SubjectDescriptor(moniker, PrimitiveExtensions.FromBase64StringNoPaddingToString(identifier)); - } - catch { } - - return new SubjectDescriptor(Constants.SubjectType.Unknown, subjectDescriptorString); - } - - /// - /// Parses a string of comma separated subject descriptors into a enumerable list of objects. - /// - /// empty enumerable if parameter 'descriptors' is null or empty - public static IEnumerable FromCommaSeperatedStrings(string descriptors) - { - if (string.IsNullOrEmpty(descriptors)) - { - return Enumerable.Empty(); - } - - return descriptors.Split(',').Where(descriptor => !string.IsNullOrEmpty(descriptor)).Select(descriptor => FromString(descriptor)); - } - - #region Equality and Compare - - #region Implement IEquatable to avoid boxing - public bool Equals(SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(SubjectType, subjectDescriptor.SubjectType) && - StringComparer.OrdinalIgnoreCase.Equals(Identifier, subjectDescriptor.Identifier); - } - #endregion - - public override bool Equals(object obj) - { - return obj is SubjectDescriptor && this == (SubjectDescriptor)obj; - } - - public override int GetHashCode() - { - if (this == default(SubjectDescriptor)) - { - return 0; - } - - int hashCode = 7443; // "large" prime to start the seed - - // Bitshifting and subtracting once is an efficient way to multiply by our second "large" prime, 0x7ffff = 524287 - hashCode = (hashCode << 19) - hashCode + StringComparer.OrdinalIgnoreCase.GetHashCode(SubjectType); - hashCode = (hashCode << 19) - hashCode + StringComparer.OrdinalIgnoreCase.GetHashCode(Identifier); - - return hashCode; - } - - public static bool operator ==(SubjectDescriptor left, SubjectDescriptor right) - { - return left.Equals(right); - } - - public static bool operator !=(SubjectDescriptor left, SubjectDescriptor right) - { - return !left.Equals(right); - } - - public static implicit operator string(SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.ToString(); - } - - internal static int Compare(SubjectDescriptor left, SubjectDescriptor right) - { - int retValue = StringComparer.OrdinalIgnoreCase.Compare(left.SubjectType, right.SubjectType); - - if (0 == retValue) - { - retValue = StringComparer.OrdinalIgnoreCase.Compare(left.Identifier, right.Identifier); - } - - return retValue; - } - - private static string NormalizeSubjectType(String subjectType) - { - // Look up the string in the static dictionary. If we get a hit, then - // we'll use that string for the subject type instead. This saves memory - // as well as improves compare/equals performance when comparing descriptors, - // since Object.ReferenceEquals will return true a lot more often - if (!Constants.SubjectTypeMap.TryGetValue(subjectType, out string normalizedSubjectType)) - { - normalizedSubjectType = subjectType; - } - - return normalizedSubjectType; - } - #endregion - - #region Validation - //Copied from TFCommonUtil.cs - private static void ValidateSubjectType(string subjectType) - { - if (string.IsNullOrEmpty(subjectType)) - { - throw new ArgumentNullException(nameof(subjectType)); - } - - if (subjectType.Length < Constants.SubjectDescriptorPolicies.MinSubjectTypeLength || subjectType.Length > Constants.SubjectDescriptorPolicies.MaxSubjectTypeLength) - { - throw new ArgumentOutOfRangeException(nameof(subjectType), subjectType, GraphResources.SubjectTypeLengthOutOfRange()); - } - } - - private static void ValidateIdentifier(string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - throw new ArgumentNullException(nameof(identifier)); - } - - if (identifier.Length > Constants.SubjectDescriptorPolicies.MaxIdentifierLength) - { - throw new ArgumentOutOfRangeException(nameof(identifier), identifier, GraphResources.IdentifierLengthOutOfRange()); - } - } - - #endregion - - #region XML Serialization - XmlSchema IXmlSerializable.GetSchema() { return null; } - - void IXmlSerializable.ReadXml(XmlReader reader) - { - ArgumentUtility.CheckForNull(reader, nameof(reader)); - - var isEmptyElement = reader.IsEmptyElement; - - reader.ReadStartElement(); - - if (isEmptyElement) - { - return; - } - - if (reader.NodeType == XmlNodeType.Text) - { - var sourceDescriptor = FromString(reader.ReadContentAsString()); - SubjectType = sourceDescriptor.SubjectType; - Identifier = sourceDescriptor.Identifier; - } - else - { - while (reader.IsStartElement()) - { - switch (reader.Name) - { - case nameof(SubjectType): - var subjectType = reader.ReadElementContentAsString(); - ValidateSubjectType(subjectType); - SubjectType = subjectType; - break; - case nameof(Identifier): - var identifier = reader.ReadElementContentAsString(); - ValidateIdentifier(identifier); - Identifier = identifier; - break; - default: - reader.ReadOuterXml(); - break; - } - } - } - - reader.ReadEndElement(); - } - - void IXmlSerializable.WriteXml(XmlWriter writer) - { - ArgumentUtility.CheckForNull(writer, nameof(writer)); - - if (Equals(default(SubjectDescriptor))) - { - return; - } - - writer.WriteElementString(nameof(SubjectType), SubjectType); - writer.WriteElementString(nameof(Identifier), Identifier); - } - #endregion - } - - public class SubjectDescriptorComparer : IComparer, IEqualityComparer - { - private SubjectDescriptorComparer() { } - - public int Compare(SubjectDescriptor left, SubjectDescriptor right) - { - return SubjectDescriptor.Compare(left, right); - } - - public bool Equals(SubjectDescriptor left, SubjectDescriptor right) - { - return left == right; - } - - public int GetHashCode(SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.GetHashCode(); - } - - public static SubjectDescriptorComparer Instance { get; } = new SubjectDescriptorComparer(); - } - - // Keep this in sync with the IdentityDescriptorExtensions to avoid extra casting/conversions - public static class SubjectDescriptorExtensions - { - internal static Guid GetMasterScopeId(this SubjectDescriptor subjectDescriptor) - { - if (!subjectDescriptor.IsGroupScopeType()) - { - throw new InvalidSubjectTypeException(subjectDescriptor.SubjectType); - } - - if (!Guid.TryParse(subjectDescriptor.Identifier, out Guid masterScopeId)) - { - throw new ArgumentException($"Parameter {nameof(subjectDescriptor)} does not have a valid master scope ID"); - } - - return masterScopeId; - } - - internal static Guid GetCuid(this SubjectDescriptor subjectDescriptor) - { - if (!subjectDescriptor.IsCuidBased()) - { - throw new InvalidSubjectTypeException(subjectDescriptor.SubjectType); - } - - if (!Guid.TryParse(subjectDescriptor.Identifier, out Guid cuid)) - { - throw new ArgumentException($"Parameter {nameof(subjectDescriptor)} does not have a valid CUID"); - } - - return cuid; - } - - public static bool IsWindowsType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.WindowsIdentity); - } - - public static bool IsGroupType(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.IsAadGroupType() || subjectDescriptor.IsVstsGroupType(); - } - - public static bool IsAadGroupType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.AadGroup); - } - - public static bool IsVstsGroupType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.VstsGroup); - } - - public static bool IsClaimsUserType(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.IsAadUserType() || subjectDescriptor.IsMsaUserType(); - } - - public static bool IsAadUserType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.AadUser); - } - - public static bool IsMsaUserType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.MsaUser); - } - - public static bool IsBindPendingUserType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.BindPendingUser); - } - - public static bool IsUnauthenticatedIdentityType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.UnauthenticatedIdentity); - } - - public static bool IsServiceIdentityType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.ServiceIdentity); - } - - public static bool IsAggregateIdentityType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.AggregateIdentity); - } - - public static bool IsImportedIdentityType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.ImportedIdentity); - } - - public static bool IsGroupScopeType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.GroupScopeType); - } - - public static bool IsServerTestIdentityType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.ServerTestIdentity); - } - - // ******* All types below this line are not backed by the graph or identity service ************************ - public static bool IsSystemServicePrincipalType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.SystemServicePrincipal); - } - - public static bool IsSystemScopeType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.SystemScope); - } - - public static bool IsSystemCspPartnerType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.SystemCspPartner); - } - - public static bool IsSystemLicenseType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.SystemLicense); - } - - public static bool IsSystemPublicAccessType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.SystemPublicAccess); - } - - public static bool IsSystemAccessControlType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.SystemAccessControl); - } - - public static bool IsSystemType(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.IsSystemServicePrincipalType() || - subjectDescriptor.IsSystemScopeType() || - subjectDescriptor.IsSystemLicenseType() || - subjectDescriptor.IsSystemCspPartnerType() || - subjectDescriptor.IsSystemPublicAccessType() || - subjectDescriptor.IsSystemAccessControlType(); - } - - public static bool IsSubjectStoreType(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.IsSystemServicePrincipalType() || - subjectDescriptor.IsSystemScopeType() || - subjectDescriptor.IsSystemLicenseType() || - subjectDescriptor.IsSystemCspPartnerType(); - } - - public static bool IsCspPartnerIdentityType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.CspPartnerIdentity); - } - - public static bool IsUnknownSubjectType(this SubjectDescriptor subjectDescriptor) - { - return StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.Unknown) || - StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.UnknownGroup) || - StringComparer.OrdinalIgnoreCase.Equals(subjectDescriptor.SubjectType, Constants.SubjectType.UnknownUser); - } - - public static bool IsCuidBased(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.IsClaimsUserType() || subjectDescriptor.IsCspPartnerIdentityType(); - } - - public static bool IsUserType(this SubjectDescriptor subjectDescriptor) - { - return subjectDescriptor.IsClaimsUserType() || - subjectDescriptor.IsCspPartnerIdentityType() || - subjectDescriptor.IsBindPendingUserType() || - subjectDescriptor.IsServiceIdentityType(); - } - - public static bool IsPubliclyAvailableGraphSubjectType(this SubjectDescriptor subjectDescriptor) - { - return (subjectDescriptor == default(SubjectDescriptor)) || - subjectDescriptor.IsUserType() || - subjectDescriptor.IsGroupType() || - subjectDescriptor.IsGroupScopeType(); - } - } - - /// - /// Converter to support data contract serialization. - /// - /// - /// This class should only be used to convert a descriptor string from the client back into a string - /// tuple SubjectDescriptor type on the server. The client should be unaware that this tuple relationship exists - /// and this should not permit that relationship to leak to the client. - /// - /// Specifically, this is provided so that the MVC router can convert a string => SubjectDescriptor so - /// that we can use the [ClientParameterType(typeof(string))] SubjectDescriptor userDescriptor) convenience in each - /// controller method. - /// - public class SubjectDescriptorConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string) - { - return SubjectDescriptor.FromString((string)value); - } - - return base.ConvertFrom(context, culture, value); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType == typeof(string) && value is SubjectDescriptor) - { - SubjectDescriptor subjectDescriptor = (SubjectDescriptor)value; - if (subjectDescriptor == default(SubjectDescriptor)) - { - // subjectDescriptor.ToString() returns null in the case of default(SubjectDescriptor) - // and null can not be deserialized when the object is a struct. - return string.Empty; - } - - return subjectDescriptor.ToString(); - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AccessTokenResult.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AccessTokenResult.cs deleted file mode 100644 index 8e119b60e..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AccessTokenResult.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.WebApi; -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.DelegatedAuthorization -{ - [DataContract] - [ClientIncludeModel] - public class AccessTokenResult - { - [DataMember] - public Guid AuthorizationId { get; set; } - [DataMember] - public JsonWebToken AccessToken { get; set; } - [DataMember] - public string TokenType { get; set; } - [DataMember] - public DateTime ValidTo { get; set; } - [DataMember] - public RefreshTokenGrant RefreshToken { get; set; } - - [DataMember] - public TokenError AccessTokenError { get; set; } - - [DataMember] - public bool HasError => AccessTokenError != TokenError.None; - - [DataMember] - public string ErrorDescription { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AuthorizationGrant.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AuthorizationGrant.cs deleted file mode 100644 index e350e9064..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AuthorizationGrant.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.DelegatedAuthorization -{ - [KnownType(typeof(RefreshTokenGrant))] - [KnownType(typeof(JwtBearerAuthorizationGrant))] - [JsonConverter(typeof(AuthorizationGrantJsonConverter))] - public abstract class AuthorizationGrant - { - public AuthorizationGrant(GrantType grantType) - { - if (grantType == GrantType.None) - { - throw new ArgumentException("Grant type is required."); - } - - GrantType = grantType; - } - - [JsonConverter(typeof(StringEnumConverter))] - public GrantType GrantType { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AuthorizationGrantJsonConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AuthorizationGrantJsonConverter.cs deleted file mode 100644 index 967c27f23..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/AuthorizationGrantJsonConverter.cs +++ /dev/null @@ -1,50 +0,0 @@ -using GitHub.Services.WebApi; -using GitHub.Services.WebApi.Jwt; -using Newtonsoft.Json.Linq; -using System; - -namespace GitHub.Services.DelegatedAuthorization -{ - public class AuthorizationGrantJsonConverter : VssJsonCreationConverter - { - protected override AuthorizationGrant Create(Type objectType, JObject jsonObject) - { - var typeValue = jsonObject.GetValue(nameof(AuthorizationGrant.GrantType), StringComparison.OrdinalIgnoreCase); - if (typeValue == null) - { - throw new ArgumentException(WebApiResources.UnknownEntityType(typeValue)); - } - - GrantType grantType; - if (typeValue.Type == JTokenType.Integer) - { - grantType = (GrantType)(Int32)typeValue; - } - else if (typeValue.Type != JTokenType.String || !Enum.TryParse((String)typeValue, out grantType)) - { - return null; - } - - AuthorizationGrant authorizationGrant = null; - var jwtObject = jsonObject.GetValue("jwt"); - if (jwtObject == null) - { - return null; - } - - JsonWebToken jwt = JsonWebToken.Create(jwtObject.ToString()); - switch (grantType) - { - case GrantType.JwtBearer: - authorizationGrant = new JwtBearerAuthorizationGrant(jwt); - break; - - case GrantType.RefreshToken: - authorizationGrant = new RefreshTokenGrant(jwt); - break; - } - - return authorizationGrant; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/GrantType.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/GrantType.cs deleted file mode 100644 index 67634f660..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/GrantType.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace GitHub.Services.DelegatedAuthorization -{ - public enum GrantType - { - None = 0, - JwtBearer = 1, - RefreshToken = 2, - Implicit = 3, - ClientCredentials = 4, - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/JwtBearerAuthorizationGrant.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/JwtBearerAuthorizationGrant.cs deleted file mode 100644 index ccfc3c243..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/JwtBearerAuthorizationGrant.cs +++ /dev/null @@ -1,21 +0,0 @@ -using GitHub.Services.WebApi.Jwt; -using System.Runtime.Serialization; - -namespace GitHub.Services.DelegatedAuthorization -{ - public class JwtBearerAuthorizationGrant : AuthorizationGrant - { - public JwtBearerAuthorizationGrant(JsonWebToken jwt) - : base(GrantType.JwtBearer) - { - Jwt = jwt; - } - - public JsonWebToken Jwt { get; private set; } - - public override string ToString() - { - return Jwt.EncodedToken; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/RefreshTokenGrant.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/RefreshTokenGrant.cs deleted file mode 100644 index fb434ba27..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/RefreshTokenGrant.cs +++ /dev/null @@ -1,20 +0,0 @@ -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.DelegatedAuthorization -{ - public class RefreshTokenGrant : AuthorizationGrant - { - public RefreshTokenGrant(JsonWebToken jwt) - : base(GrantType.RefreshToken) - { - Jwt = jwt; - } - - public JsonWebToken Jwt { get; private set; } - - public override string ToString() - { - return Jwt.EncodedToken; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/TokenError.cs b/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/TokenError.cs deleted file mode 100644 index 4f44bfd03..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/DelegatedAuthorization/TokenError.cs +++ /dev/null @@ -1,39 +0,0 @@ -namespace GitHub.Services.DelegatedAuthorization -{ - public enum TokenError - { - None, - GrantTypeRequired, - AuthorizationGrantRequired, - ClientSecretRequired, - RedirectUriRequired, - InvalidAuthorizationGrant, - InvalidAuthorizationScopes, - InvalidRefreshToken, - AuthorizationNotFound, - AuthorizationGrantExpired, - AccessAlreadyIssued, - InvalidRedirectUri, - AccessTokenNotFound, - InvalidAccessToken, - AccessTokenAlreadyRefreshed, - InvalidClientSecret, - ClientSecretExpired, - ServerError, - AccessDenied, - AccessTokenKeyRequired, - InvalidAccessTokenKey, - FailedToGetAccessToken, - InvalidClientId, - InvalidClient, - InvalidValidTo, - InvalidUserId, - FailedToIssueAccessToken, - AuthorizationGrantScopeMissing, - InvalidPublicAccessTokenKey, - InvalidPublicAccessToken, - /* Deprecated */ - PublicFeatureFlagNotEnabled, - SSHPolicyDisabled - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FileContainer/Enumerations.cs b/src/Sdk/WebApi/WebApi/Contracts/FileContainer/Enumerations.cs deleted file mode 100644 index 788ea25a1..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FileContainer/Enumerations.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.FileContainer -{ - /// - /// Options a container can have. - /// - [Flags] - [DataContract] - public enum ContainerOptions - { - /// - /// No option. - /// - [EnumMember] - None = 0, - - ///// - ///// Encrypts content of the container. - ///// - //EncryptContent = 1 - } - - /// - /// Type of a container item. - /// - [DataContract] - public enum ContainerItemType - { - /// - /// Any item type. - /// - [EnumMember] - Any = 0, - - /// - /// Item is a folder which can have child items. - /// - [EnumMember] - Folder = 1, - - /// - /// Item is a file which is stored in the file service. - /// - [EnumMember] - File = 2, - } - - /// - /// Status of a container item. - /// - [DataContract] - public enum ContainerItemStatus - { - /// - /// Item is created. - /// - [EnumMember] - Created = 1, - - /// - /// Item is a file pending for upload. - /// - [EnumMember] - PendingUpload = 2 - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FileContainer/FileContainer.cs b/src/Sdk/WebApi/WebApi/Contracts/FileContainer/FileContainer.cs deleted file mode 100644 index e00fff597..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FileContainer/FileContainer.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Serialization; - -namespace GitHub.Services.FileContainer -{ - /// - /// Represents a container that encapsulates a hierarchical file system. - /// - [DataContract] - public class FileContainer - { - /// - /// Id. - /// - [DataMember(IsRequired = true)] - public Int64 Id { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Project Id. - /// - [DataMember(IsRequired = false)] - public Guid ScopeIdentifier { get;[EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Uri of the artifact associated with the container. - /// - [DataMember(IsRequired = true)] - public Uri ArtifactUri { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Security token of the artifact associated with the container. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String SecurityToken { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Name. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Name { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Description. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Description { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Total size of the files in bytes. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int64 Size { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Options the container can have. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ContainerOptions Options { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Identifier of the optional encryption key. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid SigningKeyId { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Owner. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid CreatedBy { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Creation date. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTime DateCreated { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Location of the item resource. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String ItemLocation { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Download Url for the content of this item. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String ContentLocation { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// ItemStore Locator for this container. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String LocatorPath { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - public override bool Equals(object obj) - { - FileContainer other = obj as FileContainer; - - if (other == null) - { - return false; - } - - return this.ArtifactUri == other.ArtifactUri && - this.Description == other.Description && - this.Id == other.Id && - this.Name == other.Name && - this.ScopeIdentifier == other.ScopeIdentifier; - } - - public override int GetHashCode() - { - return this.Id.GetHashCode(); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FileContainer/FileContainerItem.cs b/src/Sdk/WebApi/WebApi/Contracts/FileContainer/FileContainerItem.cs deleted file mode 100644 index e1c26e6c8..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FileContainer/FileContainerItem.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Serialization; -using System.Text; - -namespace GitHub.Services.FileContainer -{ - /// - /// Represents an item in a container. - /// - [DataContract] - public class FileContainerItem - { - /// - /// Container Id. - /// - [DataMember(IsRequired = true)] - public Int64 ContainerId { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Project Id. - /// - [DataMember(IsRequired = false)] - public Guid ScopeIdentifier { get;[EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Unique path that identifies the item. - /// - [DataMember(IsRequired = true)] - public String Path - { - get - { - return m_path; - } - [EditorBrowsable(EditorBrowsableState.Never)] - set - { - m_path = EnsurePathFormat(value); - } - } - - /// - /// Type of the item: Folder, File or String. - /// - [DataMember(IsRequired = true)] - public ContainerItemType ItemType { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Status of the item: Created or Pending Upload. - /// - [DataMember(IsRequired = true)] - public ContainerItemStatus Status { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Length of the file. Zero if not of a file. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int64 FileLength { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Hash value of the file. Null if not a file. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Byte[] FileHash { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Encoding of the file. Zero if not a file. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int32 FileEncoding { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Type of the file. Zero if not a file. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int32 FileType { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Creation date. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTime DateCreated { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Last modified date. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTime DateLastModified { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Creator. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid CreatedBy { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Modifier. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid LastModifiedBy { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Location of the item resource. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String ItemLocation { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Download Url for the content of this item. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String ContentLocation { get; [EditorBrowsable(EditorBrowsableState.Never)] set; } - - /// - /// Id of the file content. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public Int32 FileId { get; set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public byte[] ContentId { get; set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Ticket { get; set; } - - public static string EnsurePathFormat(string path) - { - if (string.IsNullOrWhiteSpace(path)) - { - return string.Empty; - } - - // We always make sure that the path is rooted - StringBuilder sb = new StringBuilder(); - String[] components = path.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries); - - if (components.Length == 0) - { - return string.Empty; - } - - for (int i = 0; i < components.Length; i++) - { - sb.AppendFormat("{0}{1}", components[i], i == components.Length - 1 ? String.Empty : "/"); - } - - return sb.ToString(); - } - - public override bool Equals(object obj) - { - FileContainerItem other = obj as FileContainerItem; - if (other == null) - { - return false; - } - return this.ContainerId == other.ContainerId && - this.ScopeIdentifier == other.ScopeIdentifier && - this.Path == other.Path && - this.ItemType == other.ItemType; - } - public override int GetHashCode() - { - return Path.GetHashCode(); - } - - private string m_path; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputDataType.cs b/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputDataType.cs deleted file mode 100644 index c2afa9212..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputDataType.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.FormInput -{ - /// - /// Enumerates data types that are supported as subscription input values. - /// - [DataContract] - public enum InputDataType - { - /// - /// No data type is specified. - /// - [EnumMember] - None = 0, - - /// - /// Represents a textual value. - /// - [EnumMember] - String = 10, - - /// - /// Represents a numberic value. - /// - [EnumMember] - Number = 20, - - /// - /// Represents a value of true or false. - /// - [EnumMember] - Boolean = 30, - - /// - /// Represents a Guid. - /// - [EnumMember] - Guid = 40, - - /// - /// Represents a URI. - /// - [EnumMember] - Uri = 50 - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputDescriptor.cs b/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputDescriptor.cs deleted file mode 100644 index a2586816c..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputDescriptor.cs +++ /dev/null @@ -1,130 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using GitHub.Services.WebApi; - -namespace GitHub.Services.FormInput -{ - /// - /// Describes an input for subscriptions. - /// - [DataContract] - public class InputDescriptor : ISecuredObject - { - /// - /// Identifier for the subscription input - /// - [DataMember] - public String Id { get; set; } - - /// - /// Localized name which can be shown as a label for the subscription input - /// - [DataMember] - public String Name { get; set; } - - /// - /// Description of what this input is used for - /// - [DataMember] - public String Description { get; set; } - - /// - /// Underlying data type for the input value. When this value is specified, - /// InputMode, Validation and Values are optional. - /// - [DataMember] - public string Type { get; set; } - - /// - /// List of scopes supported. Null indicates all scopes are supported. - /// - public List SupportedScopes { get; set; } - - /// - /// Custom properties for the input which can be used by the service provider - /// - [DataMember] - public IDictionary Properties { get; set; } - - /// - /// Mode in which the value of this input should be entered - /// - [DataMember] - public InputMode InputMode { get; set; } - - /// - /// Gets whether this input is confidential, such as for a password or application key - /// - [DataMember] - public Boolean IsConfidential { get; set; } - - /// - /// Gets whether this input is included in the default generated action description. - /// - /// - [DataMember] - public Boolean UseInDefaultDescription { get; set; } - - /// - /// The group localized name to which this input belongs and can be shown as a header - /// for the container that will include all the inputs in the group. - /// - [DataMember] - public String GroupName { get; set; } - - /// - /// A hint for input value. It can be used in the UI as the input placeholder. - /// - [DataMember] - public String ValueHint { get; set; } - - /// - /// Information to use to validate this input's value - /// - [DataMember(EmitDefaultValue = false)] - public InputValidation Validation { get; set; } - - /// - /// Information about possible values for this input - /// - [DataMember(EmitDefaultValue = false)] - public InputValues Values { get; set; } - - /// - /// The ids of all inputs that the value of this input is dependent on. - /// - [DataMember(EmitDefaultValue = false)] - public IList DependencyInputIds { get; set; } - - /// - /// If true, the value information for this input is dynamic and - /// should be fetched when the value of dependency inputs change. - /// - [DataMember(EmitDefaultValue = false)] - public Boolean HasDynamicValueInformation { get; set; } - - public void SetSecuredObjectProperties(Guid namespaceId, Int32 requiredPermissions, String token) - { - this.m_namespaceId = namespaceId; - this.m_requiredPermissions = requiredPermissions; - this.m_token = token; - - this.Validation?.SetSecuredObjectProperties(namespaceId, requiredPermissions, token); - this.Values?.SetSecuredObjectProperties(namespaceId, requiredPermissions, token); - } - - public Guid NamespaceId => m_namespaceId; - - public Int32 RequiredPermissions => m_requiredPermissions; - - public String GetToken() - { - return m_token; - } - - private Guid m_namespaceId; - private Int32 m_requiredPermissions; - private String m_token; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputMode.cs b/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputMode.cs deleted file mode 100644 index cd819ea9e..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputMode.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.FormInput -{ - /// - /// Mode in which a subscription input should be entered (in a UI) - /// - [DataContract] - public enum InputMode - { - /// - /// This input should not be shown in the UI - /// - [EnumMember] - None = 0, - - /// - /// An input text box should be shown - /// - [EnumMember] - TextBox = 10, - - /// - /// An password input box should be shown - /// - [EnumMember] - PasswordBox = 20, - - /// - /// A select/combo control should be shown - /// - [EnumMember] - Combo = 30, - - /// - /// Radio buttons should be shown - /// - [EnumMember] - RadioButtons = 40, - - /// - /// Checkbox should be shown(for true/false values) - /// - [EnumMember] - CheckBox = 50, - - /// - /// A multi-line text area should be shown - /// - [EnumMember] - TextArea = 60 - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputValidation.cs b/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputValidation.cs deleted file mode 100644 index c57de3670..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputValidation.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.WebApi; - -namespace GitHub.Services.FormInput -{ - /// - /// Describes what values are valid for a subscription input - /// - [DataContract] - public class InputValidation : ISecuredObject - { - /// - /// Gets or sets the data data type to validate. - /// - [DataMember(EmitDefaultValue = false)] - public InputDataType DataType { get; set; } - - /// - /// Gets or sets if this is a required field. - /// - [DataMember(EmitDefaultValue = false)] - public Boolean IsRequired { get; set; } - - /// - /// Gets or sets the pattern to validate. - /// - [DataMember(EmitDefaultValue = false)] - public String Pattern { get; set; } - - /// - /// Gets or sets the error on pattern mismatch. - /// - [DataMember(EmitDefaultValue = false)] - public String PatternMismatchErrorMessage { get; set; } - - /// - /// Gets or sets the minimum value for this descriptor. - /// - [DataMember(EmitDefaultValue = false)] - public Decimal? MinValue { get; set; } - - /// - /// Gets or sets the minimum value for this descriptor. - /// - [DataMember(EmitDefaultValue = false)] - public Decimal? MaxValue { get; set; } - - /// - /// Gets or sets the minimum length of this descriptor. - /// - [DataMember(EmitDefaultValue = false)] - public Int32? MinLength { get; set; } - - /// - /// Gets or sets the maximum length of this descriptor. - /// - [DataMember(EmitDefaultValue = false)] - public Int32? MaxLength { get; set; } - - public void SetSecuredObjectProperties(Guid namespaceId, int requiredPermissions, string token) - { - this.m_namespaceId = namespaceId; - this.m_requiredPermissions = requiredPermissions; - this.m_token = token; - } - - public Guid NamespaceId => m_namespaceId; - - public int RequiredPermissions => m_requiredPermissions; - - public string GetToken() - { - return m_token; - } - - private Guid m_namespaceId; - private int m_requiredPermissions; - private string m_token; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputValues.cs b/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputValues.cs deleted file mode 100644 index 1ae8d80bc..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/FormInput/InputValues.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using GitHub.Services.WebApi; - -namespace GitHub.Services.FormInput -{ - /// - /// Information about the possible/allowed values for a given subscription input - /// - [DataContract] - public class InputValues : ISecuredObject - { - /// - /// The id of the input - /// - [DataMember(EmitDefaultValue = false)] - public String InputId { get; set; } - - /// - /// The default value to use for this input - /// - [DataMember(EmitDefaultValue = false)] - public String DefaultValue { get; set; } - - /// - /// Possible values that this input can take - /// - [DataMember(EmitDefaultValue = false)] - public IList PossibleValues { get; set; } - - /// - /// Should the value be restricted to one of the values in the PossibleValues (True) - /// or are the values in PossibleValues just a suggestion (False) - /// - [DataMember(EmitDefaultValue = false)] - public Boolean IsLimitedToPossibleValues { get; set; } - - /// - /// Should this input be disabled - /// - [DataMember(EmitDefaultValue = false)] - public Boolean IsDisabled { get; set; } - - /// - /// Should this input be made read-only - /// - [DataMember(EmitDefaultValue = false)] - public Boolean IsReadOnly { get; set; } - - /// - /// Errors encountered while computing dynamic values. - /// - /// - [DataMember(EmitDefaultValue = false)] - public InputValuesError Error { get; set; } - - public void SetSecuredObjectProperties(Guid namespaceId, Int32 requiredPermissions, String token) - { - this.m_namespaceId = namespaceId; - this.m_requiredPermissions = requiredPermissions; - this.m_token = token; - - this.Error?.SetSecuredObjectProperties(namespaceId, requiredPermissions, token); - if (this.PossibleValues != null && this.PossibleValues.Any()) - { - foreach (var value in this.PossibleValues) - { - value.SetSecuredObjectProperties(namespaceId, requiredPermissions, token); - } - } - } - - public Guid NamespaceId => m_namespaceId; - - public Int32 RequiredPermissions => m_requiredPermissions; - - public String GetToken() - { - return m_token; - } - - private Guid m_namespaceId; - private Int32 m_requiredPermissions; - private String m_token; - } - - /// - /// Information about a single value for an input - /// - [DataContract] - public class InputValue : ISecuredObject - { - /// - /// The value to store for this input - /// - [DataMember] - public String Value { get; set; } - - /// - /// The text to show for the display of this value - /// - [DataMember(EmitDefaultValue = false)] - public String DisplayValue { get; set; } - - /// - /// Any other data about this input - /// - [DataMember(EmitDefaultValue = false)] - public IDictionary Data { get; set; } - - public void SetSecuredObjectProperties(Guid namespaceId, Int32 requiredPermissions, String token) - { - this.m_namespaceId = namespaceId; - this.m_requiredPermissions = requiredPermissions; - this.m_token = token; - } - - public Guid NamespaceId => m_namespaceId; - - public Int32 RequiredPermissions => m_requiredPermissions; - - public String GetToken() - { - return m_token; - } - - private Guid m_namespaceId; - private Int32 m_requiredPermissions; - private String m_token; - } - - /// - /// Error information related to a subscription input value. - /// - [DataContract] - public class InputValuesError : ISecuredObject - { - /// - /// The error message. - /// - [DataMember] - public String Message { get; set; } - - public void SetSecuredObjectProperties(Guid namespaceId, Int32 requiredPermissions, String token) - { - this.m_namespaceId = namespaceId; - this.m_requiredPermissions = requiredPermissions; - this.m_token = token; - } - - public Guid NamespaceId => m_namespaceId; - - public Int32 RequiredPermissions => m_requiredPermissions; - - public String GetToken() - { - return m_token; - } - - private Guid m_namespaceId; - private Int32 m_requiredPermissions; - private String m_token; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroup.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroup.cs deleted file mode 100644 index e790bd5cf..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroup.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using IdentityDescriptor = GitHub.Services.Identity.IdentityDescriptor; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Graph group entity - /// - [DataContract] - public class GraphGroup : GraphMember - { - public override string SubjectKind => Constants.SubjectKind.Group; - - /// - /// A short phrase to help human readers disambiguate groups with similar names - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string Description { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal string SpecialType { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeSpecialType() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal Guid ScopeId { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeScopeId() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal string ScopeType { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeScopeType() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal string ScopeName { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeScopeName() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal Guid LocalScopeId { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeLocalScopeId() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal Guid SecuringHostId { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeSecuringHostId() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal bool IsRestrictedVisible { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeIsRestrictedVisible() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal bool IsCrossProject { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeIsIsCrossProject() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal bool IsGlobalScope { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeIsGlobalScope() => ShoudSerializeInternals; - - [DataMember(IsRequired = false, EmitDefaultValue = false), EditorBrowsable(EditorBrowsableState.Never), ClientInternalUseOnly] - internal bool IsDeleted { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - internal GraphGroup( - string origin, - string originId, - SubjectDescriptor descriptor, - IdentityDescriptor legacyDescriptor, - string displayName, - ReferenceLinks links, - string url, - string domain, - string principalName, - string mailAddress, - string description, - string specialType, - Guid scopeId, - string scopeType, - string scopeName, - Guid localScopeId, - Guid securingHostId, - bool isRestrictedVisible, - bool isCrossProject, - bool isGlobalScope, - bool isDeleted) - : base(origin, originId, descriptor, legacyDescriptor, displayName, links, url, domain, principalName, mailAddress) - { - Description = description; - SpecialType = specialType; - ScopeId = scopeId; - ScopeType = scopeType; - ScopeName = scopeName; - LocalScopeId = localScopeId; - SecuringHostId = securingHostId; - IsRestrictedVisible = isRestrictedVisible; - IsCrossProject = isCrossProject; - IsGlobalScope = isGlobalScope; - IsDeleted = isDeleted; - } - - // this is how we replace/overwrite parameters and create a new object - // and keep our internal objects immutable - [EditorBrowsable(EditorBrowsableState.Never)] - internal GraphGroup( - GraphGroup group, - string origin = null, - string originId = null, - SubjectDescriptor? descriptor = null, - IdentityDescriptor legacyDescriptor = null, - string displayName = null, - ReferenceLinks links = null, - string url = null, - string domain = null, - string principalName = null, - string mailAddress = null, - string description = null, - string specialType = null, - Guid? scopeId = null, - string scopeType = null, - string scopeName = null, - Guid? localScopeId = null, - Guid? securingHostId = null, - bool? isRestrictedVisible = null, - bool? isCrossProject = null, - bool? isGlobalScope = null, - bool? isDeleted = null) - : this(origin ?? group?.Origin, - originId ?? group?.OriginId, - descriptor ?? group?.Descriptor ?? default(SubjectDescriptor), - legacyDescriptor ?? group?.LegacyDescriptor ?? default(IdentityDescriptor), - displayName ?? group?.DisplayName, - links ?? group?.Links, - url ?? group?.Url, - domain ?? group?.Domain, - principalName ?? group?.PrincipalName, - mailAddress ?? group?.MailAddress, - description ?? group?.Description, - specialType ?? group?.SpecialType, - scopeId ?? group?.ScopeId ?? default(Guid), - scopeType ?? group?.ScopeType, - scopeName ?? group?.ScopeName, - localScopeId ?? group?.LocalScopeId ?? default(Guid), - securingHostId ?? group?.SecuringHostId ?? default(Guid), - isRestrictedVisible ?? group?.IsRestrictedVisible ?? default(bool), - isCrossProject ?? group?.IsCrossProject ?? default(bool), - isGlobalScope ?? group?.IsGlobalScope ?? default(bool), - isDeleted ?? group?.IsDeleted ?? default(bool)) - { } - - // only for serialization - protected GraphGroup() { } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroupCreationContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroupCreationContext.cs deleted file mode 100644 index 515111d3a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroupCreationContext.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using Newtonsoft.Json; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Do not attempt to use this type to create a new group. This - /// type does not contain sufficient fields to create a new group. - /// - [DataContract] - [JsonConverter(typeof(GraphGroupCreationContextJsonConverter))] - public abstract class GraphGroupCreationContext - { - /// - /// Optional: If provided, we will use this identifier for the storage key of the created group - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid StorageKey { get; set; } - } - - /// - /// Use this type to create a new group using the OriginID as a reference to an existing group from an external - /// AD or AAD backed provider. This is the subset of GraphGroup fields required for creation of - /// a group for the AD and AAD use case. - /// - [DataContract] - public class GraphGroupOriginIdCreationContext : GraphGroupCreationContext - { - /// - /// This should be the object id or sid of the group from the source AD or AAD provider. - /// Example: d47d025a-ce2f-4a79-8618-e8862ade30dd - /// Team Services will communicate with the source provider to fill all other fields on creation. - /// - [DataMember(IsRequired = true)] - public string OriginId { get; set; } - } - - /// - /// Use this type to create a new group using the mail address as a reference to an existing group from an external - /// AD or AAD backed provider. This is the subset of GraphGroup fields required for creation of - /// a group for the AAD and AD use case. - /// - [DataContract] - public class GraphGroupMailAddressCreationContext : GraphGroupCreationContext - { - /// - /// This should be the mail address or the group in the source AD or AAD provider. - /// Example: jamal@contoso.com - /// Team Services will communicate with the source provider to fill all other fields on creation. - /// - [DataMember(IsRequired = true)] - public string MailAddress { get; set; } - } - - /// - /// Use this type to create a new Vsts group that is not backed by an external provider. - /// - [DataContract] - public class GraphGroupVstsCreationContext : GraphGroupCreationContext - { - /// - /// Used by VSTS groups; if set this will be the group DisplayName, otherwise ignored - /// - [DataMember(IsRequired = true)] - public string DisplayName { get; set; } - - /// - /// Used by VSTS groups; if set this will be the group description, otherwise ignored - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string Description { get; set; } - - /// - /// Internal use only. An optional sid to use for group creation. - /// - public SubjectDescriptor Descriptor { get; set; } - - - [DataMember(Name = "Descriptor", IsRequired = false, EmitDefaultValue = false)] - private string DescriptorString - { - get { return Descriptor.ToString(); } - set { Descriptor = SubjectDescriptor.FromString(value); } - } - /// - /// For internal use only in back compat scenarios. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool CrossProject { get; set; } - - /// - /// For internal use only in back compat scenarios. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool RestrictedVisibility { get; set; } - - /// - /// For internal use only in back compat scenarios. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string SpecialGroupType { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroupCreationContextJsonConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroupCreationContextJsonConverter.cs deleted file mode 100644 index a605270d0..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphGroupCreationContextJsonConverter.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Linq; -using Newtonsoft.Json.Linq; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Graph.Client -{ - public class GraphGroupCreationContextJsonConverter : VssJsonCreationConverter - { - protected override GraphGroupCreationContext Create(Type objectType, JObject jsonObject) - { - // enforce origin id or principalname or displayName - var hasOriginId = jsonObject["originId"] != null; - var hasMailAddress = jsonObject["mailAddress"] != null; - var hasDisplayName = jsonObject["displayName"] != null; - var requiredFields = new bool[] - { - hasOriginId, - hasDisplayName, - hasMailAddress - }; - - if (requiredFields.Count(b => b) > 1) - { - throw new ArgumentNullException(WebApiResources.GraphGroupMissingRequiredFields()); - } - - if (hasOriginId) - { - return new GraphGroupOriginIdCreationContext(); - } - - if (hasMailAddress) - { - return new GraphGroupMailAddressCreationContext(); - } - - if (hasDisplayName) - { - return new GraphGroupVstsCreationContext(); - } - - throw new ArgumentException(WebApiResources.GraphGroupMissingRequiredFields()); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphMember.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphMember.cs deleted file mode 100644 index 4e150be7d..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphMember.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using IdentityDescriptor = GitHub.Services.Identity.IdentityDescriptor; - -namespace GitHub.Services.Graph.Client -{ - [DataContract] - public abstract class GraphMember : GraphSubject - { - /// - /// This represents the name of the container of origin for a graph member. - /// (For MSA this is "Windows Live ID", for AD the name of the domain, for AAD the - /// tenantID of the directory, for VSTS groups the ScopeId, etc) - /// - [DataMember(IsRequired = false, EmitDefaultValue = true)] - public string Domain { get; private set; } - - /// - /// This is the PrincipalName of this graph member from the source provider. The source - /// provider may change this field over time and it is not guaranteed to be immutable - /// for the life of the graph member by VSTS. - /// - [DataMember] - public string PrincipalName { get; private set; } - - /// - /// The email address of record for a given graph member. This may be different - /// than the principal name. - /// - [DataMember(IsRequired = false, EmitDefaultValue = true)] - public string MailAddress { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - protected GraphMember( - string origin, - string originId, - SubjectDescriptor descriptor, - IdentityDescriptor legacyDescriptor, - string displayName, - ReferenceLinks links, - string url, - string domain, - string principalName, - string mailAddress) - : base(origin, originId, descriptor, legacyDescriptor, displayName, links, url) - { - Domain = domain; - PrincipalName = principalName; - MailAddress = mailAddress; - } - - // only for serialization - protected GraphMember() { } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphScope.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphScope.cs deleted file mode 100644 index 362d29597..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphScope.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using GroupScopeType = GitHub.Services.Identity.GroupScopeType; -using IdentityDescriptor = GitHub.Services.Identity.IdentityDescriptor; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Container where a graph entity is defined (organization, project, team) - /// - [DataContract] - public class GraphScope : GraphSubject - { - public override string SubjectKind => Constants.SubjectKind.Scope; - - /// - /// The subject descriptor that references the administrators group for this scope. Only - /// members of this group can change the contents of this scope or assign other users - /// permissions to access this scope. - /// - public SubjectDescriptor AdministratorDescriptor { get; private set; } - - /// - /// The subject descriptor that references the administrators group for this scope. Only - /// members of this group can change the contents of this scope or assign other users - /// permissions to access this scope. - /// - [DataMember(Name = "AdministratorDescriptor", IsRequired = false, EmitDefaultValue = false)] - private string AdministratorString - { - get { return AdministratorDescriptor.ToString(); } - set { AdministratorDescriptor = SubjectDescriptor.FromString(value); } - } - - /// - /// When true, this scope is also a securing host for one or more scopes. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool IsGlobal { get; private set; } - - /// - /// The subject descriptor of the parent scope. - /// - public SubjectDescriptor ParentDescriptor { get; private set; } - - /// - /// The subject descriptor for the closest account or organization in the - /// ancestor tree of this scope. - /// - [DataMember(Name = "ParentDescriptor", IsRequired = false, EmitDefaultValue = false)] - private string ParentDescriptorString - { - get { return ParentDescriptor.ToString(); } - set { ParentDescriptor = SubjectDescriptor.FromString(value); } - } - - /// - /// The subject descriptor for the containing organization in the ancestor tree - /// of this scope. - /// - public SubjectDescriptor SecuringHostDescriptor { get; private set; } - - /// - /// The subject descriptor for the containing organization in the ancestor tree - /// of this scope. - /// - [DataMember(Name = "SecuringHostDescriptor", IsRequired = false, EmitDefaultValue = false)] - private string SecuringHostDescriptorString - { - get { return SecuringHostDescriptor.ToString(); } - set { SecuringHostDescriptor = SubjectDescriptor.FromString(value); } - } - - /// - /// The type of this scope. Typically ServiceHost or TeamProject. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public GroupScopeType ScopeType { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - internal GraphScope( - string origin, - string originId, - SubjectDescriptor descriptor, - IdentityDescriptor legacyDescriptor, - string displayName, - ReferenceLinks links, - string url, - SubjectDescriptor administratorDescriptor, - bool isGlobal, - SubjectDescriptor parentDescriptor, - SubjectDescriptor securingHostDescriptor, - GroupScopeType scopeType = GroupScopeType.Generic) - : base(origin, originId, descriptor, legacyDescriptor, displayName, links, url) - { - AdministratorDescriptor = administratorDescriptor; - IsGlobal = isGlobal; - ParentDescriptor = parentDescriptor; - SecuringHostDescriptor = securingHostDescriptor; - ScopeType = scopeType; - } - - // this is how we replace/overwrite parameters and create a new object - // and keep our internal objects immutable - internal GraphScope( - GraphScope scope, - string origin = null, - string originId = null, - SubjectDescriptor? descriptor = null, - IdentityDescriptor legacyDescriptor = null, - string displayName = null, - ReferenceLinks links = null, - string url = null, - SubjectDescriptor? administrator = null, - bool? isGlobal = null, - SubjectDescriptor? parentDescriptor = null, - SubjectDescriptor? securingHostDescriptor = null, - GroupScopeType? scopeType = GroupScopeType.Generic) - : this(origin ?? scope?.Origin, - originId ?? scope?.OriginId, - descriptor ?? scope?.Descriptor ?? default(SubjectDescriptor), - legacyDescriptor ?? scope?.LegacyDescriptor ?? default(IdentityDescriptor), - displayName ?? scope?.DisplayName, - links ?? scope?.Links, - url ?? scope?.Url, - administrator ?? scope?.AdministratorDescriptor ?? default(SubjectDescriptor), - isGlobal ?? scope?.IsGlobal ?? default(bool), - parentDescriptor ?? scope?.ParentDescriptor ?? default(SubjectDescriptor), - securingHostDescriptor ?? scope?.SecuringHostDescriptor ?? default(SubjectDescriptor), - scopeType ?? scope?.ScopeType ?? default(GroupScopeType)) - { } - - // only for serialization - protected GraphScope() { } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubject.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubject.cs deleted file mode 100644 index fc48a5bd9..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubject.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using Newtonsoft.Json; -using IdentityDescriptor = GitHub.Services.Identity.IdentityDescriptor; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Top-level graph entity - /// - [DataContract] - [JsonConverter(typeof(GraphSubjectJsonConverter))] - public abstract class GraphSubject : GraphSubjectBase - { - /// - /// This field identifies the type of the graph subject (ex: Group, Scope, User). - /// - [DataMember] - public abstract string SubjectKind { get; } - - /// - /// The type of source provider for the origin identifier (ex:AD, AAD, MSA) - /// - [DataMember] - public string Origin { get; private set; } - - /// - /// The unique identifier from the system of origin. Typically a sid, object id or Guid. Linking - /// and unlinking operations can cause this value to change for a user because the user is not - /// backed by a different provider and has a different unique id in the new provider. - /// - [DataMember] - public string OriginId { get; private set; } - - /// - /// [Internal Use Only] The legacy descriptor is here in case you need to access old version IMS using identity descriptor. - /// - [ClientInternalUseOnly] - internal IdentityDescriptor LegacyDescriptor { get; private set; } - - /// - /// [Internal Use Only] The legacy descriptor is here in case you need to access old version IMS using identity descriptor. - /// - [DataMember(Name = "LegacyDescriptor", IsRequired = false, EmitDefaultValue = false)] - private string LegacyDescriptorString - { - get { return LegacyDescriptor?.ToString(); } - set { LegacyDescriptor = IdentityDescriptor.FromString(value); } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeLegacyDescriptorString() => ShoudSerializeInternals; - - [ClientInternalUseOnly] - internal bool ShoudSerializeInternals; - - // only for serialization - protected GraphSubject() { } - - [EditorBrowsable(EditorBrowsableState.Never)] - protected GraphSubject( - string origin, - string originId, - SubjectDescriptor descriptor, - IdentityDescriptor legacyDescriptor, - string displayName, - ReferenceLinks links, - string url) : base(descriptor, displayName, links, url) - { - Origin = origin; - OriginId = originId; - LegacyDescriptor = legacyDescriptor; - ShoudSerializeInternals = false; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubjectBase.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubjectBase.cs deleted file mode 100644 index 71d1cd095..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubjectBase.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.ComponentModel; -using System.Runtime.Serialization; -using System.Xml; -using System.Xml.Schema; -using System.Xml.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using GitHub.Services.WebApi.Xml; -using Newtonsoft.Json; - -namespace GitHub.Services.Graph.Client -{ - [JsonObject(MemberSerialization = MemberSerialization.OptIn)] - [XmlSerializableDataContract] - public abstract class GraphSubjectBase : IXmlSerializable - { - /// The descriptor is the primary way to reference the graph subject while the system is running. This field - /// will uniquely identify the same graph subject across both Accounts and Organizations. - /// - public SubjectDescriptor Descriptor { get; protected set; } - - /// - /// The descriptor is the primary way to reference the graph subject while the system is running. This field - /// will uniquely identify the same graph subject across both Accounts and Organizations. - /// - [DataMember(Name = "Descriptor", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "Descriptor", DefaultValueHandling = DefaultValueHandling.Ignore)] - private string DescriptorString - { - get { return Descriptor.ToString(); } - set { Descriptor = SubjectDescriptor.FromString(value); } - } - - /// - /// This is the non-unique display name of the graph subject. To change this field, you must alter its value in the - /// source provider. - /// - [DataMember] - [JsonProperty] - public string DisplayName { get; protected set; } - - /// - /// This field contains zero or more interesting links about the graph subject. These links may be invoked to obtain additional - /// relationships or more detailed information about this graph subject. - /// - [DataMember(Name = "_links", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "_links", DefaultValueHandling = DefaultValueHandling.Ignore)] - [XmlIgnore] // ReferenceLinks type does not currently support XML serialization (#1164908 for tracking) - public ReferenceLinks Links { get; protected set; } - - /// - /// This url is the full route to the source resource of this graph subject. - /// - [DataMember(EmitDefaultValue = false)] - [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] - public string Url { get; protected set; } - - // only for serialization - protected GraphSubjectBase() { } - - [EditorBrowsable(EditorBrowsableState.Never)] - protected GraphSubjectBase( - SubjectDescriptor descriptor, - string displayName, - ReferenceLinks links, - string url) - { - Descriptor = descriptor; - DisplayName = displayName; - Links = links; - Url = url; - } - - XmlSchema IXmlSerializable.GetSchema() { return null; } - - void IXmlSerializable.ReadXml(XmlReader reader) => reader.ReadDataMemberXml(this); - - void IXmlSerializable.WriteXml(XmlWriter writer) => writer.WriteDataMemberXml(this); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubjectJsonConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubjectJsonConverter.cs deleted file mode 100644 index 0953b7186..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSubjectJsonConverter.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using GitHub.Services.WebApi; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.Graph.Client -{ - public class GraphSubjectJsonConverter : VssJsonCreationConverter - { - protected override GraphSubject Create(Type objectType, JObject jsonObject) - { - var subjectKindObject = jsonObject.GetValue(nameof(GraphSubject.SubjectKind), StringComparison.OrdinalIgnoreCase); - if (subjectKindObject == null) - { - throw new ArgumentException(WebApiResources.UnknownEntityType(subjectKindObject)); - } - var typeName = subjectKindObject.ToString(); - switch (typeName) - { - case Constants.SubjectKind.Group: - var groupInfo = typeof(GraphGroup).GetTypeInfo(); - var graphGroupConstructor = groupInfo.DeclaredConstructors.First(x => x.GetParameters().Length == 0); - return (GraphGroup)graphGroupConstructor.Invoke(null); - case Constants.SubjectKind.Scope: - var scopeInfo = typeof(GraphScope).GetTypeInfo(); - var graphScopeConstructor = scopeInfo.DeclaredConstructors.First(x => x.GetParameters().Length == 0); - return (GraphScope)graphScopeConstructor.Invoke(null); - case Constants.SubjectKind.User: - var userInfo = typeof(GraphUser).GetTypeInfo(); - var graphUserConstructor = userInfo.DeclaredConstructors.First(x => x.GetParameters().Length == 0); - return (GraphUser)graphUserConstructor.Invoke(null); - case Constants.SubjectKind.SystemSubject: - var systemSubjectInfo = typeof(GraphSystemSubject).GetTypeInfo(); - var graphSystemSubjectConstructor = systemSubjectInfo.DeclaredConstructors.First(x => x.GetParameters().Length == 0); - return (GraphSystemSubject)graphSystemSubjectConstructor.Invoke(null); - default: - throw new ArgumentException(WebApiResources.UnknownEntityType(typeName)); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSystemSubject.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSystemSubject.cs deleted file mode 100644 index 7a26f2e37..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphSystemSubject.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using IdentityDescriptor = GitHub.Services.Identity.IdentityDescriptor; - -namespace GitHub.Services.Graph.Client -{ - [DataContract] - public class GraphSystemSubject : GraphSubject - { - public override string SubjectKind => Constants.SubjectKind.SystemSubject; - - [EditorBrowsable(EditorBrowsableState.Never)] - internal GraphSystemSubject( - string origin, - string originId, - SubjectDescriptor descriptor, - IdentityDescriptor legacyDescriptor, - string displayName, - ReferenceLinks links, - string url) - : base(origin, originId, descriptor, legacyDescriptor, displayName, links, url) - { - } - - // only for serialization - protected GraphSystemSubject() { } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUser.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUser.cs deleted file mode 100644 index 5dd2cc866..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUser.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using IdentityDescriptor = GitHub.Services.Identity.IdentityDescriptor; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Graph user entity - /// - [DataContract] - public class GraphUser : GraphMember - { - public override string SubjectKind => Constants.SubjectKind.User; - - /// - /// The meta type of the user in the origin, such as "member", "guest", etc. - /// See for the set of possible values. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string MetaType { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false), ClientInternalUseOnly] - internal DateTime MetadataUpdateDate { get; private set; } - - /// - /// The short, generally unique name for the user in the backing directory. - /// For AAD users, this corresponds to the mail nickname, which is often but not necessarily similar - /// to the part of the user's mail address before the @ sign. - /// For GitHub users, this corresponds to the GitHub user handle. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string DirectoryAlias { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual bool ShouldSerializeMetadataUpdateDate() => ShoudSerializeInternals; - - /// - /// When true, the group has been deleted in the identity provider - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool IsDeletedInOrigin { get; private set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - internal GraphUser( - string origin, - string originId, - SubjectDescriptor descriptor, - IdentityDescriptor legacyDescriptor, - string displayName, - ReferenceLinks links, - string url, - string domain, - string principalName, - string mailAddress, - string metaType, - DateTime metadataUpdateDate, - bool isDeletedInOrigin, - string directoryAlias) - : base(origin, originId, descriptor, legacyDescriptor, displayName, links, url, domain, principalName, mailAddress) - { - MetaType = metaType; - MetadataUpdateDate = metadataUpdateDate; - IsDeletedInOrigin = isDeletedInOrigin; - DirectoryAlias = directoryAlias; - } - - // this is how we replace/overwrite parameters and create a new object - // and keep our internal objects immutable - internal GraphUser( - GraphUser user, - string origin = null, - string originId = null, - SubjectDescriptor? descriptor = null, - IdentityDescriptor legacyDescriptor = null, - string displayName = null, - ReferenceLinks links = null, - string url = null, - string domain = null, - string principalName = null, - string mailAddress = null, - string metaType = null, - DateTime? metadataUpdateDate = null, - bool? isDeletedInOrigin = false, - string directoryAlias = null) - : this(origin ?? user?.Origin, - originId ?? user?.OriginId, - descriptor ?? user?.Descriptor ?? default(SubjectDescriptor), - legacyDescriptor ?? user?.LegacyDescriptor ?? default(IdentityDescriptor), - displayName ?? user?.DisplayName, - links ?? user?.Links, - url ?? user?.Url, - domain ?? user?.Domain, - principalName ?? user?.PrincipalName, - mailAddress ?? user?.MailAddress, - metaType ?? user?.MetaType, - metadataUpdateDate ?? user?.MetadataUpdateDate ?? DateTime.MinValue, - isDeletedInOrigin ?? user?.IsDeletedInOrigin ?? default, - directoryAlias ?? user?.DirectoryAlias) - { } - - // only for serialization - protected GraphUser() { } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserCreationContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserCreationContext.cs deleted file mode 100644 index 2350e8c08..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserCreationContext.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Runtime.Serialization; -using Newtonsoft.Json; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Do not attempt to use this type to create a new user. Use - /// one of the subclasses instead. This type does not contain - /// sufficient fields to create a new user. - /// - [DataContract] - [JsonConverter(typeof(GraphUserCreationContextJsonConverter))] - public abstract class GraphUserCreationContext - { - /// - /// Optional: If provided, we will use this identifier for the storage key of the created user - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid StorageKey { get; set; } - } - - /// - /// Use this type to create a new user using the OriginID as a reference to an existing user from an external - /// AD or AAD backed provider. This is the subset of GraphUser fields required for creation of - /// a GraphUser for the AD and AAD use case when looking up the user by its unique ID in the backing provider. - /// - [DataContract] - public class GraphUserOriginIdCreationContext : GraphUserCreationContext - { - /// - /// This should be the object id or sid of the user from the source AD or AAD provider. - /// Example: d47d025a-ce2f-4a79-8618-e8862ade30dd - /// Team Services will communicate with the source provider to fill all other fields on creation. - /// - [DataMember(IsRequired = true)] - public string OriginId { get; set; } - - - /// - /// This should be the name of the origin provider. - /// Example: github.com - /// - [DataMember(IsRequired = false)] - public string Origin { get; set; } - } - - /// - /// Use this type to create a new user using the principal name as a reference to an existing user from an external - /// AD or AAD backed provider. This is the subset of GraphUser fields required for creation of - /// a GraphUser for the AD and AAD use case when looking up the user by its principal name in the backing provider. - /// - [DataContract] - public class GraphUserPrincipalNameCreationContext : GraphUserCreationContext - { - /// - /// This should be the principal name or upn of the user in the source AD or AAD provider. - /// Example: jamal@contoso.com - /// Team Services will communicate with the source provider to fill all other fields on creation. - /// - [DataMember(IsRequired = true)] - public string PrincipalName { get; set; } - } - - /// - /// Use this type to create a new user using the mail address as a reference to an existing user from an external - /// AD or AAD backed provider. This is the subset of GraphUser fields required for creation of - /// a GraphUser for the AD and AAD use case when looking up the user by its mail address in the backing provider. - /// - [DataContract] - public class GraphUserMailAddressCreationContext : GraphUserCreationContext - { - /// - /// This should be the mail address of the user in the source AD or AAD provider. - /// Example: Jamal.Hartnett@contoso.com - /// Team Services will communicate with the source provider to fill all other fields on creation. - /// - { - protected override GraphUserCreationContext Create(Type objectType, JObject jsonObject) - { - // enforce origin id or principalname or displayName - var hasOriginId = jsonObject["originId"] != null; - var hasPrincipalName = jsonObject["principalName"] != null; - var hasMailAddress = jsonObject["mailAddress"] != null; - var requiredFields = new bool[] - { - hasOriginId, - hasPrincipalName, - hasMailAddress, - }; - - if (requiredFields.Count(b => b) != 1) - { - throw new ArgumentException(WebApiResources.GraphUserMissingRequiredFields()); - } - - if (hasOriginId) - { - return new GraphUserOriginIdCreationContext(); - } - - if (hasPrincipalName) - { - return new GraphUserPrincipalNameCreationContext(); - } - - if (hasMailAddress) - { - return new GraphUserMailAddressCreationContext(); - } - - throw new ArgumentException(WebApiResources.GraphUserMissingRequiredFields()); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserUpdateContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserUpdateContext.cs deleted file mode 100644 index 9a50f3aaf..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserUpdateContext.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Runtime.Serialization; -using Newtonsoft.Json; -using System.ComponentModel; - -namespace GitHub.Services.Graph.Client -{ - /// - /// Do not attempt to use this type to update user. Use - /// one of the subclasses instead. This type does not contain - /// sufficient fields to create a new user. - /// - [DataContract] - [JsonConverter(typeof(GraphUserUpdateContextJsonConverter))] - public abstract class GraphUserUpdateContext - { - /// - /// Storage key should not be specified in case of updating user - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [EditorBrowsable(EditorBrowsableState.Never), Obsolete()] - public Guid StorageKey { get; set; } - - //Currently there's a bug on the client generator that if a class doesn't have data member, it wouldn't get generated - //We're adding a temporary data member here in order to get passed that issue - //BUG 1466336 has been created to track this issue. Once the bug is fixed, we'll remove this data member. - //Marking it as obsolete and never use for now to ensure no one can access - } - /// - /// Use this type to update an existing user using the OriginID as a reference to an existing user from an external - /// AD or AAD backed provider. This is the subset of GraphUser fields required for creation of - /// a GraphUser for the AD and AAD use case when looking up the user by its unique ID in the backing provider. - /// - [DataContract] - public class GraphUserOriginIdUpdateContext : GraphUserUpdateContext - { - /// - /// This should be the object id or sid of the user from the source AD or AAD provider. - /// Example: d47d025a-ce2f-4a79-8618-e8862ade30dd - /// Azure Devops will communicate with the source provider to fill all other fields on creation. - /// - [DataMember(IsRequired = true)] - public string OriginId { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserUpdateContextJsonConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserUpdateContextJsonConverter.cs deleted file mode 100644 index 859004236..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Client/GraphUserUpdateContextJsonConverter.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Linq; -using Newtonsoft.Json.Linq; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Graph.Client -{ - public class GraphUserUpdateContextJsonConverter : VssJsonCreationConverter - { - protected override GraphUserUpdateContext Create(Type objectType, JObject jsonObject) - { - // enforce origin id or principalname or displayName - var hasOriginId = jsonObject["originId"] != null; - - var requiredFields = new bool[] - { - hasOriginId - }; - - if (requiredFields.Count(b => b) != 1) - { - throw new ArgumentException(WebApiResources.GraphUserMissingRequiredFields()); - } - - if (hasOriginId) - { - return new GraphUserOriginIdUpdateContext(); - } - - throw new ArgumentException(WebApiResources.GraphUserMissingRequiredFields()); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Graph/Constants.cs b/src/Sdk/WebApi/WebApi/Contracts/Graph/Constants.cs deleted file mode 100644 index 5245b4426..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Graph/Constants.cs +++ /dev/null @@ -1,198 +0,0 @@ -using System; -using System.Collections.Generic; -using GitHub.Services.Common; - -namespace GitHub.Services.Graph -{ - public static class Constants - { - static Constants() - { - // For the normalization of incoming IdentityType strings. - // This is an optimization; it is not required that any particular IdentityType values - // appear in this list, but it helps performance to have common values here - var subjectTypeMap = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { SubjectType.AadUser, SubjectType.AadUser }, - { SubjectType.MsaUser, SubjectType.MsaUser }, - { SubjectType.UnknownUser, SubjectType.UnknownUser }, - { SubjectType.AadGroup, SubjectType.AadGroup }, - { SubjectType.VstsGroup, SubjectType.VstsGroup }, - { SubjectType.UnknownGroup, SubjectType.UnknownGroup }, - { SubjectType.BindPendingUser, SubjectType.BindPendingUser }, - { SubjectType.WindowsIdentity, SubjectType.WindowsIdentity }, - { SubjectType.UnauthenticatedIdentity, SubjectType.UnauthenticatedIdentity }, - { SubjectType.ServiceIdentity, SubjectType.ServiceIdentity }, - { SubjectType.AggregateIdentity, SubjectType.AggregateIdentity }, - { SubjectType.ImportedIdentity, SubjectType.ImportedIdentity }, - { SubjectType.ServerTestIdentity, SubjectType.ServerTestIdentity }, - { SubjectType.GroupScopeType, SubjectType.GroupScopeType }, - { SubjectType.CspPartnerIdentity, SubjectType.CspPartnerIdentity }, - { SubjectType.SystemServicePrincipal, SubjectType.SystemServicePrincipal }, - { SubjectType.SystemLicense, SubjectType.SystemLicense }, - { SubjectType.SystemPublicAccess, SubjectType.SystemPublicAccess}, - { SubjectType.SystemAccessControl, SubjectType.SystemAccessControl }, - { SubjectType.SystemScope, SubjectType.SystemScope }, - { SubjectType.AcsServiceIdentity, SubjectType.AcsServiceIdentity }, - { SubjectType.Unknown, SubjectType.Unknown }, - }; - - SubjectTypeMap = subjectTypeMap; - - var socialTypeMap = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { SocialType.GitHub, SocialType.GitHub }, - { SocialType.Unknown, SocialType.Unknown }, - }; - - SocialTypeMap = socialTypeMap; - } - - [GenerateSpecificConstants] - public static class SubjectKind - { - [GenerateConstant] - public const string Group = "group"; - public const string Scope = "scope"; - [GenerateConstant] - public const string User = "user"; - public const string SystemSubject = "systemSubject"; - } - - [GenerateSpecificConstants] - public static class SubjectType - { - [GenerateConstant] - public const string AadUser = "aad"; - [GenerateConstant] - public const string MsaUser = "msa"; - public const string UnknownUser = "unusr"; // user with unknown type (not add nor msa) - [GenerateConstant] - public const string AadGroup = "aadgp"; - [GenerateConstant] - public const string VstsGroup = "vssgp"; - public const string UnknownGroup = "ungrp"; // group with unknown type (not add nor vsts) - [GenerateConstant] - public const string BindPendingUser = "bnd"; - public const string WindowsIdentity = "win"; - public const string UnauthenticatedIdentity = "uauth"; - public const string ServiceIdentity = "svc"; - public const string AggregateIdentity = "agg"; - public const string ImportedIdentity = "imp"; - public const string ServerTestIdentity = "tst"; - public const string GroupScopeType = "scp"; - public const string CspPartnerIdentity = "csp"; - public const string SystemServicePrincipal = "s2s"; - public const string SystemLicense = "slic"; - public const string SystemScope = "sscp"; - public const string SystemCspPartner = "scsp"; - public const string SystemPublicAccess = "spa"; - public const string SystemAccessControl = "sace"; - public const string AcsServiceIdentity = "acs"; - public const string Unknown = "ukn"; // none of the above - } - - public static readonly IReadOnlyDictionary SubjectTypeMap; - - [GenerateSpecificConstants] - public static class SocialType - { - public const string GitHub = "ghb"; - public const string Unknown = "ukn"; - } - - public static readonly IReadOnlyDictionary SocialTypeMap; - - public static class ScopeUpdateFields - { - public const string Name = "name"; - } - - public static class GroupUpdateFields - { - public const string DisplayName = "displayName"; - public const string Description = "description"; - } - - public static class Links - { - public const string Self = "self"; - public const string Memberships = "memberships"; - public const string MembershipState = "membershipState"; - public const string StorageKey = "storageKey"; - public const string Groups = "groups"; - public const string Descriptor = "descriptor"; - public const string Subject = "subject"; - public const string Member = "member"; - public const string Conainer = "container"; - public const string Avatar = "avatar"; - } - - [GenerateSpecificConstants] - public static class OriginName - { - public const string ActiveDirectory = "ad"; - [GenerateConstant] - public const string AzureActiveDirectory = "aad"; - [GenerateConstant] - public const string MicrosoftAccount = "msa"; - [GenerateConstant] - public const string VisualStudioTeamServices = "vsts"; - [GenerateConstant] - public const string GitHubDirectory = "ghb"; - } - - public static class FederatedProviderName - { - public const string GitHub = "github.com"; - } - - public static class TraversalDepth - { - public const int Direct = 1; - public const int Expanded = -1; - } - - [GenerateSpecificConstants] - public static class UserMetaType - { - public const string Member = "member"; - [GenerateConstant] - public const string Guest = "guest"; - public const string CompanyAdministrator = "companyAdministrator"; - public const string HelpdeskAdministrator = "helpdeskAdministrator"; - } - - internal static class SubjectDescriptorPolicies - { - internal const int MaxSubjectTypeLength = 5; - internal const int MinSubjectTypeLength = 3; - internal const int MinSubjectDescriptorStringLength = 6; - internal const int MaxIdentifierLength = 256; - } - - internal static class SocialDescriptorPolicies - { - internal const int MaxSocialTypeLength = 4; - internal const int MinSocialTypeLength = SubjectDescriptorPolicies.MinSubjectTypeLength; - internal const int MinSocialDescriptorStringLength = SubjectDescriptorPolicies.MinSubjectDescriptorStringLength; - internal const int MaxIdentifierLength = SubjectDescriptorPolicies.MaxIdentifierLength; - } - - internal static class Version - { - internal const int Unspecified = -1; - } - - public const int MaximumRestResultSize = 500; - public const string JsonPatchMediaType = "application/json-patch+json"; - public const string JsonPatchOperationPathPrefix = "/"; - public const char SubjectListSeparator = ','; - public const char SubjectDescriptorPartsSeparator = '.'; - - // Social descriptor constants - public const char SocialListSeparator = ','; - public const char SocialDescriptorPartsSeparator = '.'; - public const string SocialDescriptorPrefix = "@"; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/ChangedIdentities.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/ChangedIdentities.cs deleted file mode 100644 index 23cf16f5d..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/ChangedIdentities.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using Newtonsoft.Json; - -namespace GitHub.Services.Identity -{ - /// - /// Container class for changed identities - /// - [DataContract] - public class ChangedIdentities - { - [JsonConstructor] - private ChangedIdentities() - { - } - - public ChangedIdentities( - IList identities, - ChangedIdentitiesContext sequenceContext) : - this(identities, sequenceContext, false) - { - } - - public ChangedIdentities( - IList identities, - ChangedIdentitiesContext sequenceContext, - bool moreData) - { - Identities = identities; - SequenceContext = sequenceContext; - MoreData = moreData; - } - - /// - /// Changed Identities - /// - [DataMember] - public IList Identities { get; private set; } - - /// - /// Last Identity SequenceId - /// - [DataMember] - public ChangedIdentitiesContext SequenceContext { get; private set; } - - /// - /// More data available, set to true if pagesize is specified. - /// - [DataMember] - public bool MoreData { get; private set; } - } - - /// - /// Context class for changed identities - /// - [DataContract] - public class ChangedIdentitiesContext - { - [JsonConstructor] - private ChangedIdentitiesContext() - { - } - - public ChangedIdentitiesContext( - Int32 identitySequenceId, - Int32 groupSequenceId) : - this(identitySequenceId, groupSequenceId, ChangedIdentitiesContext.UnspecifiedSequenceId) - { - } - - public ChangedIdentitiesContext( - Int32 identitySequenceId, - Int32 groupSequenceId, - Int32 organizationIdentitySequenceId) : - this(identitySequenceId, groupSequenceId, organizationIdentitySequenceId, 0) - { - } - - public ChangedIdentitiesContext( - Int32 identitySequenceId, - Int32 groupSequenceId, - Int32 organizationIdentitySequenceId, - Int32 pageSize) - { - IdentitySequenceId = identitySequenceId; - GroupSequenceId = groupSequenceId; - OrganizationIdentitySequenceId = organizationIdentitySequenceId; - PageSize = pageSize; - } - - /// - /// Last Identity SequenceId - /// - [DataMember] - public Int32 IdentitySequenceId { get; private set; } - - /// - /// Last Group SequenceId - /// - [DataMember] - public Int32 GroupSequenceId { get; private set; } - - /// - /// Last Group OrganizationIdentitySequenceId - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int32 OrganizationIdentitySequenceId { get; private set; } - - /// - /// Page size - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int32 PageSize { get; private set; } - - private static int UnspecifiedSequenceId = -1; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/CreateGroupsInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/CreateGroupsInfo.cs deleted file mode 100644 index 36b8649f3..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/CreateGroupsInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class CreateGroupsInfo - { - public CreateGroupsInfo() - { - } - - public CreateGroupsInfo(Guid scopeId, IList groups) - { - this.ScopeId = scopeId; - this.Groups = new List(groups); - } - - [DataMember] - public Guid ScopeId { get; private set; } - - [DataMember] - public List Groups { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/CreateScopeInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/CreateScopeInfo.cs deleted file mode 100644 index ff8b27875..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/CreateScopeInfo.cs +++ /dev/null @@ -1,51 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - //Technically speaking, this is poor REST - //a PUT or POST to a service to create an entity should - //contain that entity, in this case an IdentityScope - //however this contains extra fields not in an IdentityScope - [DataContract] - public class CreateScopeInfo - { - public CreateScopeInfo() - { - } - - internal CreateScopeInfo(Guid parentScopeId, GroupScopeType scopeType, String scopeName, String adminGroupName, String adminGroupDescription, Guid creatorId) - { - ArgumentUtility.CheckStringForNullOrEmpty(scopeName, "scopeName"); - ArgumentUtility.CheckStringForNullOrEmpty(adminGroupName, "adminGroupName"); - ArgumentUtility.CheckStringForNullOrEmpty(adminGroupDescription, "admingGroupDescription"); - - ParentScopeId = parentScopeId; - ScopeType = scopeType; - ScopeName = scopeName; - AdminGroupName = adminGroupName; - AdminGroupDescription = adminGroupDescription; - CreatorId = creatorId; - } - - [DataMember] - public Guid ParentScopeId { get; private set; } - - [DataMember] - public GroupScopeType ScopeType { get; private set; } - - [DataMember] - public String ScopeName { get; private set; } - - [DataMember] - public String AdminGroupName { get; private set; } - - [DataMember] - public String AdminGroupDescription { get; private set; } - - [DataMember(IsRequired=false, EmitDefaultValue=false)] - public Guid CreatorId { get; private set; } - - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/FrameworkIdentityInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/FrameworkIdentityInfo.cs deleted file mode 100644 index b40e904c1..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/FrameworkIdentityInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class FrameworkIdentityInfo - { - [DataMember] - public FrameworkIdentityType IdentityType { get; set; } - - [DataMember] - public string Role { get; set; } - - [DataMember] - public string Identifier { get; set; } - - [DataMember] - public string DisplayName { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/FrameworkIdentityType.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/FrameworkIdentityType.cs deleted file mode 100644 index 6e939ae6c..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/FrameworkIdentityType.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace GitHub.Services.Identity -{ - public enum FrameworkIdentityType - { - None = 0, - ServiceIdentity = 1, - AggregateIdentity = 2, - ImportedIdentity = 3, - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/GroupMembership.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/GroupMembership.cs deleted file mode 100644 index 311da6f16..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/GroupMembership.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.Serialization; -using System.Xml; - -namespace GitHub.Services.Identity -{ - /// - /// - /// - [DataContract] - public sealed class GroupMembership - { - public GroupMembership(Guid queriedId, Guid id, IdentityDescriptor descriptor) - { - QueriedId = queriedId; - Id = id; - Descriptor = descriptor; - Active = true; - } - - [DataMember] - public Guid QueriedId - { - get; - set; - } - - [DataMember] - public Guid Id - { - get - { - return m_id; - } - - set - { - m_id = value; - } - } - - [DataMember] - public IdentityDescriptor Descriptor - { - get; - set; - } - - [DataMember] - public Boolean Active - { - get; - set; - } - - - private Guid m_id; - - public GroupMembership Clone() - { - return new GroupMembership( - queriedId: QueriedId, - id: Id, - descriptor: Descriptor == null ? null : new IdentityDescriptor(Descriptor)) - { - Active = this.Active - }; - } - - public override string ToString() - { - return string.Format("[Id = {0}, Descriptor = {1}, Active = {2}, QueriedId = {3}]", Id, Descriptor, Active, QueriedId); - } - } - - [CollectionDataContract(Name = "GroupMemberships", ItemName = "GroupMembership")] - public class GroupMembershipCollection : List - { - public GroupMembershipCollection() - { - } - - public GroupMembershipCollection(IList source) - : base(source) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IReadOnlyVssIdentity.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IReadOnlyVssIdentity.cs deleted file mode 100644 index bda88d506..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IReadOnlyVssIdentity.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace GitHub.Services.Identity -{ - public interface IReadOnlyVssIdentity - { - Guid Id { get; } - - IdentityDescriptor Descriptor { get; } - - bool IsContainer { get; } - - bool IsExternalUser { get; } - - string DisplayName { get; } - - string ProviderDisplayName { get; } - - string CustomDisplayName { get; } - - TValue GetProperty(string name, TValue defaultValue); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IVssIdentity.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IVssIdentity.cs deleted file mode 100644 index e8fb0fa52..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IVssIdentity.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace GitHub.Services.Identity -{ - public interface IVssIdentity : IReadOnlyVssIdentity - { - new IdentityDescriptor Descriptor { get; set; } - - new string ProviderDisplayName { get; set; } - - new string CustomDisplayName { get; set; } - - void SetProperty(string name, object value); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/Identity.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/Identity.cs deleted file mode 100644 index 874022c0b..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/Identity.cs +++ /dev/null @@ -1,557 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Runtime.Serialization; -using System.Xml; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Identity -{ - //The only PATCH-able property on this class is CustomDisplayName, however there are more read/write properties - //because they get set by various providers in the Framework dll, in general Framework should not have internalsvisibleto to this dll - //CONSIDER: Should providers be in GitHub.Services.Identity instead? - [DataContract] - public sealed class Identity : IdentityBase, ISecuredObject - { - public Identity() : this(null) - { - } - - private Identity(PropertiesCollection properties) : base(properties) - { - } - - public Identity Clone(bool includeMemberships) - { - PropertiesCollection properties = new PropertiesCollection(Properties, validateExisting: false); - - Identity clone = new Identity(properties) - { - Id = Id, - Descriptor = new IdentityDescriptor(Descriptor), - SubjectDescriptor = SubjectDescriptor, - SocialDescriptor = SocialDescriptor, - ProviderDisplayName = ProviderDisplayName, - CustomDisplayName = CustomDisplayName, - IsActive = IsActive, - UniqueUserId = UniqueUserId, - IsContainer = IsContainer, - ResourceVersion = ResourceVersion, - MetaTypeId = MetaTypeId - }; - - if (includeMemberships) - { - clone.Members = CloneDescriptors(Members); - clone.MemberOf = CloneDescriptors(MemberOf); - clone.MemberIds = MemberIds?.ToList(); - clone.MemberOfIds = MemberOfIds?.ToList(); - } - - clone.MasterId = MasterId; - - return clone; - } - - public Identity Clone() - { - return this.Clone(true); - } - - internal static Identity FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - Identity obj = new Identity(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - bool empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "DisplayName": - obj.ProviderDisplayName = reader.Value; - break; - case "IsActive": - obj.IsActive = XmlConvert.ToBoolean(reader.Value); - break; - case "IsContainer": - obj.IsContainer = XmlConvert.ToBoolean(reader.Value); - break; - case "TeamFoundationId": - obj.Id = XmlConvert.ToGuid(reader.Value); - break; - case "UniqueName": - // We don't have this property on VSIdentity - //obj.UniqueName = reader.Value; - break; - case "UniqueUserId": - obj.UniqueUserId = XmlConvert.ToInt32(reader.Value); - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "Attributes": - KeyValueOfStringString[] attributes = XmlUtility.ArrayOfObjectFromXml(serviceProvider, reader, "KeyValueOfStringString", false, KeyValueOfStringString.FromXml); - if (attributes != null && obj.Properties != null) - { - foreach (KeyValueOfStringString attribute in attributes) - { - obj.Properties[attribute.Key] = attribute.Value; - } - } - break; - case "Descriptor": - obj.Descriptor = IdentityDescriptor.FromXml(serviceProvider, reader); - break; - case "LocalProperties": - // Since we're only using the SOAP serializer for bootstrap, we won't support properties - //obj.m_localPropertiesSet = Helper.ArrayOfPropertyValueFromXml(serviceProvider, reader, false); - reader.ReadOuterXml(); - break; - case "MemberOf": - obj.MemberOf = XmlUtility.ArrayOfObjectFromXml(serviceProvider, reader, "IdentityDescriptor", false, IdentityDescriptor.FromXml); - break; - case "Members": - obj.Members = XmlUtility.ArrayOfObjectFromXml(serviceProvider, reader, "IdentityDescriptor", false, IdentityDescriptor.FromXml); - break; - case "Properties": - // Since we're only using the SOAP serializer for bootstrap, we won't support properties - //obj.m_propertiesSet = Helper.ArrayOfPropertyValueFromXml(serviceProvider, reader, false); - reader.ReadOuterXml(); - break; - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - - #region ISecuredObject - public Guid NamespaceId => GraphSecurityConstants.NamespaceId; - - public int RequiredPermissions => GraphSecurityConstants.ReadByPublicIdentifier; - - public string GetToken() => GraphSecurityConstants.SubjectsToken; - #endregion - - private static ICollection CloneDescriptors(IEnumerable descriptors) - { - return descriptors?.Select(item => new IdentityDescriptor(item)).ToList(); - } - } - - /// - /// Base Identity class to allow "trimmed" identity class in the GetConnectionData API - /// Makes sure that on-the-wire representations of the derived classes are compatible with each other - /// (e.g. Server responds with PublicIdentity object while client deserializes it as Identity object) - /// Derived classes should not have additional [DataMember] properties - /// - [DebuggerDisplay("Name: {DisplayName} ID:{Id}")] - [EditorBrowsable(EditorBrowsableState.Never)] - [DataContract] - public abstract class IdentityBase : IVssIdentity - { - protected IdentityBase(PropertiesCollection properties) - { - if (properties == null) - { - Properties = new PropertiesCollection(); - } - else - { - Properties = properties; - } - - ResourceVersion = IdentityConstants.DefaultResourceVersion; - - // Initialize this as Unknown (255) so the default integer value of MetaTypeId isn't set as Member (0) - MetaType = IdentityMetaType.Unknown; - } - - [DataMember] - public Guid Id - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IdentityDescriptor Descriptor - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public SubjectDescriptor SubjectDescriptor - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public SocialDescriptor SocialDescriptor - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - //***************************************************************************************************************** - /// - /// The display name for the identity as specified by the source identity provider. - /// - //***************************************************************************************************************** - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string ProviderDisplayName - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - //***************************************************************************************************************** - /// - /// The custom display name for the identity (if any). Setting this property to an empty string will clear the existing - /// custom display name. Setting this property to null will not affect the existing persisted value - /// (since null values do not get sent over the wire or to the database) - /// - //***************************************************************************************************************** - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public string CustomDisplayName { get; set; } - - //***************************************************************************************************************** - /// - /// This is a computed property equal to the CustomDisplayName (if set) or the ProviderDisplayName. - /// - //***************************************************************************************************************** - public string DisplayName - { - get - { - if (!string.IsNullOrEmpty(CustomDisplayName)) - { - return CustomDisplayName; - } - - return ProviderDisplayName; - } - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool IsActive { get; set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public int UniqueUserId - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool IsContainer - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ICollection Members - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ICollection MemberOf - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public ICollection MemberIds { get; set; } - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public ICollection MemberOfIds { get; set; } - - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid MasterId { get; set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public PropertiesCollection Properties { get; private set; } - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool ValidateProperties - { - get - { - return this.Properties.ValidateNewValues; - } - set - { - this.Properties.ValidateNewValues = value; - } - } - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsExternalUser - { - get - { - Guid domain; - return Guid.TryParse(GetProperty(IdentityAttributeTags.Domain, string.Empty), out domain) && - Descriptor.IdentityType != IdentityConstants.ServiceIdentityType && - Descriptor.IdentityType != IdentityConstants.AggregateIdentityType && - Descriptor.IdentityType != IdentityConstants.ImportedIdentityType; - } - } - - /// - /// Get the Id of the containing scope - /// - [IgnoreDataMember] - public Guid LocalScopeId - { - get - { - return GetProperty(IdentityAttributeTags.LocalScopeId, default(Guid)); - } - } - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsBindPending => - this.Descriptor != null && - IdentityConstants.BindPendingIdentityType.Equals(Descriptor.IdentityType); - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsClaims => - this.Descriptor != null && - IdentityConstants.ClaimsType.Equals(Descriptor.IdentityType); - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsImported => - this.Descriptor != null && - IdentityConstants.ImportedIdentityType.Equals(Descriptor.IdentityType); - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsServiceIdentity => - this.Descriptor != null && - IdentityConstants.ServiceIdentityType.Equals(Descriptor.IdentityType); - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public int ResourceVersion { get; set; } - - [DataMember(IsRequired = false, EmitDefaultValue = true)] - public int MetaTypeId { get; set; } - - public IdentityMetaType MetaType - { - get { return (IdentityMetaType)MetaTypeId; } - set { MetaTypeId = (int)value; } - } - - [IgnoreDataMember] - [EditorBrowsable(EditorBrowsableState.Never)] - public bool IsCspPartnerUser => - this.Descriptor != null && - this.Descriptor.IsCspPartnerIdentityType(); - - //***************************************************************************************************************** - /// - /// Generic Property accessor. Returns default value of T if not found - /// - //***************************************************************************************************************** - public T GetProperty(string name, T defaultValue) - { - if (Properties != null && Properties.TryGetValidatedValue(name, out T value)) - { - return value; - } - else - { - return defaultValue; - } - } - - //***************************************************************************************************************** - /// - /// Property accessor. value will be null if not found. - /// - //***************************************************************************************************************** - public bool TryGetProperty(string name, out object value) - { - value = null; - return Properties != null && Properties.TryGetValue(name, out value); - } - - //***************************************************************************************************************** - /// - /// Internal function to initialize persisted property. - /// - //***************************************************************************************************************** - public void SetProperty(string name, object value) - { - m_hasModifiedProperties = true; - - //don't remove properties with null - //vals, just set them to null... - Properties[name] = value; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public bool HasModifiedProperties => m_hasModifiedProperties; - - [EditorBrowsable(EditorBrowsableState.Never)] - public void ResetModifiedProperties() - { - m_hasModifiedProperties = false; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public void SetAllModifiedProperties() - { - m_hasModifiedProperties = true; - } - - public override bool Equals(object obj) - { - IdentityBase other = obj as IdentityBase; - if (other != null) - { - return (Id == other.Id && - IdentityDescriptorComparer.Instance.Equals(Descriptor, other.Descriptor) && - string.Equals(ProviderDisplayName, other.ProviderDisplayName, StringComparison.OrdinalIgnoreCase) && - string.Equals(CustomDisplayName, other.CustomDisplayName, StringComparison.OrdinalIgnoreCase) && - IsActive == other.IsActive && - UniqueUserId == other.UniqueUserId && - IsContainer == other.IsContainer); - } - - return false; - } - - public override int GetHashCode() - { - if (Descriptor == null) - { - return 0; - } - return Descriptor.GetHashCode(); - } - - public override string ToString() - { - return string.Format(CultureInfo.InvariantCulture, "Identity {0} (IdentityType: {1}; Identifier: {2}; DisplayName: {3})", - Id, - (Descriptor == null) ? string.Empty : Descriptor.IdentityType, - (Descriptor == null) ? string.Empty : Descriptor.Identifier, - DisplayName); - } - - private bool m_hasModifiedProperties; - } - - internal class KeyValueOfStringString - { - public string Key { get; set; } - - public string Value { get; set; } - - internal static KeyValueOfStringString FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - KeyValueOfStringString obj = new KeyValueOfStringString(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - bool empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "Key": - obj.Key = XmlUtility.StringFromXmlElement(reader); - break; - case "Value": - obj.Value = XmlUtility.StringFromXmlElement(reader); - break; - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityBatchInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityBatchInfo.cs deleted file mode 100644 index 99727ca8f..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityBatchInfo.cs +++ /dev/null @@ -1,76 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class IdentityBatchInfo - { - private IdentityBatchInfo() - { - } - - public IdentityBatchInfo(IList subjectDescriptors, QueryMembership queryMembership = QueryMembership.None, IEnumerable propertyNames = null, bool includeRestrictedVisibility = false) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(subjectDescriptors, nameof(subjectDescriptors)); - - this.SubjectDescriptors = new List(subjectDescriptors); - this.QueryMembership = queryMembership; - this.PropertyNames = propertyNames; - this.IncludeRestrictedVisibility = includeRestrictedVisibility; - } - - public IdentityBatchInfo(IList descriptors, QueryMembership queryMembership = QueryMembership.None, IEnumerable propertyNames = null, bool includeRestrictedVisibility = false) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(descriptors, nameof(descriptors)); - - this.Descriptors = new List(descriptors); - this.QueryMembership = queryMembership; - this.PropertyNames = propertyNames; - this.IncludeRestrictedVisibility = includeRestrictedVisibility; - } - - public IdentityBatchInfo(IList identityIds, QueryMembership queryMembership = QueryMembership.None, IEnumerable propertyNames = null, bool includeRestrictedVisibility = false) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(identityIds, nameof(identityIds)); - - this.IdentityIds = new List(identityIds); - this.QueryMembership = queryMembership; - this.PropertyNames = propertyNames; - this.IncludeRestrictedVisibility = includeRestrictedVisibility; - } - - public IdentityBatchInfo(IList socialDescriptors, QueryMembership queryMembership = QueryMembership.None, IEnumerable propertyNames = null, bool includeRestrictedVisibility = false) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(socialDescriptors, nameof(socialDescriptors)); - - this.SocialDescriptors = new List(socialDescriptors); - this.QueryMembership = queryMembership; - this.PropertyNames = propertyNames; - this.IncludeRestrictedVisibility = includeRestrictedVisibility; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public List Descriptors { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public List SubjectDescriptors { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public List IdentityIds { get; private set; } - - [DataMember] - public QueryMembership QueryMembership { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IEnumerable PropertyNames { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool IncludeRestrictedVisibility { get; private set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public List SocialDescriptors { get; private set; } - } -} \ No newline at end of file diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityCollections.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityCollections.cs deleted file mode 100644 index 5bc30bcc8..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityCollections.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [CollectionDataContract(Name = "Identities", ItemName = "Identity")] - public class IdentitiesCollection : List - { - public IdentitiesCollection() - { - } - - public IdentitiesCollection(IList source) - : base(source) - { - } - } - - [CollectionDataContract(Name = "Descriptors", ItemName = "Descriptor")] - public class IdentityDescriptorCollection : List - { - public IdentityDescriptorCollection() - { - } - - public IdentityDescriptorCollection(IList source) - : base(source) - { - } - } - - [CollectionDataContract(Name = "IdentityIds", ItemName = "IdentityId")] - public class IdentityIdCollection : List - { - public IdentityIdCollection() - { - } - - public IdentityIdCollection(IList source) - : base(source) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityDescriptor.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityDescriptor.cs deleted file mode 100644 index 1cf584d1b..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityDescriptor.cs +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Runtime.Serialization; -using System.Xml; -using System.Xml.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Identity -{ - /// - /// An Identity descriptor is a wrapper for the identity type (Windows SID, Passport) - /// along with a unique identifier such as the SID or PUID. - /// - /// - /// This is the only legacy type moved into VSS (by necessity, it is used everywhere) - /// so it must support both Xml and DataContract serialization - /// - [XmlInclude(typeof(ReadOnlyIdentityDescriptor))] - [KnownType(typeof(ReadOnlyIdentityDescriptor))] - [TypeConverter(typeof(IdentityDescriptorConverter))] - [DataContract] - public class IdentityDescriptor : IEquatable, IComparable - { - /// - /// Default constructor, for Xml serializer only. - /// - public IdentityDescriptor() { } - - /// - /// Constructor - /// - public IdentityDescriptor(string identityType, string identifier, object data) - : this(identityType, identifier) - { - this.Data = data; - } - - /// - /// Constructor - /// - public IdentityDescriptor(string identityType, string identifier) - { - //Validation in Setters... - IdentityType = identityType; - Identifier = identifier; - } - - /// - /// Copy Constructor - /// - public IdentityDescriptor(IdentityDescriptor clone) - { - IdentityType = clone.IdentityType; - Identifier = clone.Identifier; - } - - /// - /// Type of descriptor (for example, Windows, Passport, etc.). - /// - [XmlAttribute("identityType")] - [DataMember] - public virtual string IdentityType - { - get - { - return m_identityType ?? IdentityConstants.UnknownIdentityType; - } - set - { - ValidateIdentityType(value); - m_identityType = NormalizeIdentityType(value); - - // Drop any existing data - Data = null; - } - } - - /// - /// The unique identifier for this identity, not exceeding 256 chars, - /// which will be persisted. - /// - [XmlAttribute("identifier")] - [DataMember] - public virtual string Identifier - { - get - { - return m_identifier; - } - set - { - ValidateIdentifier(value); - m_identifier = value; - - // Drop any existing data - Data = null; - } - } - - /// - /// Any additional data specific to identity type. - /// - /// - /// Not serialized under either method. - /// - [XmlIgnore] - public virtual object Data { get; set; } - - public override string ToString() - { - return string.Concat(m_identityType, IdentityConstants.IdentityDescriptorPartsSeparator, m_identifier); - } - - public static IdentityDescriptor FromString(string identityDescriptorString) - { - if (string.IsNullOrEmpty(identityDescriptorString)) - { - return null; - } - - string[] tokens; - try - { - tokens = identityDescriptorString.Split(new[] { IdentityConstants.IdentityDescriptorPartsSeparator }, 2, StringSplitOptions.RemoveEmptyEntries); - } - catch - { - return new IdentityDescriptor(IdentityConstants.UnknownIdentityType, identityDescriptorString); - } - - if (tokens.Length == 2) - { - return new IdentityDescriptor(tokens[0], tokens[1]); - } - - return new IdentityDescriptor(IdentityConstants.UnknownIdentityType, identityDescriptorString); - } - - //Copied from TFCommonUtil.cs - private static void ValidateIdentityType(string identityType) - { - if (string.IsNullOrEmpty(identityType)) - { - throw new ArgumentNullException(nameof(identityType)); - } - - if (identityType.Length > MaxTypeLength) - { - throw new ArgumentOutOfRangeException(nameof(identityType)); - } - } - - private static String NormalizeIdentityType(String identityType) - { - String normalizedIdentityType; - - // Look up the string in the static dictionary. If we get a hit, then - // we'll use that string for the identity type instead. This saves memory - // as well as improves compare/equals performance when comparing descriptors, - // since Object.ReferenceEquals will return true a lot more often - if (!IdentityConstants.IdentityTypeMap.TryGetValue(identityType, out normalizedIdentityType)) - { - normalizedIdentityType = identityType; - } - - return normalizedIdentityType; - } - - private static void ValidateIdentifier(string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - throw new ArgumentNullException(nameof(identifier)); - } - - if (identifier.Length > MaxIdLength) - { - throw new ArgumentOutOfRangeException(nameof(identifier)); - } - } - - internal static IdentityDescriptor FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - string identifier = string.Empty; - string identityType = string.Empty; - - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - bool empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "identifier": - identifier = reader.Value; - break; - case "identityType": - identityType = reader.Value; - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - IdentityDescriptor obj = new IdentityDescriptor(identityType, identifier); - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - - return obj; - } - - protected string m_identityType; - private string m_identifier; - - private const int MaxIdLength = 256; - private const int MaxTypeLength = 128; - - #region Equality and Compare - - // IEquatable - public bool Equals(IdentityDescriptor other) => IdentityDescriptorComparer.Instance.Equals(this, other); - - // IComparable - public int CompareTo(IdentityDescriptor other) => IdentityDescriptorComparer.Instance.Compare(this, other); - - public override bool Equals(object obj) => this.Equals(obj as IdentityDescriptor); - - public override int GetHashCode() => IdentityDescriptorComparer.Instance.GetHashCode(this); - - public static bool operator ==(IdentityDescriptor x, IdentityDescriptor y) - { - return IdentityDescriptorComparer.Instance.Equals(x, y); - } - - public static bool operator !=(IdentityDescriptor x, IdentityDescriptor y) - { - return !IdentityDescriptorComparer.Instance.Equals(x, y); - } - - #endregion // Equality and Compare - } - - /// - /// Class used for comparing IdentityDescriptors - /// - public class IdentityDescriptorComparer : IComparer, IEqualityComparer - { - private IdentityDescriptorComparer() - { - } - - /// - /// Compares two instances of IdentityDescriptor. - /// - /// The first IdentityDescriptor to compare. - /// The second IdentityDescriptor to compare. - /// Compares two specified IdentityDescriptor objects and returns an integer that indicates their relative position in the sort order. - public int Compare(IdentityDescriptor x, IdentityDescriptor y) - { - if (Object.ReferenceEquals(x, y)) - { - return 0; - } - - if (Object.ReferenceEquals(x, null) && !Object.ReferenceEquals(y, null)) - { - return -1; - } - - if (!Object.ReferenceEquals(x, null) && Object.ReferenceEquals(y, null)) - { - return 1; - } - - int retValue = StringComparer.OrdinalIgnoreCase.Compare(x.IdentityType, y.IdentityType); - - //have to maintain equivalence for service principals while we are migrating them - if (0 != retValue && - ((x.IsSystemServicePrincipalType() && y.IsClaimsIdentityType()) || - (y.IsSystemServicePrincipalType() && x.IsClaimsIdentityType()))) - { - retValue = 0; - } - - if (0 == retValue) - { - retValue = StringComparer.OrdinalIgnoreCase.Compare(x.Identifier, y.Identifier); - } - - return retValue; - } - - public bool Equals(IdentityDescriptor x, IdentityDescriptor y) - { - if (Object.ReferenceEquals(x, y)) - { - return true; - } - - return 0 == Compare(x, y); - } - - public int GetHashCode(IdentityDescriptor obj) - { - int hashCode = 7443; - string identityType = obj.IdentityType; - - //until all service principals are in the system store, we treat them as Claims identities for hash code - if(obj.IsSystemServicePrincipalType()) - { - identityType = IdentityConstants.ClaimsType; - } - - hashCode = 524287 * hashCode + StringComparer.OrdinalIgnoreCase.GetHashCode(identityType); - hashCode = 524287 * hashCode + StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Identifier ?? string.Empty); - - return hashCode; - } - - public static IdentityDescriptorComparer Instance { get; } = new IdentityDescriptorComparer(); - } - - // Keep this in sync with the SubjectDescriptorExtensions to avoid extra casting/conversions - public static class IdentityDescriptorExtensions - { - public static bool IsTeamFoundationType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.TeamFoundationType); - } - - public static bool IsWindowsType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.WindowsType); - } - - public static bool IsUnknownIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.UnknownIdentityType); - } - - public static bool IsSystemServicePrincipalType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.System_ServicePrincipal); - } - - public static bool IsClaimsIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.ClaimsType); - } - - public static bool IsImportedIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.ImportedIdentityType); - } - - public static bool IsServiceIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.ServiceIdentityType); - } - - public static bool IsBindPendingType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.BindPendingIdentityType); - } - - public static bool IsAggregateIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.AggregateIdentityType); - } - - public static bool IsUnauthenticatedIdentity(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.UnauthenticatedIdentityType); - } - - public static bool IsSubjectStoreType(this IdentityDescriptor identityDescriptor) - { - return ReferenceEquals(identityDescriptor.IdentityType, IdentityConstants.System_License) - || ReferenceEquals(identityDescriptor.IdentityType, IdentityConstants.System_Scope) - || ReferenceEquals(identityDescriptor.IdentityType, IdentityConstants.System_ServicePrincipal) - || ReferenceEquals(identityDescriptor.IdentityType, IdentityConstants.System_WellKnownGroup) - || ReferenceEquals(identityDescriptor.IdentityType, IdentityConstants.System_CspPartner); - } - - /// - /// true if the descriptor matches any of the passed types - /// - /// - /// - /// - public static bool IsIdentityType(this IdentityDescriptor identityDescriptor, IEnumerable identityTypes) - { - return identityTypes.Any(id => StringComparer.OrdinalIgnoreCase.Equals(identityDescriptor.IdentityType, id)); - } - - public static bool IsIdentityType(this IdentityDescriptor identityDescriptor, string identityType) - { - return StringComparer.OrdinalIgnoreCase.Equals(identityDescriptor.IdentityType, identityType); - } - - public static bool IsCspPartnerIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.CspPartnerIdentityType); - } - - public static bool IsGroupScopeType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.GroupScopeType); - } - - public static bool IsSystemLicenseType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.System_License); - } - - public static bool IsSystemScopeType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.System_Scope); - } - - public static bool IsSystemPublicAccessType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.System_PublicAccess); - } - - public static bool IsSystemAccessControlType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.System_AccessControl); - } - - public static bool IsServerTestIdentityType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.ServerTestIdentity); - } - - public static bool IsSystemCspPartnerType(this IdentityDescriptor identityDescriptor) - { - return identityDescriptor.IsIdentityType(IdentityConstants.System_CspPartner); - } - } - - [DataContract] - public sealed class ReadOnlyIdentityDescriptor : IdentityDescriptor - { - /// - /// Default constructor, for Xml serializer only. - /// - public ReadOnlyIdentityDescriptor() { } - - public ReadOnlyIdentityDescriptor(string identityType, string identifier, object data) - : base(identityType, identifier, data) - { - } - - [XmlAttribute("identityType")] - [DataMember] - public override string IdentityType - { - get - { - return base.IdentityType; - } - set - { - if (m_identityType != null) - { - throw new InvalidOperationException(IdentityResources.FieldReadOnly(nameof(IdentityType))); - } - base.IdentityType = value; - } - } - - [XmlAttribute("identifier")] - [DataMember] - public override string Identifier - { - get - { - return base.Identifier; - } - set - { - if (!string.IsNullOrEmpty(base.Identifier)) - { - throw new InvalidOperationException(IdentityResources.FieldReadOnly(nameof(Identifier))); - } - base.Identifier = value; - } - } - - [XmlIgnore] - public override object Data - { - get - { - return base.Data; - } - set - { - if (base.Data != null) - { - throw new InvalidOperationException(IdentityResources.FieldReadOnly(nameof(Data))); - } - base.Data = value; - } - } - } - - /// - /// Converter to support data contract serialization. - /// - public class IdentityDescriptorConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType.Equals(typeof(string)) || base.CanConvertFrom(context, sourceType); - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType.Equals(typeof(string)) || base.CanConvertTo(context, destinationType); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - if (value is string) - { - string descriptor = value as string; - string[] tokens = descriptor.Split(new[] { IdentityConstants.IdentityDescriptorPartsSeparator }, 2, StringSplitOptions.RemoveEmptyEntries); - - if (tokens.Length == 2) - { - return new IdentityDescriptor(tokens[0], tokens[1]); - } - } - - return base.ConvertFrom(context, culture, value); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType.Equals(typeof(string))) - { - IdentityDescriptor descriptor = value as IdentityDescriptor; - - return descriptor?.ToString() ?? string.Empty; - } - - return base.ConvertTo(context, culture, value, destinationType); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityEnumerations.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityEnumerations.cs deleted file mode 100644 index 5947e4ba5..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityEnumerations.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Runtime.Serialization; -using System.Xml.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public enum GroupScopeType - { - [EnumMember, XmlEnum("0")] - Generic = 0, - - [EnumMember, XmlEnum("1")] - ServiceHost = 1, - - [EnumMember, XmlEnum("2")] - TeamProject = 2 - } - - - // This is the *same* as IdentitySearchFactor in TFCommon - // Changed the name to avoid conflicts - [DataContract] - public enum IdentitySearchFilter - { - /// - /// NT account name (domain\alias) - /// - [EnumMember] - AccountName = 0, - - /// - /// Display name - /// - [EnumMember] - DisplayName = 1, - - /// - /// Find project admin group - /// - [EnumMember] - AdministratorsGroup = 2, - - /// - /// Find the identity using the identifier - /// - [EnumMember] - Identifier = 3, - - /// - /// Email address - /// - [EnumMember] - MailAddress = 4, - - /// - /// A general search for an identity. - /// - /// - /// This is the default search factor for shorter overloads of ReadIdentity, and typically the correct choice for user input. - /// - /// Use the general search factor to find one or more identities by one of the following properties: - /// * Display name - /// * account name - /// * UniqueName - /// - /// UniqueName may be easier to type than display name. It can also be used to indicate a single identity when two or more identities share the same display name (e.g. "John Smith") - /// - [EnumMember] - General = 5, - - /// - /// Alternate login username - /// - [EnumMember] - Alias = 6, - - /// - /// Find identity using Domain/TenantId - /// - [EnumMember] - [Obsolete("Use read identities to get member of collection valid users group instead.")] - Domain = 7, - - /// - /// Find identity using DirectoryAlias - /// - [EnumMember] - DirectoryAlias = 8, - - /// - /// Find a team group by its name - /// - [Obsolete("Deprecating TeamGroupName, use LocalGroupName instead and filter out non teams groups from the result")] - [EnumMember] - TeamGroupName = 9, - - /// - /// Find a local group (i.e. VSTS or TFS rather than AAD or AD group) by its name - /// - [EnumMember] - LocalGroupName = 10, - } - - // This enum is as an index for IMS identity caches. - // This is the *same* as MembershipQuery in TFCommon - // Changed the name to avoid conflicts - [DataContract] - public enum QueryMembership - { - // These enumeration values should run from zero to N, with no gaps. - // IdentityHostCache uses these values as indexes. - - /// - /// Query will not return any membership data - /// - [EnumMember] - None = 0, - - /// - /// Query will return only direct membership data - /// - [EnumMember] - Direct = 1, - - /// - /// Query will return expanded membership data - /// - [EnumMember] - Expanded = 2, - - /// - /// Query will return expanded up membership data (parents only) - /// - [EnumMember] - ExpandedUp = 3, - - /// - /// Query will return expanded down membership data (children only) - /// - [EnumMember] - ExpandedDown = 4 - - // Dev10 had the public value "Last = 3", as an indicator of the end of the enumeration. - // Dev14 supports public enum value "ExpandedDown = 4" , as an indicator of the end of the enumeration. - } - - // Designates "special" VSS groups. - [DataContract] - public enum SpecialGroupType - { - [EnumMember] - Generic = 0, - - [EnumMember] - AdministrativeApplicationGroup, - - [EnumMember] - ServiceApplicationGroup, - - [EnumMember] - EveryoneApplicationGroup, - - [EnumMember] - LicenseesApplicationGroup, - - [EnumMember] - AzureActiveDirectoryApplicationGroup, - - [EnumMember] - AzureActiveDirectoryRole, - } - - [Flags] - public enum ReadIdentitiesOptions - { - None = 0, - FilterIllegalMemberships = 1 - } - - public enum RestoreProjectOptions - { - /// - /// Brings back all memberships whose members are not owned by the scope - /// - All = 0, - - /// - /// Brings back some memberships whose members are not owned by the scope. - /// The membership will be a subset of All with the additional requirement - /// that the members have visibilty into the project collection scope. - /// - Visible = 1, - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityMetaType.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityMetaType.cs deleted file mode 100644 index 3ffcf165d..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityMetaType.cs +++ /dev/null @@ -1,12 +0,0 @@ - -namespace GitHub.Services.Identity -{ - public enum IdentityMetaType - { - Member = 0, - Guest = 1, - CompanyAdministrator = 2, - HelpdeskAdministrator = 3, - Unknown = 255, // When the type isn't known (default value) - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityScope.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityScope.cs deleted file mode 100644 index 2f9db5f93..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityScope.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using GitHub.Services.Common; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class IdentityScope - { - internal IdentityScope() - { - } - - //Copy-Constructor - internal IdentityScope(IdentityScope other) - : this(other.Id, other.Name) - { - Administrators = other.Administrators == null ? null : new IdentityDescriptor(other.Administrators); - IsActive = other.IsActive; - IsGlobal = other.IsGlobal; - LocalScopeId = other.LocalScopeId; - ParentId = other.ParentId; - ScopeType = other.ScopeType; - SecuringHostId = other.SecuringHostId; - } - - //Constructor used for the rename operation - internal IdentityScope(Guid id, String name) - { - ArgumentUtility.CheckForEmptyGuid(id, "id"); - ArgumentUtility.CheckStringForNullOrEmpty(name, "name"); - this.Id = id; - this.Name = name; - } - - [DataMember(IsRequired=true)] - public Guid Id - { - get; - - internal set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - internal Guid LocalScopeId - { - get; - - set; - } - - [DataMember(IsRequired=false, EmitDefaultValue=false)] - public Guid ParentId - { - get; - - internal set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public GroupScopeType ScopeType - { - get; - - internal set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Name - { - get; - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IdentityDescriptor Administrators - { - get; - - internal set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Boolean IsGlobal - { - get; - internal set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid SecuringHostId - { - get; - - internal set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Boolean IsActive - { - get; - - internal set; - } - - public IdentityScope Clone() - { - return new IdentityScope(this); - } - - public override string ToString() - { - return $"[Id={Id}, Name={Name}, LocalScopeId={LocalScopeId}, ParentId={ParentId}, ScopeType={ScopeType}, SecuringHostId={SecuringHostId}, Administrators={Administrators}, IsActive={IsActive}, IsGlobal={IsGlobal}]"; - } - - private SubjectDescriptor subjectDescriptor; - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public SubjectDescriptor SubjectDescriptor - { - get - { - if (subjectDescriptor == default(SubjectDescriptor)) - { - subjectDescriptor = new SubjectDescriptor(Graph.Constants.SubjectType.GroupScopeType, Id.ToString()); - } - - return subjectDescriptor; - } - } - } - - [CollectionDataContract(Name = "Scopes", ItemName = "Scope")] - public class IdentityScopeCollection : List - { - public IdentityScopeCollection() - { - } - - public IdentityScopeCollection(IList source) - : base(source) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentitySelf.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentitySelf.cs deleted file mode 100644 index 9c8c9df2e..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentitySelf.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - /// - /// Identity information. - /// - [DebuggerDisplay("{DisplayName}")] - [DataContract] - public class IdentitySelf - { - /// - /// This is the VSID of the home tenant profile. If the profile is signed into the home tenant or if the profile - /// has no tenants then this Id is the same as the Id returned by the profile/profiles/me endpoint. Going forward - /// it is recommended that you use the combined values of Origin, OriginId and Domain to uniquely identify a user - /// rather than this Id. - /// - [DataMember] - public Guid Id - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The display name. For AAD accounts with multiple tenants this is the display name of the profile in the home tenant. - /// - [DataMember] - public String DisplayName - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The UserPrincipalName (UPN) of the account. This value comes from the source provider. - /// - [DataMember] - public string AccountName - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The type of source provider for the origin identifier. - /// For MSA accounts this is "msa". For AAD accounts this is "aad". - /// - [DataMember] - public string Origin - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The unique identifier from the system of origin. If there are multiple tenants this is the - /// unique identifier of the account in the home tenant. - /// (For MSA this is the PUID in hex notation, for AAD this is the object id.) - /// - [DataMember] - public string OriginId - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// This represents the name of the container of origin. - /// For AAD accounts this is the tenantID of the home tenant. - /// For MSA accounts this is the string "Windows Live ID". - /// - [DataMember] - public string Domain - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// For AAD accounts this is all of the tenants that this account is a member of. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IEnumerable Tenants - { - get; set; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentitySnapshot.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentitySnapshot.cs deleted file mode 100644 index 939541935..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentitySnapshot.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class IdentitySnapshot - { - public IdentitySnapshot() - { - } - - public IdentitySnapshot(Guid scopeId) - { - ScopeId = scopeId; - Scopes = new List(); - Groups = new List(); - Memberships = new List(); - IdentityIds = new List(); - } - - [DataMember] - public Guid ScopeId - { - get; - set; - } - - [DataMember] - public List Scopes - { - get; - set; - } - - [DataMember] - public List Groups - { - get; - set; - } - - [DataMember] - public List Memberships - { - get; - set; - } - - [DataMember] - public List IdentityIds - { - get; - set; - } - - public IdentitySnapshot Clone() - { - return new IdentitySnapshot() - { - ScopeId = this.ScopeId, - Scopes = this.Scopes?.Where(x => x != null).Select(x => x.Clone()).ToList(), - Groups = this.Groups?.Where(x => x != null).Select(x => x.Clone()).ToList(), - Memberships = this.Memberships?.Where(x => x != null).Select(x => x.Clone()).ToList(), - IdentityIds = this.IdentityIds.ToList(), - }; - } - - public override string ToString() - { - return string.Format("[ScopeId = {0}, Scopes={1}, Groups={2}, Memberships={3}, Identities={4}]", - ScopeId, - Scopes?.Count, - Groups?.Count, - Memberships?.Count, - IdentityIds?.Count); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityUpdateData.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityUpdateData.cs deleted file mode 100644 index e0084a566..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/IdentityUpdateData.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class IdentityUpdateData - { - [DataMember] - public Int32 Index { get; set; } - - [DataMember] - public Guid Id { get; set; } - - [DataMember] - public Boolean Updated { get; set; } - } -} \ No newline at end of file diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/RequestHeadersContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/RequestHeadersContext.cs deleted file mode 100644 index e473bfe12..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/RequestHeadersContext.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Headers; - -namespace GitHub.Services.Identity -{ - public class RequestHeadersContext - { - internal SequenceContext SequenceContext { get; set; } - - internal bool IgnoreCache { get; set; } - - public RequestHeadersContext(SequenceContext sequenceContext) : - this(sequenceContext, false) - { - } - - public RequestHeadersContext(SequenceContext sequenceContext, bool ignoreCache) - { - SequenceContext = sequenceContext; - IgnoreCache = ignoreCache; - } - - private static bool ParseOrGetDefault(string s) - { - if (!string.IsNullOrWhiteSpace(s) && bool.TryParse(s, out var value)) - { - return value; - } - return false; - } - - internal class HeadersUtils - { - public static KeyValuePair[] PopulateRequestHeaders(RequestHeadersContext requestHeaderContext) - { - if (requestHeaderContext == null) - { - return new KeyValuePair[0]; - } - - KeyValuePair[] sequenceContextHeaders = SequenceContext.HeadersUtils.PopulateRequestHeaders(requestHeaderContext.SequenceContext); - KeyValuePair[] resultHeaderPairs = new KeyValuePair[sequenceContextHeaders.Length + 1]; - sequenceContextHeaders.CopyTo(resultHeaderPairs, 0); - resultHeaderPairs[sequenceContextHeaders.Length] = new KeyValuePair(c_ignoreCacheHeader, requestHeaderContext.IgnoreCache.ToString()); - return resultHeaderPairs; - } - - public static bool TryExtractRequestHeaderContext(HttpRequestHeaders httpRequestHeaders, out RequestHeadersContext requestHeadersContext) - { - requestHeadersContext = null; - bool hasIgnoreCacheHeader = httpRequestHeaders.TryGetValues(c_ignoreCacheHeader, out IEnumerable ignoreCacheValue) && ignoreCacheValue != null; - bool hasSequenceContextHeader = SequenceContext.HeadersUtils.TryExtractSequenceContext(httpRequestHeaders, out SequenceContext sequenceContext); - bool ignoreCache = ParseOrGetDefault(ignoreCacheValue?.FirstOrDefault()); - requestHeadersContext = new RequestHeadersContext(sequenceContext, ignoreCache); - return hasIgnoreCacheHeader || hasSequenceContextHeader; - } - - private const string c_ignoreCacheHeader = "X-VSSF-IMS-IgnoreCache"; - } - - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/SequenceContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/SequenceContext.cs deleted file mode 100644 index da935a228..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/SequenceContext.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Headers; - -namespace GitHub.Services.Identity -{ - public class SequenceContext - { - public SequenceContext(long identitySequenceId, long groupSequenceId) : - this(identitySequenceId, groupSequenceId, SequenceContext.UnspecifiedSequenceId) - { - } - - public SequenceContext(long identitySequenceId, long groupSequenceId, long organizationIdentitySequenceId) : - this(identitySequenceId, groupSequenceId, organizationIdentitySequenceId, 0) - { - } - - public SequenceContext(long identitySequenceId, long groupSequenceId, long organizationIdentitySequenceId, long pageSize) - { - IdentitySequenceId = identitySequenceId; - GroupSequenceId = groupSequenceId; - OrganizationIdentitySequenceId = organizationIdentitySequenceId; - PageSize = pageSize; - } - - internal long IdentitySequenceId { get; } - - internal long GroupSequenceId { get; } - - internal long OrganizationIdentitySequenceId { get; } - - internal long PageSize { get; } - - internal SequenceContext Clone() - { - return new SequenceContext(IdentitySequenceId, GroupSequenceId, OrganizationIdentitySequenceId); - } - - public override string ToString() => $"[{nameof(IdentitySequenceId)}:{IdentitySequenceId}, {nameof(GroupSequenceId)}:{GroupSequenceId}, {nameof(OrganizationIdentitySequenceId)}:{OrganizationIdentitySequenceId}]"; - - internal const long UnspecifiedSequenceId = -1; - - internal static SequenceContext MaxSequenceContext = new SequenceContext(long.MaxValue, long.MaxValue, long.MaxValue, 0); - internal static SequenceContext InitSequenceContext = new SequenceContext(UnspecifiedSequenceId, UnspecifiedSequenceId, UnspecifiedSequenceId, 0); - - internal class HeadersUtils - { - internal const string MinIdentitySequenceId = "X-VSSF-MinIdentitySequenceId"; - internal const string MinGroupSequenceId = "X-VSSF-MinGroupSequenceId"; - internal const string MinOrgIdentitySequenceId = "X-VSSF-MinOrgIdentitySequenceId"; - internal const string PageSize = "X-VSSF-PagingSize"; - - internal static bool TryExtractSequenceContext(HttpRequestHeaders httpRequestHeaders, out SequenceContext sequenceContext) - { - sequenceContext = null; - bool hasMinIdentitySequenceHeader = httpRequestHeaders.TryGetValues(MinIdentitySequenceId, out var minIdentitySequenceIdValues) && minIdentitySequenceIdValues != null; - bool hasMinGroupSequenceHeader = httpRequestHeaders.TryGetValues(MinGroupSequenceId, out var minGroupSequenceIdValues) && minGroupSequenceIdValues != null; - bool hasMinOrgIdentitySequenceHeader = httpRequestHeaders.TryGetValues(MinOrgIdentitySequenceId, out var minOrgIdentitySequenceIdValues) && minOrgIdentitySequenceIdValues != null; - bool hasPageSizeHeader = httpRequestHeaders.TryGetValues(PageSize, out var pageSizeValues) && pageSizeValues != null; - - if (!hasMinGroupSequenceHeader && !hasMinIdentitySequenceHeader && !hasMinOrgIdentitySequenceHeader) - { - return false; - } - - long minIdentitySequenceId = ParseOrGetDefault(minIdentitySequenceIdValues?.FirstOrDefault()); - long minGroupSequenceId = ParseOrGetDefault(minGroupSequenceIdValues?.FirstOrDefault()); - long minOrgIdentitySequenceId = ParseOrGetDefault(minOrgIdentitySequenceIdValues?.FirstOrDefault()); - long pageSize = ParseOrGetDefault(pageSizeValues?.FirstOrDefault()); - sequenceContext = new SequenceContext(minIdentitySequenceId, minGroupSequenceId, minOrgIdentitySequenceId, pageSize); - return true; - } - - internal static KeyValuePair[] PopulateRequestHeaders(SequenceContext sequenceContext) - { - if (sequenceContext == null) - { - return new KeyValuePair[0]; - } - - return new[] - { - new KeyValuePair(MinIdentitySequenceId, sequenceContext.IdentitySequenceId.ToString()), - new KeyValuePair(MinGroupSequenceId, sequenceContext.GroupSequenceId.ToString()), - new KeyValuePair(MinOrgIdentitySequenceId, sequenceContext.OrganizationIdentitySequenceId.ToString()), - new KeyValuePair(PageSize, sequenceContext.PageSize.ToString()) - }; - } - - private static long ParseOrGetDefault(string s) - { - if (!string.IsNullOrWhiteSpace(s) && long.TryParse(s, out long value)) - { - return value; - } - return UnspecifiedSequenceId; - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/SwapIdentityInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/SwapIdentityInfo.cs deleted file mode 100644 index 25b7652cb..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/SwapIdentityInfo.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DataContract] - public class SwapIdentityInfo - { - public SwapIdentityInfo() - { - } - - public SwapIdentityInfo(Guid id1, Guid id2) - { - this.Id1 = id1; - this.Id2 = id2; - } - - [DataMember] - public Guid Id1 { get; private set; } - - [DataMember] - public Guid Id2 { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Identity/TenantInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Identity/TenantInfo.cs deleted file mode 100644 index 482d12254..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Identity/TenantInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Runtime.Serialization; - -namespace GitHub.Services.Identity -{ - [DebuggerDisplay("{TenantName}")] - [DataContract] - public class TenantInfo - { - [DataMember] - public Guid TenantId { get; set; } - - [DataMember] - public string TenantName { get; set; } - - [DataMember] - public bool HomeTenant { get; set; } - - [DataMember] - public IEnumerable VerifiedDomains { get; set; } - } -} \ No newline at end of file diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/AccountLicense.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/AccountLicense.cs deleted file mode 100644 index 7a113cbc6..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/AccountLicense.cs +++ /dev/null @@ -1,134 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GitHub.Services.Licensing -{ - /// - /// Represents an Account license - /// - public sealed class AccountLicense : License, IComparable - { - /// - /// An Early Adopter License - /// - public static readonly AccountLicense EarlyAdopter = new AccountLicense(AccountLicenseType.EarlyAdopter); - - /// - /// A Stakeholder License - /// - public static readonly AccountLicense Stakeholder = new AccountLicense(AccountLicenseType.Stakeholder); - - /// - /// An Express License - /// - public static readonly AccountLicense Express = new AccountLicense(AccountLicenseType.Express); - - /// - /// A Professional License - /// - public static readonly AccountLicense Professional = new AccountLicense(AccountLicenseType.Professional); - - /// - /// An Advanced License - /// - public static readonly AccountLicense Advanced = new AccountLicense(AccountLicenseType.Advanced); - - /// - /// Initializes an instance of the class - /// - /// The type of license - private AccountLicense(AccountLicenseType license) - : base(LicensingSource.Account, typeof(AccountLicenseType), (int)license) - { - } - - /// - /// Gets the license type for the license - /// - public AccountLicenseType License - { - get { return (AccountLicenseType)this.GetLicenseAsInt32(); } - } - - /// - /// Compares the current object with another object of the same type. - /// - /// A value that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the parameter.Zero This object is equal to . Greater than zero This object is greater than . - /// An object to compare with this object. - public int CompareTo(AccountLicense other) - { - return Compare(this, other); - } - - /// - /// Compares two objects of the same type. - /// - /// A value that indicates the relative order of the objects being compared. - /// The left-hand operand to compare - /// The right-hand operand to compare - public static int Compare(AccountLicense left, AccountLicense right) - { - if (object.ReferenceEquals(left, null)) - { - if (object.ReferenceEquals(right, null)) - { - return 0; - } - return -1; - } - else if (object.ReferenceEquals(right, null)) - { - return +1; - } - - return LicenseComparer.Instance.Compare(left, right); - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is greater than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator >(AccountLicense left, AccountLicense right) - { - return Compare(left, right) > 0; - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is less than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator <(AccountLicense left, AccountLicense right) - { - return Compare(left, right) < 0; - } - - /// - /// Gets a instance for the provided license type - /// - /// The type of license - /// A license for the provided license type - /// license was not in the list of allowed values - public static License GetLicense(AccountLicenseType license) - { - switch (license) - { - case AccountLicenseType.None: return None; - case AccountLicenseType.EarlyAdopter: return EarlyAdopter; - case AccountLicenseType.Stakeholder: return Stakeholder; - case AccountLicenseType.Express: return Express; - case AccountLicenseType.Professional: return Professional; - case AccountLicenseType.Advanced: return Advanced; - default: - throw new InvalidEnumArgumentException("license", (int)license, typeof(AccountLicenseType)); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/Definitions.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/Definitions.cs deleted file mode 100644 index ac75c659c..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/Definitions.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Licensing -{ - [DataContract] - public enum AssignmentSource - { - None = 0, - Unknown = 1, - GroupRule = 2 - } - - [DataContract] - public enum LicensingOrigin - { - None = 0, - OnDemandPrivateProject = 1, - OnDemandPublicProject = 2, - UserHubInvitation = 3, - PrivateProjectInvitation = 4, - PublicProjectInvitation = 5, - } - - [DataContract] - public enum LicensingSource - { - None = 0, - Account = 1, - Msdn = 2, - Profile = 3, - Auto = 4, - Trial = 5 - } - - [DataContract] - [ClientIncludeModel] - public enum MsdnLicenseType - { - None = 0, - Eligible = 1, - Professional = 2, - Platforms = 3, - TestProfessional = 4, - Premium = 5, - Ultimate = 6, - Enterprise = 7, - } - - [DataContract] - [ClientIncludeModel] - public enum AccountLicenseType - { - None = 0, - EarlyAdopter = 1, - Express = 2, - Professional = 3, - Advanced = 4, - Stakeholder = 5, - } - - [DataContract] - public enum VisualStudioOnlineServiceLevel - { - /// - /// No service rights. The user cannot access the account - /// - [EnumMember] - None = 0, - - /// - /// Default or minimum service level - /// - [EnumMember] - Express = 1, - - /// - /// Premium service level - either by purchasing on the Azure portal or by purchasing the appropriate MSDN subscription - /// - [EnumMember] - Advanced = 2, - - /// - /// Only available to a specific set of MSDN Subscribers - /// - [EnumMember] - AdvancedPlus = 3, - - /// - /// Stakeholder service level - /// - [EnumMember] - Stakeholder = 4, - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/License.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/License.cs deleted file mode 100644 index fc0e0987f..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/License.cs +++ /dev/null @@ -1,403 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Text; -using Newtonsoft.Json; - -namespace GitHub.Services.Licensing -{ - /// - /// The base class for a specific license source and license - /// - [JsonConverter(typeof(LicenseJsonConverter))] - [TypeConverter(typeof(LicenseTypeConverter))] - [JsonObject] - [DebuggerDisplay("{ToString(), nq}")] - public abstract class License : IEquatable - { - /// - /// Represents a non-existent license - /// - public static readonly License None = new NoLicense(); - - /// - /// Represents a license that is auto assigned at user sign-in (e.g. from msdn licenses) - /// - public static readonly License Auto = new AutoLicense(); - - private Type licenseEnumType; - private int license; - - /// - /// Initializes a new instance of the License type - /// - /// The source of the license - /// The type for the license enum - /// The value for the license - internal License(LicensingSource source, Type licenseEnumType, int license) - { - this.licenseEnumType = licenseEnumType; - this.license = license; - this.Source = source; - } - - /// - /// Gets the source of the license - /// - public LicensingSource Source { get; private set; } - - /// - /// Gets the internal value for the license - /// - internal int GetLicenseAsInt32() - { - return this.license; - } - - /// - /// Serves as a hash function for a particular type. - /// - /// A hash code for the current . - public override int GetHashCode() - { - return this.Source.GetHashCode() - ^ this.license.GetHashCode(); - } - - /// - /// Determines whether the specified System.Object is equal to the current . - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals(object obj) - { - return this.Equals(obj as License); - } - - /// - /// Determines whether the specified is equal to the current . - /// - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public bool Equals(License obj) - { - return obj != null - && this.Source == obj.Source - && this.license == obj.license; - } - - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - public override string ToString() - { - var sb = new StringBuilder(); - sb.Append(this.Source.ToString()); - sb.Append('-'); - sb.Append(Enum.GetName(this.licenseEnumType, this.license)); - return sb.ToString(); - } - - /// - /// Parses the provided text into a - /// - /// The text to parse - /// The parsed - /// The text was in the wrong format - public static License Parse(string text) - { - return Parse(text, ignoreCase: false); - } - - /// - /// Parses the provided text into a - /// - /// The text to parse - /// A value indicating whether to ignore the case of the text - /// The parsed - /// The text was in the wrong format - public static License Parse(string text, bool ignoreCase) - { - License license; - if (!TryParse(text, ignoreCase, out license)) - { - throw new FormatException(); - } - - return license; - } - - /// - /// Tries to parse the provided text into a - /// - /// The text to parse - /// The parsed - /// True if the could be parsed; otherwise, false - public static bool TryParse(string text, out License license) - { - return TryParse(text, false, out license); - } - - /// - /// Tries to parse the provided text into a - /// - /// The text to parse - /// A value indicating whether to ignore the case of the text - /// The parsed - /// True if the could be parsed; otherwise, false - public static bool TryParse(string text, bool ignoreCase, out License license) - { - license = None; - if (string.IsNullOrWhiteSpace(text)) - { - return false; - } - - var parts = text.Split('-'); - - LicensingSource source; - if (!Enum.TryParse(parts[0], ignoreCase, out source)) - { - return false; - } - - if (parts.Length == 1 && source == LicensingSource.None) - { - return true; - } - - if (parts.Length == 1 && source == LicensingSource.Auto) - { - license = Auto; - return true; - } - - if (parts.Length > 2) - { - return false; - } - - switch (source) - { - case LicensingSource.Msdn: - MsdnLicenseType msdnLicense; - if (Enum.TryParse(parts[1], ignoreCase, out msdnLicense) && msdnLicense != MsdnLicenseType.None) - { - license = MsdnLicense.GetLicense(msdnLicense); - return true; - } - - break; - - case LicensingSource.Account: - AccountLicenseType accountLicense; - if (Enum.TryParse(parts[1], ignoreCase, out accountLicense) && accountLicense != AccountLicenseType.None) - { - license = AccountLicense.GetLicense(accountLicense); - return true; - } - - break; - - case LicensingSource.Auto: - LicensingSource licenseSource; - if (Enum.TryParse(parts[1], ignoreCase, out licenseSource)) - { - license = AutoLicense.GetLicense(licenseSource); - return true; - } - - break; - } - - return false; - } - - /// - /// Gets a value indicating whether the two provided values are equivalent - /// - /// The first value - /// The second value - /// True if both values are equivalent; otherwise, false - public static bool Equals(License left, License right) - { - if (object.ReferenceEquals(left, null)) - { - return object.ReferenceEquals(right, null); - } - else if (object.ReferenceEquals(right, null)) - { - return false; - } - - return left.Equals(right); - } - - /// - /// Gets a value indicating whether the license is null or - /// - /// The license - /// true if the license is either null or ; otherwise, false - public static bool IsNullOrNone(License license) - { - return license == null || license.Source == LicensingSource.None; - } - - /// - /// Gets the license for the provided source and license type - /// - /// The source - /// The license type - /// The license - internal static License GetLicense(LicensingSource source, int license) - { - switch (source) - { - case LicensingSource.None: - return None; - - case LicensingSource.Account: - return AccountLicense.GetLicense((AccountLicenseType)license); - - case LicensingSource.Msdn: - return MsdnLicense.GetLicense((MsdnLicenseType)license); - - case LicensingSource.Profile: - throw new NotSupportedException(); - - case LicensingSource.Auto: - return Auto; - - default: - throw new InvalidEnumArgumentException("source", (int)source, typeof(LicensingSource)); - } - } - - /// - /// Gets a value indicating whether the two provided values are equivalent - /// - /// The first operand - /// The second operand - /// True if both values are equivalent; otherwise, false - public static bool operator ==(License left, License right) - { - return Equals(left, right); - } - - /// - /// Gets a value indicating whether the two provided values are not equivalent - /// - /// The first operand - /// The second operand - /// True if values are not equivalent; otherwise, false - public static bool operator !=(License left, License right) - { - return !Equals(left, right); - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is greater than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator >(License left, License right) - { - return LicenseComparer.Instance.Compare(left, right) > 0; - } - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is greater than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator >=(License left, License right) - { - return LicenseComparer.Instance.Compare(left, right) >= 0; - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is less than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator <(License left, License right) - { - return LicenseComparer.Instance.Compare(left, right) < 0; - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is less than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator <=(License left, License right) - { - return LicenseComparer.Instance.Compare(left, right) <= 0; - } - - /// - /// A concrete that represents no license - /// - private sealed class NoLicense : License - { - /// - /// Initializes a new instance of the class - /// - internal NoLicense() - : base(LicensingSource.None, null, 0) - { - } - - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - public override string ToString() - { - return "None"; - } - } - - internal sealed class AutoLicense : License - { - /// - /// Represents an Auto license where the source provider is MSDN - /// - internal static readonly License Msdn = GetLicense(LicensingSource.Msdn); - - /// - /// Initializes a new instance of the class - /// - internal AutoLicense() - : base(LicensingSource.Auto, null, 0) - { - } - - private AutoLicense(LicensingSource licenseSource) - : base(LicensingSource.Auto, typeof(LicensingSource), (int) licenseSource) - { - } - - /// - /// Gets a instance for the provided licensing source - /// - internal static AutoLicense GetLicense(LicensingSource source) - { - return new AutoLicense(source); - } - - /// - /// Returns a string that represents the current object. - /// - /// A string that represents the current object. - public override string ToString() - { - return this.GetLicenseAsInt32() == 0 ? "Auto" : base.ToString(); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseComparer.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseComparer.cs deleted file mode 100644 index 48c39f2dd..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseComparer.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.Licensing -{ - public class LicenseComparer : IComparer - { - public int Compare(License x, License y) - { - if (x == null && y == null) - { - return 0; - } - - if (x == null) - { - return -1; - } - - if (y == null) - { - return 1; - } - - // both licenses have to have a source of Account or Msdn to compare weights - if((x.Source == LicensingSource.Account || x.Source == LicensingSource.Msdn) - && (y.Source == LicensingSource.Account || y.Source == LicensingSource.Msdn)) - { - var thisLicenseWeight = GetWeight(x); - var otherLicenseWeight = GetWeight(y); - - return thisLicenseWeight.CompareTo(otherLicenseWeight); - } - - // Not a known source. Just do a license value compare. - return x.GetLicenseAsInt32().CompareTo(y.GetLicenseAsInt32()); - } - - public int GetWeight(License license) - { - if (license == License.None) - { - return 0; - } - else if (license == AccountLicense.Stakeholder) - { - return 1; - } - else if (license == AccountLicense.Express) - { - return 2; - } - else if (license == AccountLicense.Professional) - { - return 3; - } - else if (license == MsdnLicense.Eligible) - { - return 4; - } - else if (license == MsdnLicense.Professional) - { - return 5; - } - else if (license == AccountLicense.Advanced) - { - return 6; - } - else if (license == MsdnLicense.TestProfessional) - { - return 7; - } - else if (license == MsdnLicense.Platforms) - { - return 8; - } - else if (license == MsdnLicense.Premium) - { - return 9; - } - else if (license == MsdnLicense.Ultimate) - { - return 10; - } - else if (license == MsdnLicense.Enterprise) - { - return 11; - } - else if (license == AccountLicense.EarlyAdopter) - { - return 12; - } - - return 0; // Unexpected license - } - - public static LicenseComparer Instance { get; } = new LicenseComparer(); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseJsonConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseJsonConverter.cs deleted file mode 100644 index f7baceb7c..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseJsonConverter.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; -using System.Reflection; -using GitHub.Services.WebApi; -using Newtonsoft.Json; - -namespace GitHub.Services.Licensing -{ - /// - /// Converts between a and a JSON-serialized license string - /// - internal sealed class LicenseJsonConverter : VssSecureJsonConverter - { - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object - /// true if this instance can convert the specified object type; otherwise, false. - public override bool CanConvert(Type objectType) - { - return typeof(License).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The Newtonsoft.Json.JsonReader to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.String) - { - return License.Parse(reader.Value.ToString(), ignoreCase: true); - } - - if (reader.TokenType == JsonToken.Null) - { - return null; - } - - throw new JsonSerializationException(); - } - - /// - /// Writes the JSON representation of the object. - /// - /// The Newtonsoft.Json.JsonWriter to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - base.WriteJson(writer, value, serializer); - - if (value == null) - { - writer.WriteNull(); - return; - } - - var license = (License)value; - writer.WriteValue(license.ToString()); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseTypeConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseTypeConverter.cs deleted file mode 100644 index adedb23c2..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/LicenseTypeConverter.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GitHub.Services.Licensing -{ - /// - /// Performs type conversion for a License - /// - internal sealed class LicenseTypeConverter : TypeConverter - { - /// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context. - /// true if this converter can perform the conversion; otherwise, false. - /// An that provides a format context. - /// A that represents the type you want to convert from. - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); - } - - /// Returns whether this converter can convert the object to the specified type, using the specified context. - /// true if this converter can perform the conversion; otherwise, false. - /// An that provides a format context. - /// A that represents the type you want to convert to. - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - return destinationType == typeof(string) || base.CanConvertTo(context, destinationType); - } - - /// Converts the given object to the type of this converter, using the specified context and culture information. - /// An that represents the converted value. - /// An that provides a format context. - /// The to use as the current culture. - /// The to convert. - /// The conversion cannot be performed. - public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) - { - var text = value as string; - if (text != null) - { - return License.Parse(text); - } - - return base.ConvertFrom(context, culture, value); - } - - /// Converts the given value object to the specified type, using the specified context and culture information. - /// An that represents the converted value. - /// An that provides a format context. - /// A . If null is passed, the current culture is assumed. - /// The to convert. - /// The to convert the parameter to. - /// The parameter is null. - /// The conversion cannot be performed. - public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) - { - var license = value as License; - if (license != null && destinationType == typeof(string)) - { - return license.ToString(); - } - - return base.ConvertTo(context, culture, value, destinationType); - } - - /// Returns whether the given value object is valid for this type and for the specified context. - /// true if the specified value is valid for this object; otherwise, false. - /// An that provides a format context. - /// The to test for validity. - public override bool IsValid(ITypeDescriptorContext context, object value) - { - var text = value as string; - if (text != null) - { - License license; - return License.TryParse(text, out license); - } - - return base.IsValid(context, value); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Licensing/MsdnLicense.cs b/src/Sdk/WebApi/WebApi/Contracts/Licensing/MsdnLicense.cs deleted file mode 100644 index 8aefe17da..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Licensing/MsdnLicense.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GitHub.Services.Licensing -{ - /// - /// Represents an Msdn license - /// - public sealed class MsdnLicense : License, IComparable - { - /// - /// The account user is MSDN Eligible - /// - public static readonly MsdnLicense Eligible = new MsdnLicense(MsdnLicenseType.Eligible); - - /// - /// The account user has an MSDN Professional license - /// - public static readonly MsdnLicense Professional = new MsdnLicense(MsdnLicenseType.Professional); - - /// - /// The account user has an MSDN Platforms license - /// - public static readonly MsdnLicense Platforms = new MsdnLicense(MsdnLicenseType.Platforms); - - /// - /// The account user has an MSDN TestProfessional license - /// - public static readonly MsdnLicense TestProfessional = new MsdnLicense(MsdnLicenseType.TestProfessional); - - /// - /// The account user has an MSDN Premium license - /// - public static readonly MsdnLicense Premium = new MsdnLicense(MsdnLicenseType.Premium); - - /// - /// The account user has an MSDN Ultimate license - /// - public static readonly MsdnLicense Ultimate = new MsdnLicense(MsdnLicenseType.Ultimate); - - /// - /// The account user has an MSDN Enterprise license - /// - public static readonly MsdnLicense Enterprise = new MsdnLicense(MsdnLicenseType.Enterprise); - - /// - /// Initializes an instance of the class - /// - /// The type of license - private MsdnLicense(MsdnLicenseType license) - : base(LicensingSource.Msdn, typeof(MsdnLicenseType), (int)license) - { - } - - /// - /// Gets the license type for the license - /// - public MsdnLicenseType License - { - get { return (MsdnLicenseType)this.GetLicenseAsInt32(); } - } - - /// - /// Compares the current object with another object of the same type. - /// - /// A value that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the parameter.Zero This object is equal to . Greater than zero This object is greater than . - /// An object to compare with this object. - public int CompareTo(MsdnLicense other) - { - return Compare(this, other); - } - - /// - /// Compares two objects of the same type. - /// - /// A value that indicates the relative order of the objects being compared. - /// The left-hand operand to compare - /// The right-hand operand to compare - public static int Compare(MsdnLicense left, MsdnLicense right) - { - if (object.ReferenceEquals(left, null)) - { - if (object.ReferenceEquals(right, null)) return 0; - return -1; - } - else if (object.ReferenceEquals(right, null)) - { - return +1; - } - - return LicenseComparer.Instance.Compare(left, right); - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is greater than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator >(MsdnLicense left, MsdnLicense right) - { - return Compare(left, right) > 0; - } - - /// - /// Compares two objects of the same type. - /// - /// True if the left-hand value is less than the right-hand value; otherwise, false - /// The left-hand operand to compare - /// The right-hand operand to compare - public static bool operator <(MsdnLicense left, MsdnLicense right) - { - return Compare(left, right) < 0; - } - - /// - /// Gets a instance for the provided license type - /// - /// The type of license - /// A license for the provided license type - /// license was not in the list of allowed values - public static License GetLicense(MsdnLicenseType license) - { - switch (license) - { - case MsdnLicenseType.None: return None; - case MsdnLicenseType.Eligible: return Eligible; - case MsdnLicenseType.Professional: return Professional; - case MsdnLicenseType.Platforms: return Platforms; - case MsdnLicenseType.TestProfessional: return TestProfessional; - case MsdnLicenseType.Premium: return Premium; - case MsdnLicenseType.Ultimate: return Ultimate; - case MsdnLicenseType.Enterprise: return Enterprise; - default: - throw new InvalidEnumArgumentException("license", (int)license, typeof(MsdnLicenseType)); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Location/AccessMapping.cs b/src/Sdk/WebApi/WebApi/Contracts/Location/AccessMapping.cs deleted file mode 100644 index 622daf2db..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Location/AccessMapping.cs +++ /dev/null @@ -1,151 +0,0 @@ -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using System; -using System.Diagnostics; -using System.Runtime.Serialization; -using System.Xml; - -namespace GitHub.Services.Location -{ - /// - /// - /// - [DataContract] - public class AccessMapping : ISecuredObject - { - public AccessMapping() { } - - public AccessMapping(String moniker, String displayName, String accessPoint, Guid serviceOwner = new Guid()) - :this (moniker, displayName, accessPoint, serviceOwner, null) - { - } - - public AccessMapping(String moniker, String displayName, String accessPoint, Guid serviceOwner, String virtualDirectory) - { - DisplayName = displayName; - Moniker = moniker; - AccessPoint = accessPoint; - ServiceOwner = serviceOwner; - VirtualDirectory = virtualDirectory; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String DisplayName - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Moniker - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String AccessPoint - { - get; - set; - } - - /// - /// The service which owns this access mapping e.g. TFS, ELS, etc. - /// - [DataMember] - public Guid ServiceOwner - { - get; - set; - } - - /// - /// Part of the access mapping which applies context after the access point - /// of the server. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String VirtualDirectory - { - get; - set; - } - - public AccessMapping Clone() - { - return new AccessMapping(Moniker, DisplayName, AccessPoint, ServiceOwner, VirtualDirectory); - } - - /// - /// - /// - /// - /// - /// - internal static AccessMapping FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - AccessMapping obj = new AccessMapping(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - Boolean empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "AccessPoint": - obj.AccessPoint = reader.Value; - break; - case "DisplayName": - obj.DisplayName = reader.Value; - break; - case "Moniker": - obj.Moniker = reader.Value; - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => LocationSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => LocationSecurityConstants.Read; - - string ISecuredObject.GetToken() => LocationSecurityConstants.NamespaceRootToken; - #endregion - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Location/ConnectionData.cs b/src/Sdk/WebApi/WebApi/Contracts/Location/ConnectionData.cs deleted file mode 100644 index 3221dc29d..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Location/ConnectionData.cs +++ /dev/null @@ -1,397 +0,0 @@ -using GitHub.Services.Common; -using GitHub.Services.Common.Internal; -using GitHub.Services.WebApi; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.Serialization; -using System.Xml; -using IC = GitHub.Services.Identity; - -namespace GitHub.Services.Location -{ - /// - /// Data transfer class that holds information needed to set up a - /// connection with a VSS server. - /// - [DataContract] - public class ConnectionData : ISecuredObject - { - /// - /// The Id of the authenticated user who made this request. More information about the user can be - /// obtained by passing this Id to the Identity service - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IC.Identity AuthenticatedUser - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The Id of the authorized user who made this request. More information about the user can be - /// obtained by passing this Id to the Identity service - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IC.Identity AuthorizedUser - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The instance id for this host. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid InstanceId - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The id for the server. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid DeploymentId - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The type for the server Hosted/OnPremises. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DeploymentFlags DeploymentType - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The last user access for this instance. Null if not requested specifically. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTime? LastUserAccess - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// Data that the location service holds. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public LocationServiceData LocationServiceData - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The virtual directory of the host we are talking to. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String WebApplicationRelativeDirectory - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// - /// - /// - /// - /// - internal static ConnectionData FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - ConnectionData obj = new ConnectionData(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - Boolean empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "CatalogResourceId": - obj.m_catalogResourceId = XmlConvert.ToGuid(reader.Value); - break; - case "InstanceId": - obj.InstanceId = XmlConvert.ToGuid(reader.Value); - break; - case "ServerCapabilities": - obj.m_serverCapabilities = XmlConvert.ToInt32(reader.Value); - break; - case "WebApplicationRelativeDirectory": - obj.WebApplicationRelativeDirectory = reader.Value; - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "AuthenticatedUser": - obj.AuthenticatedUser = IC.Identity.FromXml(serviceProvider, reader); - break; - case "AuthorizedUser": - obj.AuthorizedUser = IC.Identity.FromXml(serviceProvider, reader); - break; - case "LocationServiceData": - obj.LocationServiceData = LocationServiceData.FromXml(serviceProvider, reader); - break; - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => LocationSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => LocationSecurityConstants.Read; - - string ISecuredObject.GetToken() => LocationSecurityConstants.NamespaceRootToken; - #endregion - - private Guid m_catalogResourceId; - private Int32 m_serverCapabilities; - } - - /// - /// Data transfer class used to transfer data about the location - /// service data over the web service. - /// - [DataContract] - public class LocationServiceData : ISecuredObject - { - /// - /// The identifier of the deployment which is hosting this location data - /// (e.g. SPS, TFS, ELS, Napa, etc.) - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid ServiceOwner - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// Data about the access mappings contained by this location service. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ICollection AccessMappings - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// Data that the location service holds. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Boolean ClientCacheFresh - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The time to live on the location service cache. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [DefaultValue(3600)] - public Int32 ClientCacheTimeToLive - { - get - { - return m_clientCacheTimeToLive; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - set - { - m_clientCacheTimeToLive = value; - } - } - - /// - /// The default access mapping moniker for the server. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String DefaultAccessMappingMoniker - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The obsolete id for the last change that - /// took place on the server (use LastChangeId64). - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int32 LastChangeId - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - /// - /// The non-truncated 64-bit id for the last change that - /// took place on the server. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int64 LastChangeId64 - { - get - { - // Use obsolete truncated 32-bit value when receiving message from "old" server that doesn't provide 64-bit value - return m_lastChangeId64 != 0 ? m_lastChangeId64 : LastChangeId; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - set - { - m_lastChangeId64 = value; - } - } - - /// - /// Data about the service definitions contained by this location service. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ICollection ServiceDefinitions - { - get; - - [EditorBrowsable(EditorBrowsableState.Never)] - set; - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => LocationSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => LocationSecurityConstants.Read; - - string ISecuredObject.GetToken() => LocationSecurityConstants.NamespaceRootToken; - #endregion - - /// - /// - /// - /// - /// - /// - internal static LocationServiceData FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - LocationServiceData obj = new LocationServiceData(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - Boolean empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "AccessPointsDoNotIncludeWebAppRelativeDirectory": - obj.m_accessPointsDoNotIncludeWebAppRelativeDirectory = XmlConvert.ToBoolean(reader.Value); - break; - case "ClientCacheFresh": - obj.ClientCacheFresh = XmlConvert.ToBoolean(reader.Value); - break; - case "DefaultAccessMappingMoniker": - obj.DefaultAccessMappingMoniker = reader.Value; - break; - case "LastChangeId": - obj.LastChangeId = XmlConvert.ToInt32(reader.Value); - break; - case "ClientCacheTimeToLive": - obj.ClientCacheTimeToLive = XmlConvert.ToInt32(reader.Value); - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "AccessMappings": - obj.AccessMappings = XmlUtility.ArrayOfObjectFromXml(serviceProvider, reader, "AccessMapping", false, AccessMapping.FromXml); - break; - case "ServiceDefinitions": - obj.ServiceDefinitions = XmlUtility.ArrayOfObjectFromXml(serviceProvider, reader, "ServiceDefinition", false, ServiceDefinition.FromXml); - break; - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - - private Int32 m_clientCacheTimeToLive = 3600; - private Boolean m_accessPointsDoNotIncludeWebAppRelativeDirectory; - private Int64 m_lastChangeId64; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Location/Constants.cs b/src/Sdk/WebApi/WebApi/Contracts/Location/Constants.cs deleted file mode 100644 index 83f5b4c07..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Location/Constants.cs +++ /dev/null @@ -1,107 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.ComponentModel; -using System.Runtime.Serialization; - -namespace GitHub.Services.Location -{ - /// - /// - /// - [DataContract] - public enum RelativeToSetting - { - [EnumMember] - Context = 0, - - [EnumMember] - WebApplication = 2, - - [EnumMember] - FullyQualified = 3 - } - - [DataContract] - public enum ServiceStatus : byte - { - [EnumMember] - Assigned = 0, - - [EnumMember] - Active = 1, - - [EnumMember] - Moving = 2, - } - - [EditorBrowsable(EditorBrowsableState.Never)] - [DataContract] - public enum InheritLevel : byte - { - None = 0, - - // The definition is visible on the deployment - Deployment = 1, - - // The definition is visible on every account (unless overridden) - Account = 2, - - // The definition is visible on every collection (unless overridden) - Collection = 4, - - All = Deployment | Account | Collection - } - - /// - /// - /// - public static class ServiceInterfaces - { - public const String LocationService2 = "LocationService2"; - public const String VsService = "VsService"; - public const String VirtualLocation = "VirtualLocation"; - } - - public static class LocationServiceConstants - { - /// - /// If a Location Service has an entry for an application location service, that - /// location service definition will have an identifier of this value. - /// - public static readonly Guid ApplicationIdentifier = new Guid("8d299418-9467-402b-a171-9165e2f703e2"); - - /// - /// Pointer to the root location service instance - /// - public static readonly Guid RootIdentifier = new Guid("951917AC-A960-4999-8464-E3F0AA25B381"); - - - /// - /// All Location Services have a reference to their own service definition. That - /// service definition has an identifier of this value. - /// - public static readonly Guid SelfReferenceIdentifier = new Guid("464CCB8D-ABAF-4793-B927-CFDC107791EE"); - } - - [GenerateAllConstants] - public static class AccessMappingConstants - { - public static readonly string PublicAccessMappingMoniker = "PublicAccessMapping"; - public static readonly string ServerAccessMappingMoniker = "ServerAccessMapping"; - public static readonly string ClientAccessMappingMoniker = "ClientAccessMapping"; - public static readonly string HostGuidAccessMappingMoniker = "HostGuidAccessMapping"; - public static readonly string RootDomainMappingMoniker = "RootDomainMapping"; - public static readonly string AzureInstanceMappingMoniker = "AzureInstanceMapping"; - public static readonly string ServicePathMappingMoniker = "ServicePathMapping"; - public static readonly string ServiceDomainMappingMoniker = "ServiceDomainMapping"; - public static readonly string LegacyPublicAccessMappingMoniker = "LegacyPublicAccessMapping"; - public static readonly string MessageQueueAccessMappingMoniker = "MessageQueueAccessMapping"; - public static readonly string LegacyAppDotAccessMappingMoniker = "LegacyAppDotDomain"; - public static readonly string AffinitizedMultiInstanceAccessMappingMoniker = "AffinitizedMultiInstanceAccessMapping"; - - public static readonly string VstsAccessMapping = "VstsAccessMapping"; - public static readonly string DevOpsAccessMapping = "CodexAccessMapping"; - - [Obsolete][EditorBrowsable(EditorBrowsableState.Never)] public static readonly string ServiceAccessMappingMoniker = "ServiceAccessMappingMoniker"; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Location/LocationMapping.cs b/src/Sdk/WebApi/WebApi/Contracts/Location/LocationMapping.cs deleted file mode 100644 index 24d73a2bd..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Location/LocationMapping.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Diagnostics; -using System.Runtime.Serialization; -using System.Xml; -using System.Xml.Serialization; -using GitHub.Services.WebApi; -using GitHub.Services.Common; - -namespace GitHub.Services.Location -{ - /// - /// - /// - [DataContract] - public class LocationMapping : ISecuredObject - { - public LocationMapping() { } - - public LocationMapping(String accessMappingMoniker, String location) - { - AccessMappingMoniker = accessMappingMoniker; - Location = location; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("accessMappingMoniker")] // needed for servicing serialization - public String AccessMappingMoniker - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("location")] // needed for servicing serialization - public String Location - { - get; - set; - } - - public override string ToString() => Location; - - /// - /// - /// - /// - /// - /// - internal static LocationMapping FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - LocationMapping obj = new LocationMapping(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - Boolean empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "accessMappingMoniker": - obj.AccessMappingMoniker = reader.Value; - break; - case "location": - obj.Location = reader.Value; - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => LocationSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => LocationSecurityConstants.Read; - - string ISecuredObject.GetToken() - { - return LocationSecurityConstants.ServiceDefinitionsToken; - } - #endregion - - public LocationMapping Clone() - => new LocationMapping(AccessMappingMoniker, Location); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Location/ResourceAreaInfo.cs b/src/Sdk/WebApi/WebApi/Contracts/Location/ResourceAreaInfo.cs deleted file mode 100644 index b784e3b20..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Location/ResourceAreaInfo.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.Location -{ - [DataContract] - public class ResourceAreaInfo - { - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid Id - { - get; - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Name - { - get; - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String LocationUrl - { - get; - set; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Location/ServiceDefinition.cs b/src/Sdk/WebApi/WebApi/Contracts/Location/ServiceDefinition.cs deleted file mode 100644 index bbf1635e7..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Location/ServiceDefinition.cs +++ /dev/null @@ -1,649 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Runtime.Serialization; -using System.Xml; -using System.Xml.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.Location -{ - /// - /// - /// - [DebuggerDisplay("{ServiceType}:{Identifier}")] - [DataContract] - public class ServiceDefinition : ISecuredObject - { - public ServiceDefinition() - { - LocationMappings = new List(); - Status = ServiceStatus.Active; - Properties = new PropertiesCollection(); - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public ServiceDefinition( - String serviceType, - Guid identifier, - String displayName, - String relativePath, - RelativeToSetting relativeToSetting, - String description, - String toolId, - List locationMappings = null, - Guid serviceOwner = new Guid()) - { - ServiceType = serviceType; - Identifier = identifier; - DisplayName = displayName; - RelativePath = relativePath; - RelativeToSetting = relativeToSetting; - Description = description; - ToolId = toolId; - - if (locationMappings == null) - { - locationMappings = new List(); - } - - LocationMappings = locationMappings; - ServiceOwner = serviceOwner; - Properties = new PropertiesCollection(); - Status = ServiceStatus.Active; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("serviceType")] // XML Attribute is required for servicing xml de-serialization - public String ServiceType - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("identifier")] // XML Attribute is required for servicing xml de-serialization - public Guid Identifier - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("displayName")] // XML Attribute is required for servicing xml de-serialization - public String DisplayName - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public RelativeToSetting RelativeToSetting - { - get; - set; - } - - [XmlAttribute("relativeToSetting")] // XML Attribute is required for servicing xml de-serialization - [EditorBrowsable(EditorBrowsableState.Never)] - public Int32 RelativeToSettingValue - { - get - { - return (Int32)RelativeToSetting; - } - set - { - RelativeToSetting = (RelativeToSetting)value; - } - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("relativePath")] // XML Attribute is required for servicing xml de-serialization - public String RelativePath - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("description")] // XML Attribute is required for servicing xml de-serialization - public String Description - { - get; - set; - } - - /// - /// The service which owns this definition e.g. TFS, ELS, etc. - /// - [DataMember] - public Guid ServiceOwner - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public List LocationMappings - { - get; - set; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - [XmlAttribute("toolId")] // XML Attribute is required for servicing xml de-serialization - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String ToolId { get; set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String ParentServiceType - { - get; - set; - } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid ParentIdentifier - { - get; - set; - } - - [DefaultValue(ServiceStatus.Active)] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ServiceStatus Status - { - get; - set; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlAttribute("inheritLevel")] - public InheritLevel InheritLevel - { - get; - set; - } - - /// - /// - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - [XmlIgnore] - public PropertiesCollection Properties - { - get; - set; - } - - //***************************************************************************************************************** - /// - /// Generic Property accessor. Returns default value of T if not found - /// - //***************************************************************************************************************** - public T GetProperty(String name, T defaultValue) - { - T value; - if (Properties != null && Properties.TryGetValue(name, out value)) - { - return value; - } - else - { - return defaultValue; - } - } - - //***************************************************************************************************************** - /// - /// Property accessor. value will be null if not found. - /// - //***************************************************************************************************************** - public Boolean TryGetProperty(String name, out Object value) - { - value = null; - return Properties == null ? false : Properties.TryGetValue(name, out value); - } - - //***************************************************************************************************************** - /// - /// Internal function to initialize persisted property. - /// - //***************************************************************************************************************** - public void SetProperty(String name, Object value) - { - m_hasModifiedProperties = true; - - //don't remove properties with null - //vals, just set them to null... - Properties[name] = value; - } - - //***************************************************************************************************************** - /// - /// - /// - /// - //***************************************************************************************************************** - [EditorBrowsable(EditorBrowsableState.Never)] - public Boolean HasModifiedProperties - { - get - { - return m_hasModifiedProperties; - } - } - - //***************************************************************************************************************** - /// - /// - /// - //***************************************************************************************************************** - [EditorBrowsable(EditorBrowsableState.Never)] - public void ResetModifiedProperties() - { - m_hasModifiedProperties = false; - } - - /// - /// The current resource version supported by this resource location. Copied from ApiResourceLocation. - /// - [XmlAttribute("resourceVersion")] - [DefaultValue(0)] - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Int32 ResourceVersion { get; set; } - - /// - /// Minimum api version that this resource supports. Copied from ApiResourceLocation. - /// - [XmlIgnore] - public Version MinVersion { get; set; } - - /// - /// Minimum api version that this resource supports. Copied from ApiResourceLocation. - /// - [XmlAttribute("minVersion")] - [DefaultValue(null)] - [DataMember(IsRequired = false, EmitDefaultValue = false, Name = "MinVersion")] - public String MinVersionString - { - get - { - if (MinVersion == null) - { - return null; - } - else - { - return MinVersion.ToString(2); - } - } - set - { - if (String.IsNullOrEmpty(value)) - { - MinVersion = null; - } - else - { - MinVersion = new Version(value); - } - } - } - - /// - /// Maximum api version that this resource supports (current server version for this resource). Copied from ApiResourceLocation. - /// - [XmlIgnore] - public Version MaxVersion { get; set; } - - /// - /// Maximum api version that this resource supports (current server version for this resource). Copied from ApiResourceLocation. - /// - [XmlAttribute("maxVersion")] - [DefaultValue(null)] - [DataMember(IsRequired = false, EmitDefaultValue = false, Name = "MaxVersion")] - public String MaxVersionString - { - get - { - if (MaxVersion == null) - { - return null; - } - else - { - return MaxVersion.ToString(2); - } - } - set - { - if (String.IsNullOrEmpty(value)) - { - MaxVersion = null; - } - else - { - MaxVersion = new Version(value); - } - } - } - - /// - /// The latest version of this resource location that is in "Release" (non-preview) mode. Copied from ApiResourceLocation. - /// - [XmlIgnore] - public Version ReleasedVersion { get; set; } - - /// - /// The latest version of this resource location that is in "Release" (non-preview) mode. Copied from ApiResourceLocation. - /// - [XmlAttribute("releasedVersion")] - [DefaultValue(null)] - [DataMember(IsRequired = false, EmitDefaultValue = false, Name = "ReleasedVersion")] - public String ReleasedVersionString - { - get - { - if (ReleasedVersion == null) - { - return null; - } - else - { - return ReleasedVersion.ToString(2); - } - } - set - { - if (String.IsNullOrEmpty(value)) - { - ReleasedVersion = null; - } - else - { - ReleasedVersion = new Version(value); - } - } - } - - /// - /// - /// - /// - public ServiceDefinition Clone() - { - return Clone(true); - } - - public ServiceDefinition Clone(Boolean includeLocationMappings) - { - List locationMappings = null; - - if (LocationMappings != null && includeLocationMappings) - { - locationMappings = new List(LocationMappings.Count); - - foreach (LocationMapping mapping in LocationMappings) - { - locationMappings.Add(new LocationMapping() - { - AccessMappingMoniker = mapping.AccessMappingMoniker, - Location = mapping.Location - }); - } - } - else - { - locationMappings = new List(); - } - - PropertiesCollection properties = null; - - if (Properties != null) - { - // since we are cloning, don't validate the values - properties = new PropertiesCollection(Properties, validateExisting: false); - } - else - { - properties = new PropertiesCollection(); - } - - ServiceDefinition serviceDefinition = new ServiceDefinition() - { - ServiceType = ServiceType, - Identifier = Identifier, - DisplayName = DisplayName, - RelativePath = RelativePath, - RelativeToSetting = RelativeToSetting, - Description = Description, - LocationMappings = locationMappings, - ServiceOwner = ServiceOwner, - ToolId = ToolId, - ParentServiceType = ParentServiceType, - ParentIdentifier = ParentIdentifier, - Status = Status, - Properties = properties, - ResourceVersion = ResourceVersion, - MinVersion = MinVersion, - MaxVersion = MaxVersion, - ReleasedVersion = ReleasedVersion - }; - - serviceDefinition.ResetModifiedProperties(); - return serviceDefinition; - } - - /// - /// - /// - /// - /// - /// - internal static ServiceDefinition FromXml(IServiceProvider serviceProvider, XmlReader reader) - { - ServiceDefinition obj = new ServiceDefinition(); - Debug.Assert(reader.NodeType == XmlNodeType.Element, "Expected a node."); - - Boolean empty = reader.IsEmptyElement; - - // Process the xml attributes - if (reader.HasAttributes) - { - while (reader.MoveToNextAttribute()) - { - switch (reader.Name) - { - case "description": - obj.Description = reader.Value; - break; - case "displayName": - obj.DisplayName = reader.Value; - break; - case "identifier": - obj.Identifier = XmlConvert.ToGuid(reader.Value); - break; - case "isSingleton": - obj.m_isSingleton = XmlConvert.ToBoolean(reader.Value); - break; - case "relativePath": - obj.RelativePath = reader.Value; - break; - case "relativeToSetting": - obj.RelativeToSetting = (RelativeToSetting)XmlConvert.ToInt32(reader.Value); - break; - case "serviceType": - obj.ServiceType = reader.Value; - break; - case "toolId": - obj.ToolId = reader.Value; - break; - case "resourceVersion": - obj.ResourceVersion = XmlConvert.ToInt32(reader.Value); - break; - case "minVersion": - obj.MinVersionString = reader.Value; - break; - case "maxVersion": - obj.MaxVersionString = reader.Value; - break; - case "releasedVersion": - obj.ReleasedVersionString = reader.Value; - break; - default: - // Allow attributes such as xsi:type to fall through - break; - } - } - } - - // Process the fields in Xml elements - reader.Read(); - if (!empty) - { - while (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "LocationMappings": - obj.LocationMappings = new List(XmlUtility.ArrayOfObjectFromXml(serviceProvider, reader, "LocationMapping", false, LocationMapping.FromXml)); - break; - case "Properties": - // Ignore properties - reader.ReadOuterXml(); - break; - default: - // Make sure that we ignore XML node trees we do not understand - reader.ReadOuterXml(); - break; - } - } - reader.ReadEndElement(); - } - return obj; - } - - /// - /// Returns the LocationMapping for the AccessMapping provided or null - /// if this ServiceDefinition does not have a LocationMapping for the provided - /// AccessMapping. This function will always return null if it is called - /// on a non-relative ServiceDefinition. - /// - /// - /// The AccessMapping to find the LocationMapping for. - /// - /// - /// The LocationMapping for the AccessMapping provided or null if this - /// ServiceDefinition does not have a LocationMapping for the provided - /// AccessMapping. This function will always return null if it is called - /// on a non-relative ServiceDefinition. - /// - public LocationMapping GetLocationMapping(AccessMapping accessMapping) - { - ArgumentUtility.CheckForNull(accessMapping, "accessMapping"); - - return GetLocationMapping(accessMapping.Moniker); - } - - public LocationMapping GetLocationMapping(String accessMappingMoniker) - { - ArgumentUtility.CheckForNull(accessMappingMoniker, "accessMappingMoniker"); - - // If this is FullyQualified then look through our location mappings - if (RelativeToSetting == RelativeToSetting.FullyQualified) - { - foreach (LocationMapping locationMapping in LocationMappings) - { - if (VssStringComparer.AccessMappingMoniker.Equals(locationMapping.AccessMappingMoniker, accessMappingMoniker)) - { - return locationMapping; - } - } - } - - // We weren't able to find the location for the access mapping. Return null. - return null; - } - - /// - /// Adds a location mapping for the provided access mapping and location - /// to the service definition. Note that if a mapping already exists for - /// the provided access mapping, it will be overwritten. - /// - /// The access mapping this location mapping is for. - /// This access mapping must already be registered in the LocationService. To create - /// a new access mapping, see LocationService.ConfigureAccessMapping - /// This value must be null if the RelativeToSetting - /// for this ServiceDefinition is something other than FullyQualified. If - /// this ServiceDefinition has a RelativeToSetting of FullyQualified, this - /// value must not be null and should be the location where this service resides - /// for this access mapping. - public void AddLocationMapping(AccessMapping accessMapping, String location) - { - if (RelativeToSetting != RelativeToSetting.FullyQualified) - { - throw new InvalidOperationException(WebApiResources.RelativeLocationMappingErrorMessage()); - } - - // Make sure the location has a value - if (location == null) - { - throw new ArgumentException(WebApiResources.FullyQualifiedLocationParameter()); - } - - // See if an entry for this access mapping already exists, if it does, overwrite it. - foreach (LocationMapping mapping in LocationMappings) - { - if (VssStringComparer.AccessMappingMoniker.Equals(mapping.AccessMappingMoniker, accessMapping.Moniker)) - { - mapping.Location = location; - return; - } - } - - // This is a new entry for this access mapping, just add it. - LocationMappings.Add(new LocationMapping() { AccessMappingMoniker = accessMapping.Moniker, Location = location }); - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => LocationSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => LocationSecurityConstants.Read; - - string ISecuredObject.GetToken() - { - return LocationSecurityConstants.ServiceDefinitionsToken; - } - #endregion - - private Boolean m_isSingleton; - private Boolean m_hasModifiedProperties = true; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/PagedList.cs b/src/Sdk/WebApi/WebApi/Contracts/PagedList.cs deleted file mode 100644 index 93e8097ad..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/PagedList.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.WebApi -{ - public interface IPagedList : IList - { - string ContinuationToken { get; } - } - - public class PagedList : List, IPagedList - { - public PagedList(IEnumerable list, String continuationToken) - : base(list) - { - this.ContinuationToken = continuationToken; - } - - public String ContinuationToken - { - get; - private set; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/AddPatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/AddPatchOperation.cs deleted file mode 100644 index 959e16210..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/AddPatchOperation.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Collections; -using System.ComponentModel; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Patch.Json; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Represents the JSON Patch Add operation. - /// - /// The model the patch operation applies to. - public class AddPatchOperation : PatchOperation - { - public AddPatchOperation() - { - this.Operation = Operation.Add; - } - - public AddPatchOperation(string path, object value): this() - { - this.Path = path; - this.Value = value; - } - - /// - /// Creates the strongly typed PatchOperation and validates the operation. - /// - /// The simple json patch operation model. - /// A valid and strongly typed PatchOperation. - [EditorBrowsable(EditorBrowsableState.Never)] - public static new PatchOperation CreateFromJson(JsonPatchOperation operation) - { - ValidatePath(operation); - - var value = ValidateAndGetValue(operation); - if (value == null) - { - throw new VssPropertyValidationException("Value", PatchResources.ValueCannotBeNull()); - } - - return new AddPatchOperation(operation.Path, value); - } - - /// - /// Applies the Add patch operation to the target - /// - /// The object to apply the operation to. - public override void Apply(TModel target) - { - this.Apply( - target, - (type, parent, current) => - { - // Empty current means replace the whole object. - if (string.IsNullOrEmpty(current)) - { - parent = this.Value; - } - else if (type.IsList()) - { - var list = (IList)parent; - if (current == EndOfIndex) - { - list.Add(this.Value); - } - else - { - int index; - // When index == list.Count it's the same - // as doing an index append to the end. - if (int.TryParse(current, out index) && - list.Count >= index) - { - list.Insert(index, this.Value); - } - else - { - // We can't insert beyond the length of the list. - throw new PatchOperationFailedException(PatchResources.IndexOutOfRange(this.Path)); - } - } - } - else if (type.IsDictionary()) - { - ((IDictionary)parent)[current] = this.Value; - } - else - { - type.SetMemberValue(current, parent, this.Value); - } - }); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/Exceptions.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/Exceptions.cs deleted file mode 100644 index a9d4ca455..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/Exceptions.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi.Patch -{ - [Serializable] - [ExceptionMapping("0.0", "3.0", "PatchOperationFailedException", "GitHub.Services.WebApi.Patch.PatchOperationFailedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class PatchOperationFailedException : VssServiceException - { - public PatchOperationFailedException() - { - } - - public PatchOperationFailedException(string message) - : base(message) - { - } - - public PatchOperationFailedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected PatchOperationFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [ExceptionMapping("0.0", "3.0", "InvalidPatchFieldNameException", "GitHub.Services.WebApi.Patch.InvalidPatchFieldNameException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidPatchFieldNameException : PatchOperationFailedException - { - public InvalidPatchFieldNameException(string message) - : base(message) - { - } - } - - [Serializable] - [ExceptionMapping("0.0", "3.0", "TestPatchOperationFailedException", "GitHub.Services.WebApi.Patch.TestPatchOperationFailedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class TestPatchOperationFailedException : PatchOperationFailedException - { - public TestPatchOperationFailedException() - { - } - - public TestPatchOperationFailedException(string message) - : base(message) - { - } - - public TestPatchOperationFailedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected TestPatchOperationFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchDocument.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchDocument.cs deleted file mode 100644 index b4a3a119e..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchDocument.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// The interface for the Patch Document - /// - /// The type this patch document applies to. - public interface IPatchDocument : IPatchOperationApplied, IPatchOperationApplying - { - /// - /// The patch operations. - /// - IEnumerable> Operations { get; } - - /// - /// Applies the operations to the target object. - /// - /// The object to apply the operations to. - void Apply(TModel target); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperation.cs deleted file mode 100644 index e7109867a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperation.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// The interface for the Patch Operation. - /// - /// The type this patch document applies to. - public interface IPatchOperation : IPatchOperationApplied, IPatchOperationApplying - { - /// - /// The operation to perform. - /// - Operation Operation { get; } - - /// - /// The JSON path to apply on the model for this operation. - /// - string Path { get; } - - /// - /// The JSON path split into segments - /// - IEnumerable EvaluatedPath { get; } - - /// - /// The path to copy/move from, applies only to the Copy/Move operation. - /// - string From { get; } - - /// - /// The value to set with this patch operation. Only applies to - /// Add/Replace/Test. - /// - /// The strongly (best effort) typed representation of the value. - object Value { get; } - - /// - /// Applies the operation to the target object. - /// - /// The object to have the operation applied to. - void Apply(TModel target); - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperationApplied.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperationApplied.cs deleted file mode 100644 index ad8926e83..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperationApplied.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Event for when a patch operation has been applied. - /// - public interface IPatchOperationApplied - { - event PatchOperationAppliedEventHandler PatchOperationApplied; - } - - /// - /// Event handler for patch operation applied. - /// - public delegate void PatchOperationAppliedEventHandler(object sender, PatchOperationAppliedEventArgs e); -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperationApplying.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperationApplying.cs deleted file mode 100644 index fd41c8488..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/IPatchOperationApplying.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Event for when a patch operation is about to be applied - /// - public interface IPatchOperationApplying - { - event PatchOperationApplyingEventHandler PatchOperationApplying; - } - - /// - /// Event handler for patch operation applying. - /// - public delegate void PatchOperationApplyingEventHandler(object sender, PatchOperationApplyingEventArgs e); -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/Json/JsonPatchDocument.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/Json/JsonPatchDocument.cs deleted file mode 100644 index 02166afac..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/Json/JsonPatchDocument.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi.Patch.Json -{ - /// - /// The JSON model for JSON Patch Operations - /// - [ClientIncludeModel] - public class JsonPatchDocument : List - { - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/Json/JsonPatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/Json/JsonPatchOperation.cs deleted file mode 100644 index 08cf4516a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/Json/JsonPatchOperation.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi.Patch.Json -{ - /// - /// The JSON model for a JSON Patch operation - /// - [DataContract] - public class JsonPatchOperation - { - /// - /// The patch operation - /// - [DataMember(Name = "op", IsRequired = true)] - public Operation Operation { get; set; } - - /// - /// The path for the operation. - /// In the case of an array, a zero based index can be used to specify the position in the array (e.g. /biscuits/0/name). The "-" character can be used instead of an index to insert at the end of the array (e.g. /biscuits/-). - /// - [DataMember(IsRequired = true)] - public string Path { get; set; } - - /// - /// The path to copy from for the Move/Copy operation. - /// - /// - [DataMember] - public string From { get; set; } - - /// - /// The value for the operation. - /// This is either a primitive or a JToken. - /// - [DataMember] - public object Value { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/ObjectDictionaryConverter.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/ObjectDictionaryConverter.cs deleted file mode 100644 index fec6cb8b9..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/ObjectDictionaryConverter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace GitHub.Services.WebApi.Patch -{ - internal class ObjectDictionaryConverter : CustomCreationConverter> - { - public override IDictionary Create(Type objectType) - { - return new Dictionary(); - } - - public override bool CanConvert(Type objectType) - { - // in addition to handling IDictionary - // we want to handle the deserialization of dict value - // which is of type object - return objectType == typeof(object) || base.CanConvert(objectType); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.StartObject || - reader.TokenType == JsonToken.Null) - { - return base.ReadJson(reader, objectType, existingValue, serializer); - } - - // if the next token is not an object - // then fall back on standard deserializer (strings, numbers etc.) - return serializer.Deserialize(reader); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/Operation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/Operation.cs deleted file mode 100644 index 10883914a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/Operation.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace GitHub.Services.WebApi.Patch -{ - // See RFC 6902 - JSON Patch for more details. - // http://www.faqs.org/rfcs/rfc6902.html - public enum Operation - { - Add, - Remove, - Replace, - Move, - Copy, - Test - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperation.cs deleted file mode 100644 index 433100c77..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperation.cs +++ /dev/null @@ -1,400 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Patch.Json; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// PatchOperation represents a single JSON Patch operation. - /// - /// The model to validate and apply the patch operation against. - public abstract class PatchOperation : IPatchOperation - { - /// - /// The JSON Patch representation of insertion at the end of a list. - /// - public const string EndOfIndex = "-"; - - /// - /// The JSON Patch path separator. - /// - public const string PathSeparator = "/"; - - /// - /// The serializer that handles the object dictionary case. - /// - private static JsonSerializer serializer; - - /// - /// The path split into a string IEnumerable. - /// - private IEnumerable evaluatedPath; - - /// - /// Static constructor to create the serializer once with the - /// ObjectDictionaryConverter which converts JObject to dictionary - /// when the underlying type of the target is an object. - /// - static PatchOperation() - { - serializer = new JsonSerializer(); - serializer.Converters.Add(new ObjectDictionaryConverter()); - } - - /// - /// Event fired before applying a patch operation. - /// - public event PatchOperationApplyingEventHandler PatchOperationApplying; - - /// - /// Event fired after a patch operation has been applied. - /// - public event PatchOperationAppliedEventHandler PatchOperationApplied; - - /// - /// The operation to perform. - /// - public Operation Operation { get; protected set; } - - /// - /// The JSON path to apply on the model for this operation. - /// - public string Path { get; protected set; } - - /// - /// The path to apply that has been converted to an IEnumerable. - /// - public IEnumerable EvaluatedPath - { - get - { - if (this.evaluatedPath == null && this.Path != null) - { - this.evaluatedPath = SplitPath(this.Path); - } - - return this.evaluatedPath; - } - } - - /// - /// The path to copy/move from, applies only to the Copy/Move operation. - /// - public string From { get; protected set; } - - /// - /// The value to set with this patch operation. Only applies to - /// Add/Replace/Test. - /// - /// The strongly (best effort) typed representation of the value. - public object Value { get; protected set; } - - /// - /// Applies the operation to the target object. - /// - /// The object to have the operation applied to. - [EditorBrowsable(EditorBrowsableState.Never)] - public abstract void Apply(TModel target); - - /// - /// Creates the strongly typed PatchOperation from the json patch operation provided. - /// - /// The json patch operation. - /// The strongly typed patch operation. - [EditorBrowsable(EditorBrowsableState.Never)] - public static PatchOperation CreateFromJson(JsonPatchOperation operation) - { - if (operation != null) - { - switch (operation.Operation) - { - case Operation.Add: - return AddPatchOperation.CreateFromJson(operation); - case Operation.Replace: - return ReplacePatchOperation.CreateFromJson(operation); - case Operation.Test: - return TestPatchOperation.CreateFromJson(operation); - case Operation.Remove: - return RemovePatchOperation.CreateFromJson(operation); - default: - throw new PatchOperationFailedException(PatchResources.MoveCopyNotImplemented()); - } - } - - throw new VssPropertyValidationException("Operation", PatchResources.InvalidOperation()); - } - - /// - /// Validates the path for the operation. - /// - protected static void ValidatePath(JsonPatchOperation operation) - { - // Path cannot be null, but it can be empty. - if (operation.Path == null) - { - throw new VssPropertyValidationException("Path", PatchResources.PathCannotBeNull()); - } - - // If it is not empty and does not start with /, this is an error per RFC. - if (!operation.Path.StartsWith(PathSeparator) && !string.IsNullOrEmpty(operation.Path)) - { - throw new VssPropertyValidationException("Path", PatchResources.PathInvalidStartValue()); - } - - // Ending in / is not valid.. - if (operation.Path.EndsWith(PathSeparator)) - { - throw new VssPropertyValidationException("Path", PatchResources.PathInvalidEndValue()); - } - - // Only add operations allow insert. - if (operation.Operation != Operation.Add) - { - if (operation.Path.EndsWith(EndOfIndex)) - { - throw new VssPropertyValidationException("Path", PatchResources.InsertNotSupported(operation.Operation)); - } - } - } - - /// - /// Validates the type for the operation. - /// - protected static void ValidateType(JsonPatchOperation operation) - { - ValidateAndGetType(operation); - } - - /// - /// Validates and returns the type for the operation. - /// - /// - /// - protected static Type ValidateAndGetType(JsonPatchOperation operation) - { - var type = GetType(typeof(TModel), operation.Path); - if (type == null) - { - throw new VssPropertyValidationException("Path", PatchResources.UnableToEvaluatePath(operation.Path)); - } - - return type; - } - - /// - /// Validates the path evaluates to a property on the model, and - /// returns the strongly typed value for the model. - /// - protected static object ValidateAndGetValue(JsonPatchOperation operation) - { - var type = ValidateAndGetType(operation); - - object value; - if (operation.Value == null) - { - value = null; - } - else - { - value = DeserializeValue(type, operation.Value); - } - - return value; - } - - /// - /// Gets The type of the field the path maps to. - /// - /// The type of the parent object. - /// The path to evaluate. - /// The type of the field that path maps to. - private static Type GetType(Type type, string path) - { - return GetType(type, SplitPath(path)); - } - - /// - /// Gets The type of the field the path maps to. - /// - /// The type of the parent object. - /// The path enumeration to evaluate. - /// The type of the field that path maps to. - private static Type GetType(Type type, IEnumerable path) - { - var current = path.First(); - Type currentType = null; - - // The start of the path should always be an empty string after splitting. - if (string.IsNullOrEmpty(current)) - { - currentType = type; - } - else if (type.IsList()) - { - currentType = type.GenericTypeArguments[0]; - } - else if (type.IsDictionary()) - { - currentType = type.GenericTypeArguments[1]; - } - else - { - currentType = type.GetMemberType(current); - } - - // Couldn't map the type, return null and let consumer handle. - if (currentType == null) - { - return null; - } - // The end of the list, this must be the type we're looking for. - else if (path.Count() == 1) - { - return currentType; - } - else - { - return GetType(currentType, path.Skip(1)); - } - } - - /// - /// Deserializes the json value. - /// - /// - /// The json formatted value. - /// The strongly typed (best effort) value. - private static object DeserializeValue(Type type, object jsonValue) - { - object value = null; - if (jsonValue is JToken) - { - try - { - value = ((JToken)jsonValue).ToObject(type, serializer); - } - catch (JsonException ex) - { - throw new VssPropertyValidationException("Value", PatchResources.InvalidValue(jsonValue, type), ex); - } - } - else - { - // Not a JToken, so it must be a primitive type. Will - // attempt to convert to the requested type. - if (type.IsAssignableOrConvertibleFrom(jsonValue)) - { - value = ConvertUtility.ChangeType(jsonValue, type); - } - else - { - Guid guidValue; - if (Guid.TryParse((string)jsonValue, out guidValue)) - { - value = guidValue; - } - else - { - throw new VssPropertyValidationException("Value", PatchResources.InvalidValue(jsonValue, type)); - } - } - } - - return value; - } - - /// - /// Converts the string path into the evaluatable path. - /// - private static IEnumerable SplitPath(string path) - { - return path.Split(new[] { PathSeparator }, StringSplitOptions.None); - } - - /// - /// Evaluates the path on the target and applies an action to the result. - /// - /// The target object to apply the operation to. - /// The action to apply to the result of the evaluation. - protected void Apply(object target, Action actionToApply) - { - this.Apply(target, this.EvaluatedPath, actionToApply); - } - - /// - /// Evaluates the path on the target and applies an action to the result. - /// - /// The target object to apply the operation to. - /// The path to evaluate. - /// The action to apply to the result of the evaluation. - private void Apply(object target, IEnumerable path, Action actionToApply) - { - var current = path.First(); - var type = target.GetType(); - - // We're at the end, time to apply the action. - if (path.Count() == 1) - { - if (PatchOperationApplying != null) - { - PatchOperationApplying(this, new PatchOperationApplyingEventArgs(this.EvaluatedPath, this.Operation)); - } - - actionToApply(type, target, current); - - if (PatchOperationApplied != null) - { - PatchOperationApplied(this, new PatchOperationAppliedEventArgs(this.EvaluatedPath, this.Operation)); - } - } - else - { - object newTarget = null; - - // The start of the path should always be an empty string after splitting. - // We just assign target to new target and move down the path. - if (string.IsNullOrEmpty(current)) - { - newTarget = target; - } - // If the next level is a dictionary, we want to get object at the key. - else if (type.IsDictionary()) - { - var dictionary = ((IDictionary)target); - if (dictionary.Contains(current)) - { - newTarget = dictionary[current]; - } - } - else if (type.IsList()) - { - var list = (IList)target; - int index; - if (int.TryParse(current, out index) && - list.Count > index) - { - newTarget = ((IList)target)[index]; - } - } - else - { - newTarget = type.GetMemberValue(current, target); - } - - if (newTarget == null) - { - // An extra layer of protection, since this should never happen because the earlier call to GetType would have failed. - throw new PatchOperationFailedException(PatchResources.TargetCannotBeNull()); - } - - this.Apply(newTarget, path.Skip(1), actionToApply); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperationAppliedEventArgs.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperationAppliedEventArgs.cs deleted file mode 100644 index b647e7ad2..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperationAppliedEventArgs.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Event args for the applied patch operation. - /// - public class PatchOperationAppliedEventArgs - { - public PatchOperationAppliedEventArgs(IEnumerable path, Operation operation) - { - this.Path = path; - this.Operation = operation; - } - - /// - /// The current path. - /// - public IEnumerable Path { get; private set; } - - /// - /// The operation being applied. - /// - public Operation Operation { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperationApplyingEventArgs.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperationApplyingEventArgs.cs deleted file mode 100644 index 584bf8218..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/PatchOperationApplyingEventArgs.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Event args for the applying patch operation. - /// - public class PatchOperationApplyingEventArgs - { - public PatchOperationApplyingEventArgs(IEnumerable path, Operation operation) - { - this.Path = path; - this.Operation = operation; - } - - /// - /// The current path. - /// - public IEnumerable Path { get; private set; } - - /// - /// The operation about to be applied. - /// - public Operation Operation { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/RemovePatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/RemovePatchOperation.cs deleted file mode 100644 index 051613176..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/RemovePatchOperation.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System.Collections; -using System.ComponentModel; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Patch.Json; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Represents the JSON Patch Remove operation. - /// - /// The model the patch operation applies to. - public class RemovePatchOperation : PatchOperation - { - public RemovePatchOperation() - { - this.Operation = Operation.Remove; - } - - public RemovePatchOperation(string path) : this() - { - this.Path = path; - } - - /// - /// Creates the strongly typed PatchOperation and validates the operation. - /// - /// The simple json patch operation model. - /// A valid and strongly typed PatchOperation. - [EditorBrowsable(EditorBrowsableState.Never)] - public static new PatchOperation CreateFromJson(JsonPatchOperation operation) - { - ValidatePath(operation); - ValidateType(operation); - - if (operation.Value != null) - { - throw new VssPropertyValidationException("Value", PatchResources.ValueNotNull()); - } - - return new RemovePatchOperation(operation.Path); - } - - /// - /// Applies the Remove patch operation to the target - /// - /// The object to apply the operation to. - public override void Apply(TModel target) - { - this.Apply( - target, - (type, parent, current) => - { - if (type.IsList()) - { - var list = (IList)parent; - int index; - if (int.TryParse(current, out index) && - list.Count > index) - { - list.RemoveAt(index); - } - else - { - // We can't remove outside the rangeof the list. - throw new PatchOperationFailedException(PatchResources.IndexOutOfRange(this.Path)); - } - } - else if (type.IsDictionary()) - { - ((IDictionary)parent).Remove(current); - } - else - { - type.SetMemberValue(current, parent, this.Value); - } - }); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/ReplacePatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/ReplacePatchOperation.cs deleted file mode 100644 index dda4e91b1..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/ReplacePatchOperation.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System.Collections; -using System.ComponentModel; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Patch.Json; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Represents the JSON Patch Replace operation. - /// - /// The model the patch operation applies to. - public class ReplacePatchOperation : PatchOperation - { - public ReplacePatchOperation() - { - this.Operation = Operation.Replace; - } - - public ReplacePatchOperation(string path, object value): this() - { - this.Path = path; - this.Value = value; - } - - /// - /// Creates the strongly typed PatchOperation and validates the operation. - /// - /// The simple json patch operation model. - /// A valid and strongly typed PatchOperation. - [EditorBrowsable(EditorBrowsableState.Never)] - public static new PatchOperation CreateFromJson(JsonPatchOperation operation) - { - ValidatePath(operation); - - var value = ValidateAndGetValue(operation); - if (value == null) - { - throw new VssPropertyValidationException("Value", PatchResources.ValueCannotBeNull()); - } - - return new ReplacePatchOperation(operation.Path, value); - } - - /// - /// Applies the Replace patch operation to the target - /// - /// The object to apply the operation to. - public override void Apply(TModel target) - { - this.Apply( - target, - (type, parent, current) => - { - if (type.IsList()) - { - var list = (IList)parent; - int index; - if (int.TryParse(current, out index) && - list.Count > index) - { - list[index] = this.Value; - } - else - { - throw new PatchOperationFailedException(PatchResources.CannotReplaceNonExistantValue(this.Path)); - } - } - else if (type.IsDictionary()) - { - var dictionary = (IDictionary)parent; - if (!dictionary.Contains(current)) - { - throw new InvalidPatchFieldNameException(PatchResources.InvalidFieldName(current)); - } - - dictionary[current] = this.Value; - } - else - { - if (type.GetMemberValue(current, parent) == null) - { - throw new PatchOperationFailedException(PatchResources.CannotReplaceNonExistantValue(this.Path)); - } - - type.SetMemberValue(current, parent, this.Value); - } - }); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Patch/TestPatchOperation.cs b/src/Sdk/WebApi/WebApi/Contracts/Patch/TestPatchOperation.cs deleted file mode 100644 index 832ccf8ef..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Patch/TestPatchOperation.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System.Collections; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Patch.Json; - -namespace GitHub.Services.WebApi.Patch -{ - /// - /// Represents the JSON Patch Test operation. - /// - /// The model the patch operation applies to. - public class TestPatchOperation : PatchOperation - { - public TestPatchOperation() - { - this.Operation = Operation.Test; - } - - public TestPatchOperation(string path, object value): this() - { - this.Path = path; - this.Value = value; - } - - /// - /// Creates the strongly typed PatchOperation and validates the operation. - /// - /// The simple json patch operation model. - /// A valid and strongly typed PatchOperation. - public static new PatchOperation CreateFromJson(JsonPatchOperation operation) - { - ValidatePath(operation); - - return new TestPatchOperation(operation.Path, ValidateAndGetValue(operation)); - } - - /// - /// Applies the Test patch operation to the target - /// - /// The object to apply the operation to. - public override void Apply(TModel target) - { - this.Apply( - target, - (type, parent, current) => - { - object memberValue = null; - if (type.IsList()) - { - var list = (IList)parent; - int index; - if (int.TryParse(current, out index) && - list.Count > index) - { - memberValue = list[index]; - } - else - { - // We can't insert beyond the length of the list. - throw new PatchOperationFailedException(PatchResources.IndexOutOfRange(this.Path)); - } - } - else if (type.IsDictionary()) - { - var fieldDictionary = ((IDictionary)parent); - - if (!fieldDictionary.Contains(current)) - { - throw new InvalidPatchFieldNameException(PatchResources.InvalidFieldName(current)); - } - memberValue = fieldDictionary[current]; - } - else - { - memberValue = type.GetMemberValue(current, parent); - } - - var success = false; - if (memberValue != null) - { - if (memberValue is IList) - { - // TODO: Implement - throw new PatchOperationFailedException(PatchResources.TestNotImplementedForList()); - } - else if (memberValue is IDictionary) - { - // TODO: Implement - throw new PatchOperationFailedException(PatchResources.TestNotImplementedForDictionary()); - } - else if (memberValue.GetType().IsAssignableOrConvertibleFrom(this.Value)) - { - // We convert the objects since we need the values unboxed. - var convertedMemberValue = ConvertUtility.ChangeType(memberValue, memberValue.GetType()); - var convertedValue = ConvertUtility.ChangeType(this.Value, memberValue.GetType()); - - success = convertedMemberValue.Equals(convertedValue); - } - else - { - success = memberValue.Equals(this.Value); - } - } - else - { - success = object.Equals(memberValue, this.Value); - } - - if (!success) - { - throw new TestPatchOperationFailedException(PatchResources.TestFailed(this.Path, memberValue, this.Value)); - } - }); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributeDescriptor.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributeDescriptor.cs deleted file mode 100644 index 62c63b818..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributeDescriptor.cs +++ /dev/null @@ -1,139 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - /// - /// Identifies an attribute with a name and a container. - /// - public class AttributeDescriptor : IComparable, ICloneable - { - /// - /// Constructor - /// - public AttributeDescriptor(string containerName, string attributeName) - { - //Validation in setters... - AttributeName = attributeName; - ContainerName = containerName; - } - - /// - /// The name of the attribute. - /// - [DataMember(IsRequired = true, EmitDefaultValue = false)] - public string AttributeName - { - get - { - return m_attributeName; - } - set - { - ProfileArgumentValidation.ValidateAttributeName(value); - m_attributeName = value; - } - } - - /// - /// The container the attribute resides in. - /// - [DataMember(IsRequired = true, EmitDefaultValue = false)] - public string ContainerName - { - get - { - return m_containerName; - } - set - { - ProfileArgumentValidation.ValidateContainerName(value); - m_containerName = value; - } - } - - private string m_attributeName; - private string m_containerName; - - public int CompareTo(AttributeDescriptor obj) - { - if (this == obj) return 0; - if (obj == null) return 1; - - int retValue; - if ((retValue = VssStringComparer.AttributesDescriptor.Compare(this.AttributeName, obj.AttributeName)) != 0) - { - return retValue; - } - - return VssStringComparer.AttributesDescriptor.Compare(this.ContainerName, obj.ContainerName); - } - - public override bool Equals(object obj) - { - if (obj == null || GetType() != obj.GetType()) - { - return false; - } - - return CompareTo((AttributeDescriptor) obj) == 0; - } - - public override int GetHashCode() - { - return this.ContainerName.GetHashCode() + this.AttributeName.GetHashCode(); - } - - public object Clone() - { - return new AttributeDescriptor(ContainerName, AttributeName); - } - - public override string ToString() - { - return string.Concat(ContainerName,";",AttributeName); - } - } - - /// - /// Class used for comparing AttributeDescriptors - /// - public class AttributeDescriptorComparer : IComparer, IEqualityComparer - { - private AttributeDescriptorComparer() { } - - public int Compare(AttributeDescriptor x, AttributeDescriptor y) - { - if (x == y) return 0; - if (x == null && y != null) return -1; - if (x != null && y == null) return 1; - - return (x.CompareTo(y)); - } - - public bool Equals(AttributeDescriptor x, AttributeDescriptor y) - { - return Compare(x, y) == 0; - } - - public int GetHashCode(AttributeDescriptor obj) - { - return obj.GetHashCode(); - } - - public static AttributeDescriptorComparer Instance - { - get - { - return s_instance; - } - } - - private static AttributeDescriptorComparer s_instance = new AttributeDescriptorComparer(); - } - - -} - diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributesContainer.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributesContainer.cs deleted file mode 100644 index 07c03beab..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributesContainer.cs +++ /dev/null @@ -1,65 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - /// - /// Stores a set of named profile attributes. - /// - [DataContract] - public class AttributesContainer : IVersioned, ICloneable - { - public AttributesContainer(string containerName) : this() - { - ContainerName = containerName; - } - - public AttributesContainer() - { - Attributes = new Dictionary(VssStringComparer.AttributesDescriptor); - } - - /// - /// The name of the container. - /// - [DataMember(IsRequired = true, EmitDefaultValue = false)] - public string ContainerName { - get - { - return m_containerName; - } - set - { - ProfileArgumentValidation.ValidateContainerName(value); - m_containerName = value; - } - } - - public object Clone() - { - AttributesContainer newContainer = (AttributesContainer)MemberwiseClone(); - - // Deep copy of attributes dictionary - newContainer.Attributes = Attributes != null ? Attributes.ToDictionary(x => x.Key, x => (ProfileAttribute)x.Value.Clone()) : null; - - return newContainer; - } - - /// - /// The attributes stored by the container. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public IDictionary Attributes { get; set; } - - /// - /// The maximum revision number of any attribute within the container. - /// - [DataMember(IsRequired = true, EmitDefaultValue = false)] - public int Revision { get; set; } - - private string m_containerName; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributesQueryContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributesQueryContext.cs deleted file mode 100644 index 94db2400a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/AttributesQueryContext.cs +++ /dev/null @@ -1,135 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - public class AttributesQueryContext : ICloneable - { - public AttributesQueryContext( - AttributesScope scope, - DateTimeOffset? modifiedSince = null, - int? modifiedAfterRevision = null, - CoreProfileAttributes? coreAttributes = null, - string containerName = null) - { - if (scope.HasFlag(~(AttributesScope.Application | AttributesScope.Core)) - || (!scope.HasFlag(AttributesScope.Application) && !scope.HasFlag(AttributesScope.Core))) - { - throw new ArgumentException(string.Format("The scope '{0}' is not supported for this operation.", scope)); - } - - Scope = scope; - ModifiedSince = modifiedSince; - ModifiedAfterRevision = modifiedAfterRevision; - - if (scope.HasFlag(AttributesScope.Application)) - { - ProfileArgumentValidation.ValidateApplicationContainerName(containerName); - ContainerName = containerName; - } - else - { - ContainerName = null; - } - - if (scope.HasFlag(AttributesScope.Core)) - { - CoreAttributes = coreAttributes ?? CoreProfileAttributes.All; - } - else - { - CoreAttributes = null; - } - } - - public AttributesQueryContext(AttributesScope scope, string containerName) - : this(scope, null, null, CoreProfileAttributes.All, containerName) - { - } - - /// - /// Deprecated constructor. The operation to 'get attributes since a certain point in time' is now deprecated. - /// > - public AttributesQueryContext(AttributesScope scope, DateTimeOffset modifiedSince, string containerName = null) - : this(scope, modifiedSince, null, CoreProfileAttributes.All, containerName) - { - } - - public AttributesQueryContext(AttributesScope scope, int modifiedAfterRevision, string containerName = null) - : this(scope, null, modifiedAfterRevision, CoreProfileAttributes.All, containerName) - { - } - - [DataMember(IsRequired = true)] - public AttributesScope Scope { get; private set; } - - [DataMember] - public string ContainerName { get; private set; } - - [DataMember] - public DateTimeOffset? ModifiedSince { get; private set; } - - [DataMember] - public int? ModifiedAfterRevision { get; private set; } - - [DataMember] - public CoreProfileAttributes? CoreAttributes { get; private set; } - - public override bool Equals(object obj) - { - if (obj == null || GetType() != obj.GetType()) - { - return false; - } - - var other = obj as AttributesQueryContext; - - return this.Equals(other); - } - - public bool Equals(AttributesQueryContext other) - { - return (Scope == other.Scope && - VssStringComparer.AttributesDescriptor.Equals(ContainerName, other.ContainerName) && - ModifiedSince == other.ModifiedSince && - ModifiedAfterRevision == other.ModifiedAfterRevision); - } - - public override int GetHashCode() - { - int hashCode = Scope.GetHashCode(); - hashCode = (hashCode * 499) ^ (ContainerName != null ? ContainerName.ToLowerInvariant().GetHashCode() : 0); - hashCode = (hashCode * 499) ^ (ModifiedSince != null ? ModifiedSince.GetHashCode() : 0); - hashCode = (hashCode * 499) ^ (ModifiedAfterRevision != null ? ModifiedAfterRevision.GetHashCode() : 0); - hashCode = (hashCode * 499) ^ (CoreAttributes != null ? CoreAttributes.GetHashCode() : 0); - - return hashCode; - } - - public object Clone() - { - return MemberwiseClone(); - } - } - - /// - /// Used to specify the scope of a set of attributes. - /// - /// - /// A profile attribute is either a core attribute or an attribute beloging to some application container. - /// A core attribute belongs to scope AttributesScope.Core. - /// An attribute stored under some application container belongs to scope AttributesScope.Application. - /// An attribute always belongs to scope AttributesScope.Core | AttributesScope.Application. - /// - [DataContract, Flags] - public enum AttributesScope - { - [EnumMember] - Core = 0x1, - - [EnumMember] - Application = 0x2, - } - -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/Avatar.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/Avatar.cs deleted file mode 100644 index b38f1d9f6..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/Avatar.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - [DataContract] - public class Avatar : ITimeStamped, ICloneable - { - [DataMember] - public byte[] Value { get; set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTimeOffset TimeStamp { get; set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public AvatarSize Size { get; internal set; } - - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public bool? IsAutoGenerated { get; internal set; } - - public object Clone() - { - var clone = new Avatar() - { - Size = this.Size, - TimeStamp = this.TimeStamp, - IsAutoGenerated = this.IsAutoGenerated - }; - if (Value != null) - { - clone.Value = new byte[Value.Length]; - Buffer.BlockCopy(Value, 0, clone.Value, 0, Value.Length); - } - return clone; - } - } - - /// - /// Small = 34 x 34 pixels; Medium = 44 x 44 pixels; Large = 220 x 220 pixels - /// - [DataContract] - public enum AvatarSize - { - Small, - Medium, - Large, - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/CoreProfileAttribute.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/CoreProfileAttribute.cs deleted file mode 100644 index 2fcbcba44..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/CoreProfileAttribute.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - /// - /// A profile attribute which always has a value for each profile. - /// - [DataContract] - public class CoreProfileAttribute : ProfileAttributeBase - { - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/ITimeStamped.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/ITimeStamped.cs deleted file mode 100644 index dd3eb87ad..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/ITimeStamped.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - public interface ITimeStamped - { - [DataMember(IsRequired = false, EmitDefaultValue = false)] - DateTimeOffset TimeStamp { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/IVersioned.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/IVersioned.cs deleted file mode 100644 index cb622d5ec..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/IVersioned.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - public interface IVersioned - { - [DataMember(IsRequired = false, EmitDefaultValue = false)] - int Revision { get; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/Profile.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/Profile.cs deleted file mode 100644 index 7ba1e71a5..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/Profile.cs +++ /dev/null @@ -1,234 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - /// - /// A user profile. - /// - [DataContract] - public class Profile : ITimeStamped, IVersioned, ICloneable - { - public Profile() - { - CoreAttributes = new Dictionary(VssStringComparer.AttributesDescriptor); - } - - public string DisplayName - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.DisplayName, null); } - set { SetAttributeInCoreContainer(CoreAttributeNames.DisplayName, value); } - } - - public string PublicAlias - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.PublicAlias, null); } - set { SetAttributeInCoreContainer(CoreAttributeNames.PublicAlias, value); } - } - - public string CountryName - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.CountryName, null); } - set { SetAttributeInCoreContainer(CoreAttributeNames.CountryName, value); } - } - - public string EmailAddress - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.EmailAddress, null); } - set { SetAttributeInCoreContainer(CoreAttributeNames.EmailAddress, value); } - } - - public string UnconfirmedEmailAddress - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.UnconfirmedEmailAddress, null); } - set { SetAttributeInCoreContainer(CoreAttributeNames.UnconfirmedEmailAddress, value); } - } - - public DateTimeOffset CreatedDateTime - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.DateCreated, default(DateTimeOffset)); } - set { SetAttributeInCoreContainer(CoreAttributeNames.DateCreated, value); } - } - - public Avatar Avatar - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.Avatar, null); } - set { SetAttributeInCoreContainer(CoreAttributeNames.Avatar, value); } - } - - /// - /// The attributes of this profile. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public AttributesContainer ApplicationContainer { get; set; } - - /// - /// The core attributes of this profile. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - internal IDictionary CoreAttributes { get; set; } - - /// - /// The maximum revision number of any attribute. - /// - [DataMember(IsRequired = true, EmitDefaultValue = false)] - public int CoreRevision { get; set; } - - /// - /// The time at which this profile was last changed. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTimeOffset TimeStamp { get; set; } - - /// - /// The unique identifier of the profile. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public Guid Id { get; internal set; } - - /// - /// The maximum revision number of any attribute. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public int Revision { get; set; } - - /// - /// The current state of the profile. - /// - [DataMember(IsRequired = false)] - public ProfileState ProfileState { get; set; } - - public int TermsOfServiceVersion - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.TermsOfServiceVersion, 0); } - set { SetAttributeInCoreContainer(CoreAttributeNames.TermsOfServiceVersion, value); } - } - - public DateTimeOffset TermsOfServiceAcceptDate - { - get { return GetAttributeFromCoreContainer(CoreAttributeNames.TermsOfServiceAcceptDate, default(DateTimeOffset)); } - set { SetAttributeInCoreContainer(CoreAttributeNames.TermsOfServiceAcceptDate, value); } - } - - public bool? ContactWithOffers - { - get - { - CoreProfileAttribute attribute; - CoreAttributes.TryGetValue(CoreAttributeNames.ContactWithOffers, out attribute); - if (attribute != null && attribute.Value != null && attribute.Value is bool) - { - return (bool?)attribute.Value; - } - return null; - } - set { SetAttributeInCoreContainer(CoreAttributeNames.ContactWithOffers, value); } - } - - private T GetAttributeFromCoreContainer(string attributeName, T defaultValue) - { - CoreProfileAttribute attribute; - CoreAttributes.TryGetValue(attributeName, out attribute); - - if (attribute != null && attribute.Value != null && attribute.Value.GetType() == typeof(T)) - { - return (T)attribute.Value; - } - return defaultValue; - } - - private void SetAttributeInCoreContainer(string attributeName, object value) - { - CoreProfileAttribute attribute; - if (CoreAttributes.TryGetValue(attributeName, out attribute)) - { - attribute.Value = value; - } - else - { - CoreAttributes.Add(attributeName, new CoreProfileAttribute() - { - Descriptor = new AttributeDescriptor(CoreContainerName, attributeName), - Value = value, - }); - } - } - - public CoreProfileAttribute GetCoreAttribute(string attributeName) - { - CoreProfileAttribute attribute; - CoreAttributes.TryGetValue(attributeName, out attribute); - if (attribute == null) - { - return null; - } - return (CoreProfileAttribute)attribute.Clone(); - } - - public object Clone() - { - Profile newProfile = MemberwiseClone() as Profile; - - // Since core attributes are cloned on read, we can get away with a shallow copy - newProfile.CoreAttributes = CoreAttributes != null ? CoreAttributes.ToDictionary(x => x.Key, x => (CoreProfileAttribute) x.Value.Clone()) : null; - newProfile.ApplicationContainer = ApplicationContainer != null ? (AttributesContainer)ApplicationContainer.Clone() : null; - - return newProfile; - } - - internal const string CoreContainerName = "Core"; - - internal class CoreAttributeNames - { - internal const string DisplayName = "DisplayName"; - internal const string PublicAlias = "PublicAlias"; - internal const string EmailAddress = "EmailAddress"; - internal const string DefaultEmailAddress = "DefaultEmailAddress"; - internal const string UnconfirmedEmailAddress = "UnconfirmedEmailAddress"; - internal const string CountryName = "CountryName"; - internal const string Avatar = "Avatar"; - internal const string TermsOfServiceVersion = "TermsOfServiceVersion"; - internal const string TermsOfServiceAcceptDate = "TermsOfServiceAcceptDate"; - internal const string ContactWithOffers = "ContactWithOffers"; - internal const string DateCreated = "DateCreated"; - - internal static readonly List AttributeNameList = new List() - { - DisplayName, - PublicAlias, - EmailAddress, - UnconfirmedEmailAddress, - CountryName, - Avatar, - TermsOfServiceVersion, - TermsOfServiceAcceptDate, - ContactWithOffers, - DateCreated - }; - } - } - - /// - /// The state of a profile. - /// - public enum ProfileState - { - /// - /// The profile is in use. - /// - Custom = 0, - - /// - /// The profile is in use, but can only be read. - /// - CustomReadOnly = 1, - - /// - /// The profile may only be read. - /// - ReadOnly = 2 - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileAttribute.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileAttribute.cs deleted file mode 100644 index b62aac92a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileAttribute.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - /// - /// A named object associated with a profile. - /// - [DataContract] - public class ProfileAttribute : ProfileAttributeBase - { - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileAttributeBase.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileAttributeBase.cs deleted file mode 100644 index f667c3da5..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileAttributeBase.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - [DataContract] - public class ProfileAttributeBase : ITimeStamped, IVersioned, ICloneable - { - /// - /// The descriptor of the attribute. - /// - [DataMember] - public AttributeDescriptor Descriptor { get; set; } - - /// - /// The value of the attribute. - /// - [DataMember] - public T Value { get; set; } - - /// - /// The time the attribute was last changed. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public DateTimeOffset TimeStamp { get; set; } - - /// - /// The revision number of the attribute. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public int Revision { get; set; } - - public object Clone() - { - ProfileAttributeBase newProfileAttribute = (ProfileAttributeBase)MemberwiseClone(); - newProfileAttribute.Descriptor = Descriptor != null ? (AttributeDescriptor)Descriptor.Clone() : null; - newProfileAttribute.Value = Value is ICloneable ? (T)((ICloneable)Value).Clone() : Value; - return newProfileAttribute; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileQueryContext.cs b/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileQueryContext.cs deleted file mode 100644 index 69daf560f..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Profile/ProfileQueryContext.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.Profile -{ - public class ProfileQueryContext - { - public ProfileQueryContext(AttributesScope scope, string containerName = null) - : this(scope, CoreProfileAttributes.All, containerName) - { - } - - public ProfileQueryContext(AttributesScope scope, CoreProfileAttributes coreAttributes, string containerName = null) - { - ContainerScope = scope; - CoreAttributes = coreAttributes; - switch (scope) - { - case AttributesScope.Core: - ContainerName = null; - break; - case AttributesScope.Core | AttributesScope.Application: - ProfileArgumentValidation.ValidateApplicationContainerName(containerName); - ContainerName = containerName; - break; - default: - throw new ArgumentException(string.Format("The scope '{0}' is not supported for this operation.", scope)); - } - } - - [DataMember(IsRequired = true)] - public AttributesScope ContainerScope { get; private set; } - - [DataMember] - public string ContainerName { get; private set; } - - [DataMember] - public CoreProfileAttributes CoreAttributes { get; private set; } - } - - [Flags] - public enum CoreProfileAttributes - { - Minimal = 0x0000, // Does not contain email, avatar, display name, or marketing preferences - Email = 0x0001, - Avatar = 0x0002, - DisplayName = 0x0004, - ContactWithOffers = 0x0008, - All = 0xFFFF, - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/PropertiesCollection.cs b/src/Sdk/WebApi/WebApi/Contracts/PropertiesCollection.cs deleted file mode 100644 index 5b7748df4..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/PropertiesCollection.cs +++ /dev/null @@ -1,462 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.Common.Internal; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi -{ - //extended properties are serialized with many core types, - //so a single contract to deal with them - //the server side TeamFoundationPropertiesService stores five types in their native format - //: Byte[], Int32, Double, DateType and String. - //JSON.NET deals correctly with Double, DateType and String, but can't discern the proper - //type of Byte[] and Int32 on deserization if deserializing into Object. Byte[] gets serialized as a - //Base64 encoded string, and stays that way. All integers get serialized as Int64, and stay that way - //on deserialization. Adding ItemTypeNameHandling=TypeNameHandling.All fixed Byte[] but not Int32, it turns - //out that they only primitive type that gets the name is byte[]... - //So we implemented the PropertiesCollectionItemConverter to preserve the type. - //PropertyValidation accepts the 5 types named above, plus any other Primitive type (any type with a TypeCode != TypeCode.Object) - //Except for DBNull. We also accept Guid. Types *not* in the set of five (including Guid) are stored as String in the DB - //and come back as that from the service. There is a special TryGetValue that can be used to try to convert the type - //from string back to the type it is supposed to be. - - - /// - /// The class represents a property bag as a collection of key-value pairs. Values of all primitive types (any type with a `TypeCode != TypeCode.Object`) - /// except for `DBNull` are accepted. Values of type Byte[], Int32, Double, DateType and String preserve their type, - /// other primitives are retuned as a String. Byte[] expected as base64 encoded string. - /// - [CollectionDataContract(Name = "Properties", ItemName = "Property", KeyName = "Key", ValueName = "Value")] - [JsonDictionary(ItemConverterType = typeof(PropertiesCollectionItemConverter))] - public sealed class PropertiesCollection : IDictionary, ICollection - { - public PropertiesCollection() - { - m_innerDictionary = new Dictionary(VssStringComparer.PropertyName); - this.ValidateNewValues = true; - } - - public PropertiesCollection(IDictionary source) : this(source, validateExisting: true) - { - } - - internal PropertiesCollection(IDictionary source, bool validateExisting) - { - if (validateExisting) - { - PropertyValidation.ValidateDictionary(source); - } - m_innerDictionary = new Dictionary(source, VssStringComparer.PropertyName); - this.ValidateNewValues = true; - } - - private Dictionary m_innerDictionary; - - //allow containers to turn off property validation - internal Boolean ValidateNewValues - { - get; - set; - } - - #region Public Properties - /// - /// The count of properties in the collection. - /// - public Int32 Count - { - get - { - return m_innerDictionary.Count; - } - } - - /// - /// Implements IDictionary<String, Object>.Item - /// - /// - /// - public Object this[String key] - { - get - { - return m_innerDictionary[key]; - } - set - { - if (this.ValidateNewValues) - { - PropertyValidation.ValidatePropertyName(key); - PropertyValidation.ValidatePropertyValue(key, value); - } - - m_innerDictionary[key] = value; - } - } - - /// - /// The set of keys in the collection. - /// - public Dictionary.KeyCollection Keys - { - get - { - return m_innerDictionary.Keys; - } - } - - /// - /// The set of values in the collection. - /// - public Dictionary.ValueCollection Values - { - get - { - return m_innerDictionary.Values; - } - } - #endregion - - #region Public Methods - /// - /// Implements IDictionary<String, Object>.Add - /// - /// - /// - public void Add(String key, Object value) - { - if (this.ValidateNewValues) - { - PropertyValidation.ValidatePropertyName(key); - PropertyValidation.ValidatePropertyValue(key, value); - } - - m_innerDictionary.Add(key, value); - } - - /// - /// Implements ICollection<KeyValuePair<String, Object>>.Clear() - /// - public void Clear() - { - m_innerDictionary.Clear(); - } - - /// - /// Implements IDictionary<String, Object>.ContainsKey() - /// - /// - /// - public Boolean ContainsKey(String key) - { - return m_innerDictionary.ContainsKey(key); - } - - /// - /// Implements IDictionary<String, Object>.ContainsValue() - /// - /// - /// - public Boolean ContainsValue(Object value) - { - return m_innerDictionary.ContainsValue(value); - } - - /// - /// Implements IDictionary<String, Object>.Remove() - /// - /// - /// - public Boolean Remove(String key) - { - return m_innerDictionary.Remove(key); - } - - public T GetValue(String key, T defaultValue) - { - T value; - if (!TryGetValue(key, out value)) - { - value = defaultValue; - } - return value; - } - - /// - /// Implements IDictionary<String, Object>.TryGetValue() - /// - /// - /// - /// - public Boolean TryGetValue(String key, out Object value) - { - return m_innerDictionary.TryGetValue(key, out value); - } - - public Boolean TryGetValue(String key, out T value) - { - return this.TryGetValidatedValue(key, out value); - } - - public override Boolean Equals(Object otherObj) - { - if (Object.ReferenceEquals(this, otherObj)) - { - return true; - } - - PropertiesCollection otherCollection = otherObj as PropertiesCollection; - if (otherCollection == null || Count != otherCollection.Count) - { - return false; - } - else - { - Object obj; - foreach (var key in Keys) - { - if (!otherCollection.TryGetValue(key, out obj) || !obj.Equals(this[key])) - { - return false; - } - } - return true; - } - } - - public override Int32 GetHashCode() - { - return base.GetHashCode(); - } - - #endregion - - #region ICollection explicit implementation - //We implement ICollection to get the SyncRoot - void ICollection.CopyTo(Array array, int index) - { - ((ICollection)m_innerDictionary).CopyTo(array, index); - } - - Boolean ICollection.IsSynchronized - { - get - { - return ((ICollection)m_innerDictionary).IsSynchronized; - } - } - - Object ICollection.SyncRoot - { - get - { - return ((ICollection)m_innerDictionary).SyncRoot; - } - } - #endregion - - #region ICollection explicit implementation - void ICollection>.Add(KeyValuePair keyValuePair) - { - if (this.ValidateNewValues) - { - PropertyValidation.ValidatePropertyName(keyValuePair.Key); - PropertyValidation.ValidatePropertyValue(keyValuePair.Key, keyValuePair.Value); - } - - ((ICollection>)m_innerDictionary).Add(keyValuePair); - } - - Boolean ICollection>.Contains(KeyValuePair keyValuePair) - { - return ((ICollection>)m_innerDictionary).Contains(keyValuePair); - } - - void ICollection>.CopyTo(KeyValuePair[] array, Int32 index) - { - ((ICollection>)m_innerDictionary).CopyTo(array, index); - } - - Boolean ICollection>.IsReadOnly - { - get - { - return false; - } - } - - Boolean ICollection>.Remove(KeyValuePair keyValuePair) - { - return ((ICollection>)m_innerDictionary).Remove(keyValuePair); - } - #endregion - - #region IDictionary explicit implementation - ICollection IDictionary.Keys - { - get - { - return ((IDictionary)m_innerDictionary).Keys; - } - } - - ICollection IDictionary.Values - { - get - { - return ((IDictionary)m_innerDictionary).Values; - } - } - #endregion - - #region IEnumerable> explicit implementation - IEnumerator> IEnumerable>.GetEnumerator() - { - return ((IEnumerable>)m_innerDictionary).GetEnumerator(); - } - #endregion - - #region IEnumerable implementation - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)m_innerDictionary).GetEnumerator(); - } - #endregion - - #region PropertiesCollectionItemConverter class - internal class PropertiesCollectionItemConverter : JsonConverter - { - public PropertiesCollectionItemConverter() { } - - private const string TypePropertyName = "$type"; - private const string ValuePropertyName = "$value"; - - /// - /// Writes the JSON representation of the object. - /// - /// The to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - Type valueType = value.GetType(); - - // We don't want to use the type name of the enum itself; instead we marshal - // it as a decimal number inside of a string - if (valueType.GetTypeInfo().IsEnum) - { - value = ((Enum)value).ToString("D"); - valueType = typeof(String); - } - - PropertyValidation.ValidatePropertyValue(WebApiResources.SerializingPhrase(), value); - - //write out as an object with type information - writer.WriteStartObject(); - writer.WritePropertyName(TypePropertyName); - - // Check that the Type we're claiming is safely deserializable - String typeName = valueType.FullName; - - if (!PropertyValidation.IsValidTypeString(typeName)) - { - throw new PropertyTypeNotSupportedException(TypePropertyName, valueType); - } - - writer.WriteValue(typeName); - writer.WritePropertyName(ValuePropertyName); - writer.WriteValue(value); - writer.WriteEndObject(); - } - - /// - /// Reads the JSON representation of the object. - /// - /// The to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// The object value. - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.StartObject) - { - JObject valueInfo = serializer.Deserialize(reader); - if (!valueInfo.TryGetValue(TypePropertyName, out JToken typeToken) || - !valueInfo.TryGetValue(ValuePropertyName, out JToken valueToken)) - { - // The following block is for compatability with old code behavior. - // The old code blindly took the first argument add treated it as the $type string, - // It blindly took the second argument and treated it as the $value object. - IEnumerator tokenEnumerator = valueInfo.Values().GetEnumerator(); - if (tokenEnumerator.MoveNext()) - { - typeToken = tokenEnumerator.Current; - if (tokenEnumerator.MoveNext()) - { - valueToken = tokenEnumerator.Current; - } - else - { - throw new InvalidOperationException(WebApiResources.DeserializationCorrupt()); - } - } - else - { - throw new InvalidOperationException(WebApiResources.DeserializationCorrupt()); - } - } - - string typeToCreate = typeToken.ToObject(); - - //make sure the string is a valid type, - //an arbitrary type string with nested generics could overflow the - //stack for a DOS. - if (!PropertyValidation.TryGetValidType(typeToCreate, out Type type)) - { - throw new InvalidOperationException(WebApiResources.DeserializationCorrupt()); - } - - //deserialize the type - return valueToken.ToObject(type); - } - else if (reader.TokenType == JsonToken.Boolean || - reader.TokenType == JsonToken.Bytes || - reader.TokenType == JsonToken.Date || - reader.TokenType == JsonToken.Float || - reader.TokenType == JsonToken.Integer || - reader.TokenType == JsonToken.String) - { - // Allow the JSON to simply specify "name": value syntax if type information is not necessary. - return serializer.Deserialize(reader); - } - else if (reader.TokenType == JsonToken.Null) - { - return null; - } - else - { - throw new InvalidOperationException(WebApiResources.DeserializationCorrupt()); - } - } - - /// - /// Determines whether this instance can convert the specified object type. - /// - /// Type of the object. - /// - /// true if this instance can convert the specified object type; otherwise, false. - /// - public override Boolean CanConvert(Type objectType) - { - return true; - } - } - #endregion - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/ReferenceLink/ReferenceLink.cs b/src/Sdk/WebApi/WebApi/Contracts/ReferenceLink/ReferenceLink.cs deleted file mode 100644 index 583efb56c..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/ReferenceLink/ReferenceLink.cs +++ /dev/null @@ -1,54 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - /// - /// The class to represent a REST reference link. - /// - /// RFC: http://tools.ietf.org/html/draft-kelly-json-hal-06 - /// - /// The RFC is not fully implemented, additional properties are allowed on the - /// reference link but as of yet we don't have a need for them. - /// - [DataContract] - public class ReferenceLink : ISecuredObject - { - public ReferenceLink() { } - - internal ReferenceLink(ISecuredObject securedObject) - { - m_securedObject = securedObject; - } - - [DataMember] - public string Href { get; set; } - - Guid ISecuredObject.NamespaceId - { - get - { - ArgumentUtility.CheckForNull(m_securedObject, nameof(m_securedObject)); - return m_securedObject.NamespaceId; - } - } - - int ISecuredObject.RequiredPermissions - { - get - { - ArgumentUtility.CheckForNull(m_securedObject, nameof(m_securedObject)); - return m_securedObject.RequiredPermissions; - } - } - - string ISecuredObject.GetToken() - { - ArgumentUtility.CheckForNull(m_securedObject, nameof(m_securedObject)); - return m_securedObject.GetToken(); - } - - private readonly ISecuredObject m_securedObject; - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/ReferenceLink/ReferenceLinks.cs b/src/Sdk/WebApi/WebApi/Contracts/ReferenceLink/ReferenceLinks.cs deleted file mode 100644 index 35d5d9be5..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/ReferenceLink/ReferenceLinks.cs +++ /dev/null @@ -1,304 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Xml; -using System.Xml.Schema; -using System.Xml.Serialization; -using GitHub.Services.Common; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi -{ - /// - /// The class to represent a collection of REST reference links. - /// - [XmlRoot("ReferenceLinks")] - [JsonConverter(typeof(ReferenceLinksConverter))] - public class ReferenceLinks : ICloneable, IXmlSerializable - { - /// - /// The internal representation of the reference links. - /// - private IDictionary referenceLinks = new Dictionary(); - - /// - /// Helper method to easily add a reference link to the dictionary. - /// If the specified name has already been added, the subsequent calls - /// to AddLink will create a list of reference links for the name. - /// - /// The name of the reference link. - /// The href the reference link refers to. - /// The implementation for securedObject. - [EditorBrowsable(EditorBrowsableState.Never)] - public void AddLink(string name, string href, ISecuredObject securedObject) - { - if (referenceLinks.ContainsKey(name)) - { - IList links; - if (referenceLinks[name] is ReferenceLink) - { - // promote to a list of links - links = new List(); - links.Add((ReferenceLink)referenceLinks[name]); - referenceLinks[name] = links; - } - else - { - links = (IList)referenceLinks[name]; - } - - links.Add(new ReferenceLink(securedObject) { Href = href }); - } - else - { - referenceLinks[name] = new ReferenceLink(securedObject) { Href = href }; - } - } - - /// - /// Helper method to easily add a reference link to the dictionary. - /// If the specified name has already been added, the subsequent calls - /// to AddLink will create a list of reference links for the name. - /// - /// The name of the reference link. - /// The href the reference link refers to. - public void AddLink(string name, string href) - { - AddLink(name, href, null); - } - - /// - /// Helper method to easily add a reference link to the dictionary if href is not null or empty value. - /// If the specified name has already been added, the subsequent calls to AddLink will create a list of reference links for the name. - /// - /// The name of the reference link. - /// The href the reference link refers to. - public void AddLinkIfIsNotEmpty(string name, string href) - { - if (!string.IsNullOrEmpty(href)) - { - AddLink(name, href, null); - } - } - - Object ICloneable.Clone() - { - return this.Clone(); - } - - /// - /// Creates a deep copy of the ReferenceLinks. - /// - /// A deep copy of the ReferenceLinks - public ReferenceLinks Clone() - { - ReferenceLinks linksCloned = new ReferenceLinks(); - this.CopyTo(linksCloned); - return linksCloned; - } - - /// - /// Copies the ReferenceLinks to another ReferenceLinks. - /// - /// - public void CopyTo(ReferenceLinks target) - { - CopyTo(target, null); - } - - /// - /// Copies the ReferenceLinks to another ReferenceLinks and secures using the specified object. - /// - /// - public void CopyTo(ReferenceLinks target, ISecuredObject securedObject) - { - ArgumentUtility.CheckForNull(target, nameof(target)); - - foreach (var link in this.Links) - { - if (link.Value is IList) - { - var hrefs = link.Value as IList; - if (hrefs != null) - { - foreach (var href in hrefs) - { - target.AddLink(link.Key, href.Href, securedObject); - } - } - } - else if (link.Value is ReferenceLink) - { - var href = link.Value as ReferenceLink; - if (href != null) - { - target.AddLink(link.Key, href.Href, securedObject); - } - } - } - } - - XmlSchema IXmlSerializable.GetSchema() - { - return null; - } - - void IXmlSerializable.ReadXml(XmlReader reader) - { - XmlSerializer keySerializer = new XmlSerializer(typeof(string)); - XmlSerializer valueSerializer = new XmlSerializer(typeof(List)); - - bool wasEmpty = reader.IsEmptyElement; - reader.Read(); - - if (wasEmpty) - { - return; - } - - while (reader.NodeType != XmlNodeType.EndElement) - { - reader.ReadStartElement("item"); - - reader.ReadStartElement("key"); - var key = (string)keySerializer.Deserialize(reader); - reader.ReadEndElement(); - - reader.ReadStartElement("value"); - var value = (List)valueSerializer.Deserialize(reader); - reader.ReadEndElement(); - - if (value.Count == 1) - { - referenceLinks.Add(key, value[0]); - } - else if (value.Count > 1) - { - referenceLinks.Add(key, value); - } - - reader.ReadEndElement(); - reader.MoveToContent(); - } - reader.ReadEndElement(); - } - - void IXmlSerializable.WriteXml(XmlWriter writer) - { - XmlSerializer keySerializer = new XmlSerializer(typeof(string)); - XmlSerializer valueSerializer = new XmlSerializer(typeof(List)); - - foreach (var item in this.referenceLinks) - { - writer.WriteStartElement("item"); - - writer.WriteStartElement("key"); - keySerializer.Serialize(writer, item.Key); - writer.WriteEndElement(); - - writer.WriteStartElement("value"); - var links = item.Value as List; - if (links == null) - { - links = new List() - { - (ReferenceLink)item.Value - }; - } - - valueSerializer.Serialize(writer, links); - writer.WriteEndElement(); - - writer.WriteEndElement(); - } - } - - /// - /// The readonly view of the links. Because Reference links are readonly, - /// we only want to expose them as read only. - /// - public IReadOnlyDictionary Links - { - get - { - return new ReadOnlyDictionary(referenceLinks); - } - } - - /// - /// The json converter to represent the reference links as a dictionary. - /// - private class ReferenceLinksConverter : VssSecureJsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(ReferenceLinks)); - } - - /// - /// Because ReferenceLinks is a dictionary of either a single - /// ReferenceLink or an array of ReferenceLinks, we need custom - /// deserialization to correctly rebuild the dictionary. - /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - var unresolvedLinks = serializer.Deserialize>(reader); - if (unresolvedLinks == null) - { - return null; - } - - var links = new Dictionary(); - foreach (var entry in unresolvedLinks) - { - if (String.IsNullOrEmpty(entry.Key)) - { - throw new JsonSerializationException(WebApiResources.InvalidReferenceLinkFormat()); - } - - JToken token = entry.Value as JToken; - if (token != null) - { - switch (token.Type) - { - case JTokenType.Array: - using (var tokenReader = token.CreateReader()) - { - links[entry.Key] = serializer.Deserialize>(tokenReader); - } - break; - - case JTokenType.Object: - using (var tokenReader = token.CreateReader()) - { - links[entry.Key] = serializer.Deserialize(tokenReader); - } - break; - - default: - throw new JsonSerializationException(WebApiResources.InvalidReferenceLinkFormat()); - } - } - else if (entry.Value is ReferenceLink || entry.Value is IList) - { - links[entry.Key] = entry.Value; - } - else - { - throw new JsonSerializationException(WebApiResources.InvalidReferenceLinkFormat()); - } - } - - return new ReferenceLinks { referenceLinks = links }; - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - base.WriteJson(writer, value, serializer); - serializer.Serialize(writer, ((ReferenceLinks)value).referenceLinks); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/SignedUrl/SignedUrl.cs b/src/Sdk/WebApi/WebApi/Contracts/SignedUrl/SignedUrl.cs deleted file mode 100644 index 1802e7fe2..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/SignedUrl/SignedUrl.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - /// - /// A signed url allowing limited-time anonymous access to private resources. - /// - [DataContract] - public class SignedUrl - { - [DataMember] - public string Url { get; set; } - - [DataMember] - public DateTime SignatureExpires { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Users/UpdateUserParameters.cs b/src/Sdk/WebApi/WebApi/Contracts/Users/UpdateUserParameters.cs deleted file mode 100644 index e74dfdd8a..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Users/UpdateUserParameters.cs +++ /dev/null @@ -1,181 +0,0 @@ -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using System; -using System.Runtime.Serialization; -using System.Linq; -using System.Globalization; - -namespace GitHub.Services.Users -{ - /// - /// Used for updating a user's data. - /// - [DataContract] - public class UpdateUserParameters - { - /// - /// Creates a new instance of an UpdateUserParameters object. - /// - public UpdateUserParameters() - { - this.Properties = new PropertiesCollection(); - } - - public UpdateUserParameters(UpdateUserParameters copy) - { - Descriptor = copy.Descriptor; - Properties = new PropertiesCollection(copy.Properties); - LastModified = copy.LastModified; - Revision = copy.Revision; - } - - /// - /// The user's unique identifier, and the primary means by which the user is referenced. - /// - [IgnoreDataMember] - public SubjectDescriptor Descriptor { get; set; } - - /// - /// The collection of properties to set. See "User" for valid fields. - /// - [DataMember(IsRequired = true, EmitDefaultValue = false)] - public PropertiesCollection Properties - { - get; private set; - } - - /// - /// The user's name, as displayed throughout the product. - /// - [IgnoreDataMember] - public String DisplayName - { - set { this.Properties[nameof(DisplayName)] = value; } - get { return this.Properties.GetValue(nameof(DisplayName), defaultValue: null); } - } - - /// - /// The user's preferred email address. - /// - [IgnoreDataMember] - public String Mail - { - set { this.Properties[nameof(Mail)] = value; } - get { return this.Properties.GetValue(nameof(Mail), defaultValue: null); } - } - - /// - /// The user's preferred email address which has not yet been confirmed. - /// - [IgnoreDataMember] - public String UnconfirmedMail - { - set { this.Properties[nameof(UnconfirmedMail)] = value; } - get { return this.Properties.GetValue(nameof(UnconfirmedMail), defaultValue: null); } - } - - /// - /// The user's country of residence or association. - /// - [IgnoreDataMember] - public String Country - { - set { this.Properties[nameof(Country)] = value; } - get { return this.Properties.GetValue(nameof(Country), defaultValue: null); } - } - - /// - /// The region in which the user resides or is associated. - /// - [IgnoreDataMember] - public String Region - { - set { this.Properties[nameof(Region)] = value; } - get { return this.Properties.GetValue(nameof(Region), defaultValue: null); } - } - - /// - /// A short blurb of "about me"-style text. - /// - [IgnoreDataMember] - public String Bio - { - set { this.Properties[nameof(Bio)] = value; } - get { return this.Properties.GetValue(nameof(Bio), defaultValue: null); } - } - - /// - /// A link to an external blog. - /// - [IgnoreDataMember] - public String Blog - { - set { this.Properties[nameof(Blog)] = value; } - get { return this.Properties.GetValue(nameof(Blog), defaultValue: null); } - } - - /// - /// The company at which the user is employed. - /// - [IgnoreDataMember] - public String Company - { - set { this.Properties[nameof(Company)] = value; } - get { return this.Properties.GetValue(nameof(Company), defaultValue: null); } - } - - /// - /// The date/time at which the user data was last modified. - /// - [IgnoreDataMember] - internal DateTimeOffset LastModified { get; set; } - - /// - /// The user data revision, for change tracking. - /// - [IgnoreDataMember] - internal Int32 Revision { get; set; } - - internal UpdateUserParameters Clone() - { - UpdateUserParameters clone = new UpdateUserParameters(); - - clone.Descriptor = this.Descriptor; - clone.Properties = new PropertiesCollection(this.Properties); - clone.Revision = this.Revision; - - return clone; - } - - internal virtual User ToUser() - { - User user = new User - { - Descriptor = this.Descriptor, - LastModified = this.LastModified, - Revision = this.Revision, - }; - - user.UpdateWith(this); - - return user; - } - - public override string ToString() - { - return String.Format( - CultureInfo.InvariantCulture, - @"UpdateUserParameters -[ -Descriptor: {0} -Revision: {1} -LastModified: {2} -{3} -]", - this.Descriptor, - this.Revision, - this.LastModified, - String.Join("\r\n", Properties.Select(kvp => $"{kvp.Key}:{kvp.Value}"))); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Contracts/Users/User.cs b/src/Sdk/WebApi/WebApi/Contracts/Users/User.cs deleted file mode 100644 index 0c529d456..000000000 --- a/src/Sdk/WebApi/WebApi/Contracts/Users/User.cs +++ /dev/null @@ -1,187 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Users -{ - [DataContract] - public class User - { - public User() - { - } - - public User(User copy) - { - Descriptor = copy.Descriptor; - UserName = copy.UserName; - DisplayName = copy.DisplayName; - Mail = copy.Mail; - UnconfirmedMail = copy.UnconfirmedMail; - Bio = copy.Bio; - Blog = copy.Blog; - Company = copy.Company; - Country = copy.Country; - DateCreated = copy.DateCreated; - Links = copy.Links; - LastModified = copy.LastModified; - Revision = copy.Revision; - State = copy.State; - } - - /// - /// The user's unique identifier, and the primary means by which the user is referenced. - /// - [DataMember(IsRequired = true)] - public SubjectDescriptor Descriptor { get; set; } - - /// - /// The unique name of the user. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String UserName { get; set; } - - /// - /// The user's name, as displayed throughout the product. - /// - [DataMember(IsRequired = false)] - public String DisplayName { get; set; } - - /// - /// The user's preferred email address. - /// - [DataMember(IsRequired = false)] - public String Mail { get; set; } - - /// - /// The user's preferred email address which has not yet been confirmed. - /// Do not use this as an email destination, instead prefer the - /// confirmed email address - /// - [DataMember(IsRequired = false)] - public String UnconfirmedMail { get; set; } - - /// - /// A short blurb of "about me"-style text. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Bio { get; set; } - - /// - /// A link to an external blog. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Blog { get; set; } - - /// - /// The company at which the user is employed. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public String Company { get; set; } - - /// - /// The user's country of residence or association. - /// - [DataMember(IsRequired = false)] - public String Country { get; set; } - - /// - /// The date the user was created in the system - /// - [DataMember(IsRequired = false)] - public DateTimeOffset DateCreated { get; set; } - - /// - /// A set of readonly links for obtaining more info about the user. - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public ReferenceLinks Links { get; internal set; } - - /// - /// The date/time at which the user data was last modified. - /// - [DataMember(IsRequired = false)] - public DateTimeOffset LastModified { get; internal set; } - - /// - /// The attribute's revision, for change tracking. - /// - [DataMember(IsRequired = false)] - public Int32 Revision { get; internal set; } - - /// - /// The status of the user - /// - [DataMember(IsRequired = false, EmitDefaultValue = false)] - public UserState State { get; internal set; } - - /// - /// Enumeration for the user status - /// - [DataContract] - public enum UserState - { - Wellformed=0, - PendingProfileCreation, - Deleted, - } - - public static implicit operator UpdateUserParameters(User user) - { - return new UpdateUserParameters - { - Descriptor = user.Descriptor, - DisplayName = user.DisplayName, - Mail = user.Mail, - UnconfirmedMail = user.UnconfirmedMail, - Country = user.Country, - Bio = user.Bio, - Blog = user.Blog, - Company = user.Company, - LastModified = user.LastModified, - Revision = user.Revision, - }; - } - - internal virtual void UpdateWith(UpdateUserParameters userParameters) - { - ArgumentUtility.CheckForNull(userParameters, nameof(userParameters)); - - foreach (String propertyName in userParameters.Properties.Keys) - { - String value = userParameters.Properties[propertyName] as String; - switch (propertyName) - { - case (nameof(DisplayName)): - DisplayName = value; - break; - - case (nameof(Mail)): - Mail = value; - break; - - case (nameof(UnconfirmedMail)): - UnconfirmedMail = value; - break; - - case (nameof(Country)): - Country = value; - break; - - case (nameof(Bio)): - Bio = value; - break; - - case (nameof(Blog)): - Blog = value; - break; - - case (nameof(Company)): - Company = value; - break; - } - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/CommonRestExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/CommonRestExceptions.cs deleted file mode 100644 index 351e9be7f..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/CommonRestExceptions.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi.Exceptions -{ - [Serializable] - [ExceptionMapping("0.0", "3.0", "MissingRequiredParameterException", "GitHub.Services.WebApi.Exceptions.MissingRequiredParameterException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class MissingRequiredParameterException : VssServiceException - { - public MissingRequiredParameterException() - { - } - - public MissingRequiredParameterException(string message) - : base(message) - { - } - - public MissingRequiredParameterException(string message, Exception innerException) - : base(message, innerException) - { - } - - public MissingRequiredParameterException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class MissingRequiredHeaderException : VssServiceException - { - public MissingRequiredHeaderException() - { - } - - public MissingRequiredHeaderException(string message) - : base(message) - { - } - - public MissingRequiredHeaderException(string message, Exception innerException) - : base(message, innerException) - { - } - - public MissingRequiredHeaderException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class MultipleHeaderValuesException : VssServiceException - { - public MultipleHeaderValuesException() - { - } - - public MultipleHeaderValuesException(string message) - : base(message) - { - } - - public MultipleHeaderValuesException(string message, Exception innerException) - : base(message, innerException) - { - } - - public MultipleHeaderValuesException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/FileContainerExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/FileContainerExceptions.cs deleted file mode 100644 index 9381ced29..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/FileContainerExceptions.cs +++ /dev/null @@ -1,360 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.FileContainer -{ - [Serializable] - [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] - [ExceptionMapping("0.0", "3.0", "FileContainerException", "GitHub.Services.FileContainer.FileContainerException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public abstract class FileContainerException : VssServiceException - { - public FileContainerException() - { - EventId = VssEventId.FileContainerBaseEventId; - } - - public FileContainerException(String message) - : base(message) - { - EventId = VssEventId.FileContainerBaseEventId; - } - - public FileContainerException(String message, Exception ex) - : base(message, ex) - { - EventId = VssEventId.FileContainerBaseEventId; - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ArtifactUriNotSupportedException", "GitHub.Services.FileContainer.ArtifactUriNotSupportedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ArtifactUriNotSupportedException : FileContainerException - { - public ArtifactUriNotSupportedException(Uri artifactUri) : - base(FileContainerResources.ArtifactUriNotSupportedException(artifactUri)) - { - } - - public ArtifactUriNotSupportedException(String message) : - base(message) - { - } - - public ArtifactUriNotSupportedException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerNotFoundException", "GitHub.Services.FileContainer.ContainerNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ContainerNotFoundException : FileContainerException - { - public ContainerNotFoundException() : - base() - { - } - - public ContainerNotFoundException(Int64 containerId) : - base(FileContainerResources.ContainerNotFoundException(containerId)) - { - } - - public ContainerNotFoundException(String message) : - base(message) - { - } - - public ContainerNotFoundException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemNotFoundException", "GitHub.Services.FileContainer.ContainerItemNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemNotFoundException : FileContainerException - { - public ContainerItemNotFoundException() : - base() - { - } - - public ContainerItemNotFoundException(Int64 containerId, String path) : - base(FileContainerResources.ContainerItemNotFoundException(path, containerId)) - { - } - - public ContainerItemNotFoundException(ContainerItemType itemType, String existingPath) - : base(FileContainerResources.ContainerItemDoesNotExist(existingPath, itemType)) - { - } - - public ContainerItemNotFoundException(String message) : - base(message) - { - } - - public ContainerItemNotFoundException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerWriteAccessDeniedException", "GitHub.Services.FileContainer.ContainerWriteAccessDeniedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ContainerWriteAccessDeniedException : FileContainerException - { - public ContainerWriteAccessDeniedException(String message) : - base(message) - { - } - - public ContainerWriteAccessDeniedException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemExistsException", "GitHub.Services.FileContainer.ContainerItemExistsException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemExistsException : FileContainerException - { - public ContainerItemExistsException(ContainerItemType itemType, String existingPath) - : base(FileContainerResources.ContainerItemWithDifferentTypeExists(itemType, existingPath)) - { - } - - public ContainerItemExistsException(String message) : - base(message) - { - } - - public ContainerItemExistsException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemCopyTargetChildOfSourceException", "GitHub.Services.FileContainer.ContainerItemCopyTargetChildOfSourceException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemCopyTargetChildOfSourceException : FileContainerException - { - public ContainerItemCopyTargetChildOfSourceException(String targetPath, String sourcePath) - : base(FileContainerResources.ContainerItemCopyTargetChildOfSource(targetPath, sourcePath)) - { - } - - public ContainerItemCopyTargetChildOfSourceException(String message) : - base(message) - { - } - - public ContainerItemCopyTargetChildOfSourceException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemCopySourcePendingUploadException", "GitHub.Services.FileContainer.ContainerItemCopySourcePendingUploadException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemCopySourcePendingUploadException : FileContainerException - { - public ContainerItemCopySourcePendingUploadException(String sourcePath) - : base(FileContainerResources.ContainerItemCopySourcePendingUpload(sourcePath)) - { - } - - public ContainerItemCopySourcePendingUploadException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemCopyDuplicateTargetsException", "GitHub.Services.FileContainer.ContainerItemCopyDuplicateTargetsException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemCopyDuplicateTargetsException : FileContainerException - { - public ContainerItemCopyDuplicateTargetsException(String targetPath) - : base(FileContainerResources.ContainerItemCopyDuplicateTargets(targetPath)) - { - } - - public ContainerItemCopyDuplicateTargetsException(String message, Exception ex) : - base(message, ex) - { - } -} - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "PendingUploadNotFoundException", "GitHub.Services.FileContainer.PendingUploadNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class PendingUploadNotFoundException : FileContainerException - { - public PendingUploadNotFoundException(Int32 uploadId) : - base(FileContainerResources.PendingUploadNotFoundException(uploadId)) - { - } - - public PendingUploadNotFoundException(String message) : - base(message) - { - } - - public PendingUploadNotFoundException(String message, Exception ex) : - base(message, ex) - { - } -} - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerAlreadyExistsException", "GitHub.Services.FileContainer.ContainerAlreadyExistsException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerAlreadyExistsException : FileContainerException - { - public ContainerAlreadyExistsException(String artifactUri) - : base(FileContainerResources.ContainerAlreadyExists(artifactUri)) - { - } - - public ContainerAlreadyExistsException(String message, Exception ex) : - base(message, ex) - { - } -} - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerUnexpectedContentTypeException", "GitHub.Services.FileContainer.ContainerUnexpectedContentTypeException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerUnexpectedContentTypeException : FileContainerException - { - public ContainerUnexpectedContentTypeException(String expectedContent, String actualContent) - : base(FileContainerResources.UnexpectedContentType(expectedContent, actualContent)) - { - } - - public ContainerUnexpectedContentTypeException(String message) : - base(message) - { - } - - public ContainerUnexpectedContentTypeException(String message, Exception ex) : - base(message, ex) - { - } -} - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerNoContentException", "GitHub.Services.FileContainer.ContainerNoContentException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerNoContentException : FileContainerException - { - public ContainerNoContentException() - : base(FileContainerResources.NoContentReturned()) - { - } - - public ContainerNoContentException(String message) : - base(message) - { - } - - public ContainerNoContentException(String message, Exception ex) : - base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemContentException", "GitHub.Services.FileContainer.ContainerItemContentException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemContentException : FileContainerException - { - public ContainerItemContentException() - : base(FileContainerResources.NoContentReturned()) - { - } - - public ContainerItemContentException(String message) : - base(message) - { - } - - public ContainerItemContentException(String message, Exception ex) : - base(message, ex) - { - } - } - - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerContentIdCollisionException", "GitHub.Services.FileContainer.ContainerContentIdCollisionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerContentIdCollisionException : FileContainerException - { - public ContainerContentIdCollisionException(String fileId1, String length1, String fileId2, String length2) - : base(FileContainerResources.ContentIdCollision(fileId1, length1, fileId2, length2)) - { - } - - public ContainerContentIdCollisionException(String message) : - base(message) - { - } - - public ContainerContentIdCollisionException(String message, Exception ex) : - base(message, ex) - { - } - } - - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemCreateDuplicateItemException", "GitHub.Services.FileContainer.ContainerItemCreateDuplicateItemException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemCreateDuplicateItemException : FileContainerException - { - public ContainerItemCreateDuplicateItemException(String targetPath) - : base(FileContainerResources.ContainerItemCopyDuplicateTargets(targetPath)) - { - } - public ContainerItemCreateDuplicateItemException(String message, Exception ex) : - base(message, ex) - { - } - } - - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerDeleteFailedException", "GitHub.Services.FileContainer.ContainerDeleteFailedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerDeleteFailedException : FileContainerException - { - public ContainerDeleteFailedException(String targetContainerPath) - : base(targetContainerPath) - { - } - } - - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ContainerItemUpdateFailedException", "GitHub.Services.FileContainer.ContainerItemUpdateFailedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public sealed class ContainerItemUpdateFailedException : FileContainerException - { - public ContainerItemUpdateFailedException(String targetPath) - : base(targetPath) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/GraphExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/GraphExceptions.cs deleted file mode 100644 index a606584aa..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/GraphExceptions.cs +++ /dev/null @@ -1,469 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.Identity; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Graph -{ - [Serializable] - public class GraphException : VssServiceException - { - public GraphException() - { } - - public GraphException(string message) - : base(message) - { } - - public GraphException(string message, Exception innerException) - : base(message, innerException) - { } - - protected GraphException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } - - #region Common Exceptions - - [Serializable] - public class GraphBadRequestException : GraphException - { - protected GraphBadRequestException() - { - } - - public GraphBadRequestException(string message) - : base(message) - { - } - - public GraphBadRequestException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected GraphBadRequestException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class InvalidGraphMemberIdException : GraphException - { - protected InvalidGraphMemberIdException() - { - } - - public InvalidGraphMemberIdException(string message) - : base(message) - { - } - - public InvalidGraphMemberIdException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected InvalidGraphMemberIdException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class GraphSubjectNotFoundException : GraphException - { - protected GraphSubjectNotFoundException() - { - } - - public GraphSubjectNotFoundException(string message) - : base(message) - { - } - - public GraphSubjectNotFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected GraphSubjectNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public GraphSubjectNotFoundException(SubjectDescriptor subjectDescriptor) - : base(GraphResources.GraphSubjectNotFound(subjectDescriptor.ToString())) - { - } - - public GraphSubjectNotFoundException(Guid id) - : base(IdentityResources.IdentityNotFoundWithTfid(id)) - { - } - } - - [Serializable] - public class GraphMemberNotFoundException : GraphException - { - protected GraphMemberNotFoundException() - { - } - - public GraphMemberNotFoundException(string message) - : base(message) - { - } - - public GraphMemberNotFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected GraphMemberNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public GraphMemberNotFoundException(SubjectDescriptor subjectDescriptor, SubjectDescriptor containerDescriptor) - : base(GraphResources.GraphMembershipNotFound(subjectDescriptor.ToString(), containerDescriptor.ToString())) - { - } - } - - [Serializable] - public class GraphMembershipNotFoundException : GraphException - { - protected GraphMembershipNotFoundException() - { - } - - public GraphMembershipNotFoundException(string message) - : base(message) - { - } - - public GraphMembershipNotFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected GraphMembershipNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public GraphMembershipNotFoundException(SubjectDescriptor subjectDescriptor, SubjectDescriptor containerDescriptor) - : base(GraphResources.GraphMembershipNotFound(subjectDescriptor.ToString(), containerDescriptor.ToString())) - { - } - } - - [Serializable] - public class GraphApiUnavailableException : GraphException - { - protected GraphApiUnavailableException() - { - } - - public GraphApiUnavailableException(string message) - : base(message) - { - } - - public GraphApiUnavailableException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected GraphApiUnavailableException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public GraphApiUnavailableException(SubjectDescriptor subjectDescriptor) - : base(IdentityResources.IdentityNotFoundWithDescriptor(subjectDescriptor.SubjectType, subjectDescriptor.Identifier)) - { - } - - public GraphApiUnavailableException(Guid id) - : base(IdentityResources.IdentityNotFoundWithTfid(id)) - { - } - } - - #endregion - - [Serializable] - public class GraphProviderInfoApiUnavailableException : GraphException - { - protected GraphProviderInfoApiUnavailableException() - { - } - - public GraphProviderInfoApiUnavailableException(string message) - : base(message) - { - } - - public GraphProviderInfoApiUnavailableException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected GraphProviderInfoApiUnavailableException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public GraphProviderInfoApiUnavailableException(SubjectDescriptor subjectDescriptor) - : base(IdentityResources.IdentityNotFoundWithDescriptor(subjectDescriptor.SubjectType, subjectDescriptor.Identifier)) - { - } - - public GraphProviderInfoApiUnavailableException(Guid id) - : base(IdentityResources.IdentityNotFoundWithTfid(id)) - { - } - } - - [Serializable] - public class SubjectDescriptorNotFoundException : GraphException - { - public SubjectDescriptorNotFoundException() - { } - - public SubjectDescriptorNotFoundException(string message) - : base(message) - { } - - public SubjectDescriptorNotFoundException(string message, Exception innerException) - : base(message, innerException) - { } - - protected SubjectDescriptorNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - - public SubjectDescriptorNotFoundException(Guid storageKey) - : base(GraphResources.SubjectDescriptorNotFoundWithStorageKey(storageKey)) - { - } - - public SubjectDescriptorNotFoundException(IdentityDescriptor identityDescriptor) - : base(GraphResources.SubjectDescriptorNotFoundWithIdentityDescriptor(identityDescriptor)) - { - } - } - - [Serializable] - public class StorageKeyNotFoundException : GraphException - { - public StorageKeyNotFoundException() - { } - - public StorageKeyNotFoundException(string message) - : base(message) - { } - - public StorageKeyNotFoundException(string message, Exception innerException) - : base(message, innerException) - { } - - protected StorageKeyNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - - public StorageKeyNotFoundException(SubjectDescriptor descriptor) - : base(GraphResources.StorageKeyNotFound(descriptor)) - { - } - } - - [Serializable] - public class InvalidGetDescriptorRequestException : GraphException - { - public InvalidGetDescriptorRequestException() - { } - - public InvalidGetDescriptorRequestException(string message) - : base(message) - { } - - public InvalidGetDescriptorRequestException(string message, Exception innerException) - : base(message, innerException) - { } - - protected InvalidGetDescriptorRequestException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - - public InvalidGetDescriptorRequestException(Guid id) - : base(IdentityResources.InvalidGetDescriptorRequestWithLocalId(id)) - { - } - } - - [Serializable] - public class TooManyRequestedItemsException : GraphException - { - /// - /// Gets the count of the requested items. - /// Note: the value can be null based on whether the message disclose the limit. - /// - [DataMember] - public int? RequestedCount { get; set; } - - /// - /// Gets max limit for the requested items. - /// Note: the value can be null based on whether the message disclose the limit. - /// - [DataMember] - public int? MaxLimit { get; set; } - - public TooManyRequestedItemsException() - : base(IdentityResources.TooManyRequestedItemsError()) - { } - - public TooManyRequestedItemsException(string message) - : base(message) - { } - - public TooManyRequestedItemsException(string message, Exception innerException) - : base(message, innerException) - { } - - protected TooManyRequestedItemsException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - - public TooManyRequestedItemsException(int providedCount, int maxCount) - : base(IdentityResources.TooManyRequestedItemsErrorWithCount(providedCount, maxCount)) - { - this.RequestedCount = providedCount; - this.MaxLimit = maxCount; - } - } - - [Serializable] - public class InvalidGraphRequestException : GraphException - { - public InvalidGraphRequestException() - { } - - public InvalidGraphRequestException(string message) - : base(message) - { } - - public InvalidGraphRequestException(string message, Exception innerException) - : base(message, innerException) - { } - - protected InvalidGraphRequestException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } - - [Serializable] - public class CannotEditChildrenOfNonGroupException : GraphException - { - public CannotEditChildrenOfNonGroupException() - { } - - public CannotEditChildrenOfNonGroupException(string message) - : base(message) - { } - - public CannotEditChildrenOfNonGroupException(string message, Exception innerException) - : base(message, innerException) - { } - - protected CannotEditChildrenOfNonGroupException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - - public CannotEditChildrenOfNonGroupException(SubjectDescriptor subjectDescriptor) - : base(GraphResources.CannotEditChildrenOfNonGroup(subjectDescriptor.ToString())) - { - } - } - - [Serializable] - public class InvalidSubjectTypeException : GraphException - { - public InvalidSubjectTypeException() - { } - - public InvalidSubjectTypeException(string message) - : base(message) - { } - - public InvalidSubjectTypeException(string message, Exception innerException) - : base(message, innerException) - { } - - protected InvalidSubjectTypeException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } - - [Serializable] - public class GraphAccountNameCollisionRepairUnsafeException : GraphException - { - public GraphAccountNameCollisionRepairUnsafeException() - { } - - public GraphAccountNameCollisionRepairUnsafeException(string message) - : base(message) - { } - - public GraphAccountNameCollisionRepairUnsafeException(string message, Exception innerException) - : base(message, innerException) - { } - - protected GraphAccountNameCollisionRepairUnsafeException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } - - [Serializable] - public class GraphAccountNameCollisionRepairFailedException : GraphException - { - public GraphAccountNameCollisionRepairFailedException() - { } - - public GraphAccountNameCollisionRepairFailedException(string message) - : base(message) - { } - - public GraphAccountNameCollisionRepairFailedException(string message, Exception innerException) - : base(message, innerException) - { } - - protected GraphAccountNameCollisionRepairFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } - - [Serializable] - public class CannotUpdateWellKnownGraphGroupException : GraphException - { - public CannotUpdateWellKnownGraphGroupException() - { } - - public CannotUpdateWellKnownGraphGroupException(string message) - : base(message) - { } - - public CannotUpdateWellKnownGraphGroupException(string message, Exception innerException) - : base(message, innerException) - { } - - protected CannotUpdateWellKnownGraphGroupException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/IdentityExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/IdentityExceptions.cs deleted file mode 100644 index 12db542e7..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/IdentityExceptions.cs +++ /dev/null @@ -1,1533 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Globalization; -using System.Runtime.Serialization; -using System.Text; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Identity -{ - [Serializable] - [ExceptionMapping("0.0", "3.0", "IdentityServiceException", "GitHub.Services.Identity.IdentityServiceException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityServiceException : VssServiceException - { - public IdentityServiceException() - { - EventId = VssEventId.VssIdentityServiceException; - } - - public IdentityServiceException(string message) - : base(message) - { - EventId = VssEventId.VssIdentityServiceException; - } - - public IdentityServiceException(string message, Exception innerException) - : base(message, innerException) - { - EventId = VssEventId.VssIdentityServiceException; - } - - protected IdentityServiceException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - EventId = VssEventId.VssIdentityServiceException; - } - } - /// - /// The group you are creating already exists, thrown by the data tier - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "GroupCreationException", "GitHub.Services.Identity.GroupCreationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class GroupCreationException : IdentityServiceException - { - public GroupCreationException(string displayName, string projectName) - : base(IdentityResources.GROUPCREATIONERROR(displayName, projectName)) - { - } - - public GroupCreationException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// IMS domain is incorrect for operation - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityDomainMismatchException", "GitHub.Services.Identity.IdentityDomainMismatchException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityDomainMismatchException : IdentityServiceException - { - public IdentityDomainMismatchException(string incorrectHost, string correctHost) - : base(IdentityResources.IDENTITYDOMAINMISMATCHERROR(incorrectHost, correctHost)) - { - } - - public IdentityDomainMismatchException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected IdentityDomainMismatchException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// You are trying to add a group that is a parent group of the current group, throw - /// by the data tier - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "AddMemberCyclicMembershipException", "GitHub.Services.Identity.AddMemberCyclicMembershipException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddMemberCyclicMembershipException : IdentityServiceException - { - public AddMemberCyclicMembershipException() - { - } - - public AddMemberCyclicMembershipException(string groupName, string memberName) - : base(IdentityResources.ADDMEMBERCYCLICMEMBERSHIPERROR(groupName, memberName)) - { - } - - public AddMemberCyclicMembershipException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected AddMemberCyclicMembershipException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// You are trying to create a group scope that already exists - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "GroupScopeCreationException", "GitHub.Services.Identity.GroupScopeCreationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class GroupScopeCreationException : IdentityServiceException - { - public GroupScopeCreationException() - { - } - - public GroupScopeCreationException(String message, Exception innerException) - : base(message, innerException) - { - } - - public GroupScopeCreationException(string scopeId) - : base(IdentityResources.GROUPSCOPECREATIONERROR(scopeId)) - { - } - - protected GroupScopeCreationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Group cannot be created in the requested scope since the requested scope is not within the root scope. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - public class IncompatibleScopeException : IdentityServiceException - { - public IncompatibleScopeException() - { - } - - public IncompatibleScopeException(String message): base(message) - { - } - public IncompatibleScopeException(String message, Exception innerException) - : base(message, innerException) - { - } - - public IncompatibleScopeException(string rootScopeId, string scopeIdToCheck) - : base(IdentityResources.IncompatibleScopeError(rootScopeId, scopeIdToCheck)) - { - } - - protected IncompatibleScopeException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Trying to add a member to a group that is already a member of the group, thrown by the data tier. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "AddMemberIdentityAlreadyMemberException", "GitHub.Services.Identity.AddMemberIdentityAlreadyMemberException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddMemberIdentityAlreadyMemberException : IdentityServiceException - { - public AddMemberIdentityAlreadyMemberException(string groupName, string memberName) - : base(IdentityResources.ADDMEMBERIDENTITYALREADYMEMBERERROR(groupName, memberName)) - { - } - - public AddMemberIdentityAlreadyMemberException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected AddMemberIdentityAlreadyMemberException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveAccountOwnerFromAdminGroupException", "GitHub.Services.Identity.RemoveAccountOwnerFromAdminGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RemoveAccountOwnerFromAdminGroupException : IdentityServiceException - { - public RemoveAccountOwnerFromAdminGroupException() - : base(IdentityResources.AccountOwnerCannotBeRemovedFromGroup(IdentityResources.ProjectCollectionAdministrators())) { } - - public RemoveAccountOwnerFromAdminGroupException(string message) : base(message){ } - - public RemoveAccountOwnerFromAdminGroupException(string message, Exception innerException) : base(message, innerException) { } - } - - /// - /// You can't remove yourself from the global namespace admins group and lock yourself out of your collection/hosting account. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveSelfFromAdminGroupException", "GitHub.Services.Identity.RemoveSelfFromAdminGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RemoveSelfFromAdminGroupException : IdentityServiceException - { - public RemoveSelfFromAdminGroupException() - : base(IdentityResources.RemoveSelfFromAdminGroupError(BlockRemovingSelfFromAdminGroup)) - { - } - - public RemoveSelfFromAdminGroupException(String message, Exception innerException) - : base(message, innerException) - { - } - - private const String BlockRemovingSelfFromAdminGroup = @"/Service/Integration/Settings/BlockRemovingSelfFromAdminGroup"; - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveOrganizationAdminFromAdminGroupException", "GitHub.Services.Identity.RemoveOrganizationAdminFromAdminGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - class RemoveOrganizationAdminFromAdminGroupException : IdentityServiceException - { - public RemoveOrganizationAdminFromAdminGroupException(string message) : base(message) { } - - public RemoveOrganizationAdminFromAdminGroupException(String message, Exception innerException) : base(message, innerException) { } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveServiceAccountsFromAdminGroupException", "GitHub.Services.Identity.RemoveServiceAccountsFromAdminGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - class RemoveServiceAccountsFromAdminGroupException : IdentityServiceException - { - public RemoveServiceAccountsFromAdminGroupException(string message) : base(message) { } - public RemoveServiceAccountsFromAdminGroupException(String message, Exception innerException) : base(message, innerException) { } - } - - /// - /// Group member you are trying to delete was not a member of the group. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveGroupMemberNotMemberException", "GitHub.Services.Identity.RemoveGroupMemberNotMemberException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RemoveGroupMemberNotMemberException : IdentityServiceException - { - public RemoveGroupMemberNotMemberException(string sid) - : base(IdentityResources.REMOVEGROUPMEMBERNOTMEMBERERROR(sid)) - { - } - - public RemoveGroupMemberNotMemberException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// Thrown when an AddMemberToGroup call is made to put an identity X into group Y, but the action - /// is not legal for some reason related to identity X - /// - [Serializable] - [ExceptionMapping("0.0", "3.0", "AddGroupMemberIllegalMemberException", "GitHub.Services.Identity.AddGroupMemberIllegalMemberException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddGroupMemberIllegalMemberException : IdentityServiceException - { - public AddGroupMemberIllegalMemberException() - { - } - - public AddGroupMemberIllegalMemberException(String message) - : base(message) - { - } - - public AddGroupMemberIllegalMemberException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected AddGroupMemberIllegalMemberException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Cannot add windows identity to hosted deployment - /// - [Serializable] - [ExceptionMapping("0.0", "3.0", "AddGroupMemberIllegalWindowsIdentityException", "GitHub.Services.Identity.AddGroupMemberIllegalWindowsIdentityException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddGroupMemberIllegalWindowsIdentityException : IdentityServiceException - { - public AddGroupMemberIllegalWindowsIdentityException(Identity member) - : base(IdentityResources.ADDGROUPMEMBERILLEGALWINDOWSIDENTITY(member.DisplayName)) - { - } - - public AddGroupMemberIllegalWindowsIdentityException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// Cannot add internet identity to on premise deployment - /// - [Serializable] - [ExceptionMapping("0.0", "3.0", "AddGroupMemberIllegalInternetIdentityException", "GitHub.Services.Identity.AddGroupMemberIllegalInternetIdentityException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddGroupMemberIllegalInternetIdentityException : IdentityServiceException - { - public AddGroupMemberIllegalInternetIdentityException(Identity member) - : base(IdentityResources.ADDGROUPMEMBERILLEGALINTERNETIDENTITY(member.DisplayName)) - { - } - - public AddGroupMemberIllegalInternetIdentityException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// Trying to remove a group that doesn't exist, thrown by the data tier - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveNonexistentGroupException", "GitHub.Services.Identity.RemoveNonexistentGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RemoveNonexistentGroupException : IdentityServiceException - { - public RemoveNonexistentGroupException(string sid) - : base(IdentityResources.REMOVENONEXISTENTGROUPERROR(sid)) - { - } - - public RemoveNonexistentGroupException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// You can't remove any of the special groups: the global administrators group, the - /// service users group, the team foundation valid users group, or a project administration - /// group. Thrown by the data tier. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveSpecialGroupException", "GitHub.Services.Identity.RemoveSpecialGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RemoveSpecialGroupException : IdentityServiceException - { - public RemoveSpecialGroupException(string sid, SpecialGroupType specialType) - : base(BuildMessage(sid, specialType)) - { - } - - public RemoveSpecialGroupException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected static string BuildMessage(string sid, SpecialGroupType specialType) - { - switch (specialType) - { - case SpecialGroupType.AdministrativeApplicationGroup: - return IdentityResources.REMOVEADMINGROUPERROR(); - - case SpecialGroupType.EveryoneApplicationGroup: - return IdentityResources.REMOVEEVERYONEGROUPERROR(); - - case SpecialGroupType.ServiceApplicationGroup: - return IdentityResources.REMOVESERVICEGROUPERROR(); - - default: - return IdentityResources.REMOVESPECIALGROUPERROR(); - } - } - } - - /// - /// Group you were looking up does not exist, thrown by the data tier - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "FindGroupSidDoesNotExistException", "GitHub.Services.Identity.FindGroupSidDoesNotExistException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class FindGroupSidDoesNotExistException : IdentityServiceException - { - public FindGroupSidDoesNotExistException(string sid) - : base(IdentityResources.FINDGROUPSIDDOESNOTEXISTERROR(sid)) - { - } - - public FindGroupSidDoesNotExistException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected FindGroupSidDoesNotExistException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Group rename error, new name already in use - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "GroupRenameException", "GitHub.Services.Identity.GroupRenameException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class GroupRenameException : IdentityServiceException - { - public GroupRenameException(string displayName) - : base(IdentityResources.GROUPRENAMEERROR(displayName)) - { - } - - public GroupRenameException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// You cannot add a project group to a project group in a different project - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "AddProjectGroupProjectMismatchException", "GitHub.Services.Identity.AddProjectGroupProjectMismatchException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddProjectGroupProjectMismatchException : IdentityServiceException - { - public AddProjectGroupProjectMismatchException() - { - } - - public AddProjectGroupProjectMismatchException(string groupName, string memberName) - : base(IdentityResources.ADDPROJECTGROUPTPROJECTMISMATCHERROR(groupName, memberName)) - { - } - - public AddProjectGroupProjectMismatchException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected AddProjectGroupProjectMismatchException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "AddProjectGroupToGlobalGroupException", "GitHub.Services.Identity.AddProjectGroupToGlobalGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AddProjectGroupToGlobalGroupException : IdentityServiceException - { - public AddProjectGroupToGlobalGroupException() - { - } - - public AddProjectGroupToGlobalGroupException(string globalGroupName, string projectGroupName) - : base(IdentityResources.ADDPROJECTGROUPTOGLOBALGROUPERROR(projectGroupName, globalGroupName)) - { - } - - public AddProjectGroupToGlobalGroupException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected AddProjectGroupToGlobalGroupException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Unable to locate project for the project uri passed in - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "GroupScopeDoesNotExistException", "GitHub.Services.Identity.GroupScopeDoesNotExistException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class GroupScopeDoesNotExistException : IdentityServiceException - { - [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")] - public GroupScopeDoesNotExistException(string projectUri) - : base(IdentityResources.GROUPSCOPEDOESNOTEXISTERROR(projectUri)) - { - } - - public GroupScopeDoesNotExistException(Guid scopeId) - : base(IdentityResources.GROUPSCOPEDOESNOTEXISTERROR(scopeId)) - { - } - - public GroupScopeDoesNotExistException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected GroupScopeDoesNotExistException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// This exception is thrown when a user tries to add a group that is - /// not an application group. We do not modify the memberships of Windows groups. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "NotApplicationGroupException", "GitHub.Services.Identity.NotApplicationGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class NotApplicationGroupException : IdentityServiceException - { - public NotApplicationGroupException() - : base(IdentityResources.NOT_APPLICATION_GROUP()) - { - } - - public NotApplicationGroupException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// You must specify a group when removing members from a group, thrown by the app tier - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ModifyEveryoneGroupException", "GitHub.Services.Identity.ModifyEveryoneGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ModifyEveryoneGroupException : IdentityServiceException - { - public ModifyEveryoneGroupException() - : base(IdentityResources.MODIFYEVERYONEGROUPEXCEPTION()) - { - } - - public ModifyEveryoneGroupException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// ReadIdentityFromSource returned null and we need an identity to continue the operation - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityNotFoundException", "GitHub.Services.Identity.IdentityNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityNotFoundException : IdentityServiceException - { - public IdentityNotFoundException() - : base(IdentityResources.IdentityNotFoundSimpleMessage()) - { - } - - public IdentityNotFoundException(String message) - : base(message) - { - } - - public IdentityNotFoundException(String message, Exception innerException) - : base(message, innerException) - { - } - - public IdentityNotFoundException(IdentityDescriptor descriptor) - : base(IdentityResources.IdentityNotFoundMessage(descriptor.IdentityType)) - { - } - - public IdentityNotFoundException(SubjectDescriptor subjectDescriptor) - : base(IdentityResources.IdentityNotFoundMessage(subjectDescriptor.SubjectType)) - { - } - - public IdentityNotFoundException(Guid tfid) - : base(IdentityResources.IdentityNotFoundWithTfid(tfid)) - { - } - } - - /// - /// Identity is not part of calling identity's directory - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - public class IdentityNotFoundInCurrentDirectoryException : IdentityServiceException - { - public IdentityNotFoundInCurrentDirectoryException() - : base(IdentityResources.IdentityNotFoundInCurrentDirectory()) - { - } - - public IdentityNotFoundInCurrentDirectoryException(String message) - : base(message) - { - } - - public IdentityNotFoundInCurrentDirectoryException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// The identity is not a service identity - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityNotServiceIdentityException", "GitHub.Services.Identity.IdentityNotServiceIdentityException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityNotServiceIdentityException : IdentityServiceException - { - public IdentityNotServiceIdentityException(String message) - : base(message) - { - } - - public IdentityNotServiceIdentityException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidServiceIdentityNameException", "GitHub.Services.Identity.InvalidServiceIdentityNameException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidServiceIdentityNameException : IdentityServiceException - { - public InvalidServiceIdentityNameException(String identityName) - : base(IdentityResources.InvalidServiceIdentityName(identityName)) - { - } - - public InvalidServiceIdentityNameException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// The identity already exists - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityAlreadyExistsException", "GitHub.Services.Identity.IdentityAlreadyExistsException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityAlreadyExistsException : IdentityServiceException - { - public IdentityAlreadyExistsException(String message) - : base(message) - { - } - - public IdentityAlreadyExistsException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// This exception is thrown when a user tries to add a distribution list - /// to a group. We only allow security groups to used. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "NotASecurityGroupException", "GitHub.Services.Identity.NotASecurityGroupException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class NotASecurityGroupException : IdentityServiceException - { - public NotASecurityGroupException(String displayName) - : base(IdentityResources.NOT_A_SECURITY_GROUP(displayName)) - { - } - - public NotASecurityGroupException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RemoveMemberServiceAccountException", "GitHub.Services.Identity.RemoveMemberServiceAccountException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RemoveMemberServiceAccountException : IdentityServiceException - { - public RemoveMemberServiceAccountException() - : base(IdentityResources.CANNOT_REMOVE_SERVICE_ACCOUNT()) - { - } - - public RemoveMemberServiceAccountException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IllegalAliasException", "GitHub.Services.Identity.IllegalAliasException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IllegalAliasException : IdentityServiceException - { - public IllegalAliasException(string name) : - base(name) - { - } - - public IllegalAliasException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IllegalIdentityException", "GitHub.Services.Identity.IllegalIdentityException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IllegalIdentityException : IdentityServiceException - { - public IllegalIdentityException(string name) : - base(IdentityResources.IllegalIdentityException(name)) - { - } - - public IllegalIdentityException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentitySyncException", "GitHub.Services.Identity.IdentitySyncException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentitySyncException : IdentityServiceException - { - public IdentitySyncException(string message, Exception innerException) : - base(IdentityResources.IDENTITY_SYNC_ERROR(message)) - { - } - } - - /// - /// Identity provider not available - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityProviderUnavailableException", "GitHub.Services.Identity.IdentityProviderUnavailableException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityProviderUnavailableException : IdentityServiceException - { - public IdentityProviderUnavailableException(IdentityDescriptor descriptor) - : base(IdentityResources.IdentityProviderUnavailable(descriptor.IdentityType, descriptor.Identifier)) - { - } - - public IdentityProviderUnavailableException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityPropertyRequiredException", "GitHub.Services.Identity.IdentityPropertyRequiredException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityPropertyRequiredException : IdentityServiceException - { - public IdentityPropertyRequiredException(String message) - : base(message) - { - } - - public IdentityPropertyRequiredException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityAccountNameAlreadyInUseException", "GitHub.Services.Identity.IdentityAccountNameAlreadyInUseException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityAccountNameAlreadyInUseException : IdentityServiceException - { - public IdentityAccountNameAlreadyInUseException(String oneAccountName, Int32 collisionCount) - : base(BuildExceptionMessage(oneAccountName, collisionCount)) - { - } - - public IdentityAccountNameAlreadyInUseException(String message, Exception innerException) - : base(message, innerException) - { - } - - private static String BuildExceptionMessage(String oneAccountName, Int32 collisionCount) - { - Debug.Assert(collisionCount > 0, "identity account name exception fired, but no collisions were found"); - - if (collisionCount == 1) - { - return IdentityResources.IdentityAccountNameAlreadyInUseError(oneAccountName); - } - else - { - return IdentityResources.IdentityAccountNamesAlreadyInUseError(collisionCount, oneAccountName); - } - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityAccountNameCollisionRepairFailedException", "GitHub.Services.Identity.IdentityAccountNameCollisionRepairFailedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityAccountNameCollisionRepairFailedException : IdentityServiceException - { - public IdentityAccountNameCollisionRepairFailedException(String accountName) - : base(IdentityResources.IdentityAccountNameCollisionRepairFailedError(accountName)) - { - } - - public IdentityAccountNameCollisionRepairFailedException(String accountName, Exception innerException) - : base(IdentityResources.IdentityAccountNameCollisionRepairFailedError(accountName), innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityAccountNameCollisionRepairUnsafeException", "GitHub.Services.Identity.IdentityAccountNameCollisionRepairUnsafeException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityAccountNameCollisionRepairUnsafeException : IdentityServiceException - { - public IdentityAccountNameCollisionRepairUnsafeException(String accountName) - : base(IdentityResources.IdentityAccountNameCollisionRepairUnsafeError(accountName)) - { - } - - public IdentityAccountNameCollisionRepairUnsafeException(String accountName, Exception innerException) - : base(IdentityResources.IdentityAccountNameCollisionRepairUnsafeError(accountName), innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityAliasAlreadyInUseException", "GitHub.Services.Identity.IdentityAliasAlreadyInUseException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityAliasAlreadyInUseException : IdentityServiceException - { - public IdentityAliasAlreadyInUseException(String conflictingAlias) - : base(IdentityResources.IdentityAliasAlreadyInUseError(conflictingAlias)) - { - } - - public IdentityAliasAlreadyInUseException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "DynamicIdentityTypeCreationNotSupportedException", "GitHub.Services.Identity.DynamicIdentityTypeCreationNotSupportedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class DynamicIdentityTypeCreationNotSupportedException : IdentityServiceException - { - public DynamicIdentityTypeCreationNotSupportedException() - : base(IdentityResources.DynamicIdentityTypeCreationNotSupported()) - { - } - - public DynamicIdentityTypeCreationNotSupportedException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "TooManyIdentitiesReturnedException", "GitHub.Services.Identity.TooManyIdentitiesReturnedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class TooManyIdentitiesReturnedException : IdentityServiceException - { - public TooManyIdentitiesReturnedException() - : base(IdentityResources.TooManyResultsError()) - { - } - - public TooManyIdentitiesReturnedException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "MultipleIdentitiesFoundException", "GitHub.Services.Identity.MultipleIdentitiesFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class MultipleIdentitiesFoundException : IdentityServiceException - { - public MultipleIdentitiesFoundException(string identityName, IEnumerable matchingIdentities) - : base(BuildExceptionMessage(identityName, matchingIdentities)) - { - - } - - public MultipleIdentitiesFoundException(string identityName, IEnumerable matchingIdentities) - : base(BuildExceptionMessage(identityName, matchingIdentities)) - { - - } - - public MultipleIdentitiesFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - - private static string BuildExceptionMessage(string identityName, IEnumerable matchingIdentities) - { - StringBuilder builder = new StringBuilder(); - - foreach (var identity in matchingIdentities) - { - builder.AppendFormat(CultureInfo.CurrentUICulture, "- {0} ({1})", identity.ProviderDisplayName, identity.CustomDisplayName); - } - - return IdentityResources.MultipleIdentitiesFoundError(identityName, builder.ToString()); - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "HistoricalIdentityNotFoundException", "GitHub.Services.Identity.HistoricalIdentityNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class HistoricalIdentityNotFoundException : IdentityServiceException - { - public HistoricalIdentityNotFoundException() - : base(IdentityResources.TooManyResultsError()) - { - } - - public HistoricalIdentityNotFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidIdentityIdTranslationException", "GitHub.Services.Identity.InvalidIdentityIdTranslationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidIdentityIdTranslationException : IdentityServiceException - { - public InvalidIdentityIdTranslationException() - : base(IdentityResources.InvalidIdentityIdTranslations()) - { - } - - public InvalidIdentityIdTranslationException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdTranslationsAreMigratedException", "GitHub.Services.Identity.IdTranslationsAreMigratedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdTranslationsAreMigratedException : IdentityServiceException - { - public IdTranslationsAreMigratedException() - : base(IdentityResources.IdentityIdTranslationsAreMigrated()) - { - } - - public IdTranslationsAreMigratedException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidIdentityStorageKeyTranslationException", "GitHub.Services.Identity.InvalidIdentityStorageKeyTranslationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidIdentityStorageKeyTranslationException : IdentityServiceException - { - public InvalidIdentityStorageKeyTranslationException() - : base(IdentityResources.InvalidIdentityKeyMaps()) - { - } - - public InvalidIdentityStorageKeyTranslationException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidIdentityKeyMapsException", "GitHub.Services.Identity.InvalidIdentityKeyMapsException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidIdentityKeyMapException : IdentityServiceException - { - public InvalidIdentityKeyMapException() - : base(IdentityResources.InvalidIdentityKeyMaps()) - { - } - - public InvalidIdentityKeyMapException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidTypeIdForIdentityStorageKeyException", "GitHub.Services.Identity.InvalidTypeIdForIdentityStorageKeyException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidTypeIdForIdentityKeyMapException : IdentityServiceException - { - public InvalidTypeIdForIdentityKeyMapException() - : base(IdentityResources.InvalidIdentityKeyMaps()) - { - } - - public InvalidTypeIdForIdentityKeyMapException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "DuplicateIdentitiesFoundException", "GitHub.Services.Identity.DuplicateIdentitiesFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class DuplicateIdentitiesFoundException : IdentityServiceException - { - public DuplicateIdentitiesFoundException() - : base(IdentityResources.InvalidIdentityIdTranslations()) - { - } - - public DuplicateIdentitiesFoundException(String message) - : base(message) - { - } - - public DuplicateIdentitiesFoundException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityExpressionException", "GitHub.Services.Identity.IdentityExpressionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityExpressionException : IdentityServiceException - { - public IdentityExpressionException(String message) - : base(message) - { - } - - public IdentityExpressionException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidDisplayNameException", "GitHub.Services.Identity.InvalidDisplayNameException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidDisplayNameException : IdentityServiceException - { - public InvalidDisplayNameException(String message) - : base(message) - { - } - - public InvalidDisplayNameException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [ExceptionMapping("0.0", "3.0", "GroupNameNotRecognizedException", "GitHub.Services.Identity.GroupNameNotRecognizedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class GroupNameNotRecognizedException : IdentityServiceException - { - public GroupNameNotRecognizedException() - { - } - - public GroupNameNotRecognizedException(string message, Exception innerException) - : base(message, innerException) - { - } - - public GroupNameNotRecognizedException(string groupName) - : this(IdentityResources.InvalidNameNotRecognized(groupName), null) - { - } - - protected GroupNameNotRecognizedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "AccountPreferencesAlreadyExistException", "GitHub.Services.Identity.AccountPreferencesAlreadyExistException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AccountPreferencesAlreadyExistException : IdentityServiceException - { - public AccountPreferencesAlreadyExistException() - : base(IdentityResources.AccountPreferencesAlreadyExist()) - { - } - - public AccountPreferencesAlreadyExistException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [ExceptionMapping("0.0", "3.0", "IdentityMapReadOnlyException", "GitHub.Services.Identity.IdentityMapReadOnlyException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityMapReadOnlyException : IdentityServiceException - { - public IdentityMapReadOnlyException() - : this((Exception)null) - { - } - - public IdentityMapReadOnlyException(Exception innerException) - : base(IdentityResources.IdentityMapReadOnlyException(), innerException) - { - } - - public IdentityMapReadOnlyException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected IdentityMapReadOnlyException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [ExceptionMapping("0.0", "3.0", "IdentityStoreNotAvailableException", "GitHub.Services.Identity.IdentityStoreNotAvailableException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityStoreNotAvailableException : IdentityServiceException - { - public IdentityStoreNotAvailableException() : base() { } - public IdentityStoreNotAvailableException(string errorMessage) : base(errorMessage) { } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidDisplayNameException", "GitHub.Services.Identity.InvalidChangedIdentityException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidChangedIdentityException : IdentityServiceException - { - public InvalidChangedIdentityException(String message) - : base(message) - { - } - - public InvalidChangedIdentityException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdenittyInvalidTypeIdException", "GitHub.Services.Identity.IdenittyInvalidTypeIdException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - [Obsolete("This exception has been renamed to IdentityInvalidTypeIdException")] - public class IdenittyInvalidTypeIdException : IdentityServiceException - { - public IdenittyInvalidTypeIdException(string message) : - base(message) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "IdentityInvalidTypeIdException", "GitHub.Services.Identity.IdentityInvalidTypeIdException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] -#pragma warning disable 618 - public class IdentityInvalidTypeIdException : IdenittyInvalidTypeIdException -#pragma warning restore 618 - { - public IdentityInvalidTypeIdException(string message) : - base(message) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidIdentityKeyException", "GitHub.Services.Identity.InvalidIdentityKeyException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidIdentityKeyException : IdentityServiceException - { - public InvalidIdentityKeyException() : base() { } - - public InvalidIdentityKeyException(string message) : - base(message) - { - } - } - - [Serializable] - [ExceptionMapping("0.0", "3.0", "IdentityMaterializationFailedException", "GitHub.Services.Identity.IdentityMaterializationFailedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class IdentityMaterializationFailedException : IdentityServiceException - { - public IdentityMaterializationFailedException() - { - } - - public IdentityMaterializationFailedException(string message, Exception innerException) - : base(message, innerException) - { - } - - public IdentityMaterializationFailedException(string principalName) - : this(IdentityResources.IdentityMaterializationFailedMessage(principalName), null) - { - } - - protected IdentityMaterializationFailedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class IdentityDescriptorNotFoundException : IdentityServiceException - { - public IdentityDescriptorNotFoundException() - { } - - public IdentityDescriptorNotFoundException(string message) - : base(message) - { } - - public IdentityDescriptorNotFoundException(string message, Exception innerException) - : base(message, innerException) - { } - - protected IdentityDescriptorNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } - - public IdentityDescriptorNotFoundException(Guid id, bool isMasterId) - : base(isMasterId ? - IdentityResources.IdentityDescriptorNotFoundWithMasterId(id) : - IdentityResources.IdentityDescriptorNotFoundWithLocalId(id)) - { - } - } - - [Serializable] - public abstract class TenantSwitchException : IdentityServiceException - { - public TenantSwitchException() - { - } - - public TenantSwitchException(string message) : base(message) - { - } - - public TenantSwitchException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected TenantSwitchException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class InvitationPendingException : TenantSwitchException - { - public string AccountName { get; } - public string OrganizationName { get; } - - public InvitationPendingException() - { - } - - public InvitationPendingException(string message) - : base(message) - { - } - - public InvitationPendingException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected InvitationPendingException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public InvitationPendingException(string accountName, string organizationName) - : base(IdentityResources.InvitationPendingMessage(accountName, organizationName)) - { - AccountName = accountName; - OrganizationName = organizationName; - } - } - - [Serializable] - public class WrongWorkOrPersonalException : TenantSwitchException - { - public string AccountName { get; } - public bool ShouldBePersonal { get; } - public bool ShouldCreatePersonal { get; } - - public WrongWorkOrPersonalException() - { - } - - public WrongWorkOrPersonalException(string message) - : base(message) - { - } - - public WrongWorkOrPersonalException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected WrongWorkOrPersonalException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - public WrongWorkOrPersonalException(string accountName, bool shouldBePersonal, bool shouldCreatePersonal) - : base(GetMessage(shouldBePersonal, shouldCreatePersonal)) - { - AccountName = accountName; - ShouldBePersonal = shouldBePersonal; - ShouldCreatePersonal = shouldCreatePersonal; - } - - private static string GetMessage(bool shouldBePersonal, bool shouldCreatePersonal) - { - if (shouldBePersonal) - { - if (shouldCreatePersonal) - { - return IdentityResources.ShouldCreatePersonalAccountMessage(); - } - else - { - return IdentityResources.ShouldBePersonalAccountMessage(); - } - } - else - { - return IdentityResources.ShouldBeWorkAccountMessage(); - } - } - } - - [Serializable] - public class InvalidTransferIdentityRightsRequestException : IdentityServiceException - { - public InvalidTransferIdentityRightsRequestException() - { - } - - public InvalidTransferIdentityRightsRequestException(string message) - : base(message) - { - } - - public InvalidTransferIdentityRightsRequestException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected InvalidTransferIdentityRightsRequestException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class FailedTransferIdentityRightsException : IdentityServiceException - { - public FailedTransferIdentityRightsException() - { - } - - public FailedTransferIdentityRightsException(string message) - : base(message) - { - } - - public FailedTransferIdentityRightsException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected FailedTransferIdentityRightsException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class CollectionShardingException : IdentityServiceException - { - public CollectionShardingException() - { - } - - public CollectionShardingException(string message) - : base(message) - { - } - - public CollectionShardingException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected CollectionShardingException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - public class ScopeBadRequestException: IdentityServiceException - { - protected ScopeBadRequestException() - { - } - - public ScopeBadRequestException(string message) - : base(message) - { - } - - public ScopeBadRequestException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected ScopeBadRequestException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Indicates that a caller action triggered an attempt to read or update identity information at the deployment level - /// directly from (or using data from) a sharded host after dual writes had been disabled, meaning that the fallback is not allowed. - /// - [Serializable] - public class FallbackIdentityOperationNotAllowedException : IdentityServiceException - { - public FallbackIdentityOperationNotAllowedException() - { - } - - public FallbackIdentityOperationNotAllowedException(string message) - : base(message) - { - } - - public FallbackIdentityOperationNotAllowedException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected FallbackIdentityOperationNotAllowedException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Thrown when we were trying to create a client to talk to the legacy SPS identity store (e.g. SPS SU1), - /// but were not able to do so due to an unexpected response. - /// - [Serializable] - public class CannotFindLegacySpsIdentityStoreException : IdentityServiceException - { - public CannotFindLegacySpsIdentityStoreException() - { - } - - public CannotFindLegacySpsIdentityStoreException(string message) - : base(message) - { - } - - public CannotFindLegacySpsIdentityStoreException(string message, Exception innerException) - : base(message, innerException) - { - } - - protected CannotFindLegacySpsIdentityStoreException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Unable to restore group scope - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "RestoreGroupScopeValidationException", "GitHub.Services.Identity.RestoreGroupScopeValidationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class RestoreGroupScopeValidationException : IdentityServiceException - { - [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#")] - public RestoreGroupScopeValidationException(string validationError) - : base(IdentityResources.RestoreGroupScopeValidationError(validationError)) - { - } - - public RestoreGroupScopeValidationException(String message, Exception innerException) - : base(message, innerException) - { - } - - protected RestoreGroupScopeValidationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/LocationExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/LocationExceptions.cs deleted file mode 100644 index 44b44cf2f..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/LocationExceptions.cs +++ /dev/null @@ -1,155 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.Serialization; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Location -{ - [Serializable] - [SuppressMessageAttribute("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ServiceDefinitionDoesNotExistException", "GitHub.Services.Location.ServiceDefinitionDoesNotExistException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public partial class ServiceDefinitionDoesNotExistException : VssServiceException - { - public ServiceDefinitionDoesNotExistException(String message) - : base(message) - { - } - - public ServiceDefinitionDoesNotExistException(String message, Exception ex) - : base(message, ex) - { - } - - protected ServiceDefinitionDoesNotExistException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessageAttribute("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidAccessPointException", "GitHub.Services.Location.InvalidAccessPointException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public partial class InvalidAccessPointException : VssServiceException - { - public InvalidAccessPointException(String message) - : base(message) - { - } - - public InvalidAccessPointException(String message, Exception ex) - : base(message, ex) - { - } - - protected InvalidAccessPointException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessageAttribute("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidServiceDefinitionException", "GitHub.Services.Location.InvalidServiceDefinitionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public partial class InvalidServiceDefinitionException : VssServiceException - { - public InvalidServiceDefinitionException(String message) - : base(message) - { - } - - public InvalidServiceDefinitionException(String message, Exception ex) - : base(message, ex) - { - } - - protected InvalidServiceDefinitionException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessageAttribute("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "CannotChangeParentDefinitionException", "GitHub.Services.Location.CannotChangeParentDefinitionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public partial class CannotChangeParentDefinitionException : VssServiceException - { - public CannotChangeParentDefinitionException() - { - } - - public CannotChangeParentDefinitionException(String message) - : base(GetMessage(message)) - { - } - - public CannotChangeParentDefinitionException(String message, Exception ex) - : base(GetMessage(message), ex) - { - } - - protected CannotChangeParentDefinitionException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - private static String GetMessage(String message) - { -#if DEBUG - String helpText = " Are you trying to move an existing Resource Area to a different service? You will need to follow the steps at: https://vsowiki.com/index.php?title=Moving_an_existing_Resource_Area_to_a_different_Service"; - if (message != null && !message.EndsWith(helpText, StringComparison.Ordinal)) - { - message = String.Concat(message, helpText); - } -#endif - return message; - } - } - - [Serializable] - [SuppressMessageAttribute("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ParentDefinitionNotFoundException", "GitHub.Services.Location.ParentDefinitionNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public partial class ParentDefinitionNotFoundException : VssServiceException - { - public ParentDefinitionNotFoundException(String serviceType, Guid identifier, String parentServiceType, Guid serviceInstance) - : this(LocationResources.ParentDefinitionNotFound(serviceType, identifier, parentServiceType, serviceInstance)) - { - } - - public ParentDefinitionNotFoundException(String message) - : base(message) - { - } - - public ParentDefinitionNotFoundException(String message, Exception ex) - : base(message, ex) - { - } - - protected ParentDefinitionNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - [Serializable] - [SuppressMessageAttribute("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ActionDeniedBySubscriberException", "GitHub.Services.Location.ActionDeniedBySubscriberException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public partial class ActionDeniedBySubscriberException : VssServiceException - { - public ActionDeniedBySubscriberException(String message) - : base(message) - { - } - - public ActionDeniedBySubscriberException(String message, Exception ex) - : base(message, ex) - { - } - - protected ActionDeniedBySubscriberException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/SecurityExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/SecurityExceptions.cs deleted file mode 100644 index 2c67437d1..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/SecurityExceptions.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.WebApi; -using GitHub.Services.Identity; - -namespace GitHub.Services.Security -{ - [Serializable] - [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] - [ExceptionMapping("0.0", "3.0", "SecurityException", "GitHub.Services.Security.SecurityException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public abstract class SecurityException : VssServiceException - { - public SecurityException(String message) - : base(message) - { - } - - public SecurityException(String message, Exception ex) - : base(message, ex) - { - } - } - - /// - /// An exception which is thrown when a permission check fails in the security service. - /// - [Serializable] - [ExceptionMapping("0.0", "3.0", "AccessCheckException", "GitHub.Framework.Server.AccessCheckException, GitHub.Framework.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class AccessCheckException : SecurityException - { - /// - /// Constructs an AccessCheckException. - /// - /// The identity descriptor which was checked. - /// The display name of the identity which was checked. - /// The token which was checked. - /// The requested permissions, which were not satisifed by the check. - /// The security namespace which was checked. - /// A descriptive message for the exception. - public AccessCheckException( - IdentityDescriptor descriptor, - String identityDisplayName, - String token, - int requestedPermissions, - Guid namespaceId, - String message) - : this(descriptor, token, requestedPermissions, namespaceId, message) - { - this.IdentityDisplayName = identityDisplayName; - } - - /// - /// Constructs an AccessCheckException. - /// - /// The identity descriptor which was checked. - /// The token which was checked. - /// The requested permissions, which were not satisifed by the check. - /// The security namespace which was checked. - /// A descriptive message for the exception. - public AccessCheckException( - IdentityDescriptor descriptor, - String token, - int requestedPermissions, - Guid namespaceId, - String message) - : base(message) - { - ArgumentUtility.CheckForNull(descriptor, nameof(descriptor)); - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(message, nameof(message)); - - this.Descriptor = descriptor; - this.Token = token; - this.RequestedPermissions = requestedPermissions; - this.NamespaceId = namespaceId; - } - - public AccessCheckException(String message) - : base(message) - { - } - - /// - /// The identity descriptor which was checked. - /// - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public IdentityDescriptor Descriptor { get; private set; } - - /// - /// The display name of the identity which was checked. - /// This property may be null. - /// - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public String IdentityDisplayName { get; private set; } - - /// - /// The token which was checked. - /// - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public String Token { get; private set; } - - /// - /// The permissions which were demanded. - /// - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public int RequestedPermissions { get; private set; } - - /// - /// The identifier of the security namespace which was checked. - /// - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public Guid NamespaceId { get; private set; } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidAclStoreException", "GitHub.Services.Security.InvalidAclStoreException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidAclStoreException : SecurityException - { - public InvalidAclStoreException(Guid namespaceId, Guid aclStoreId) - : this(SecurityResources.InvalidAclStoreException(namespaceId, aclStoreId)) - { - } - - public InvalidAclStoreException(String message) - : base(message) - { - } - - public InvalidAclStoreException(String message, Exception ex) - : base(message, ex) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - public class InvalidPermissionsException : SecurityException - { - public InvalidPermissionsException(Guid namespaceId, Int32 bitmask) - : this(SecurityResources.InvalidPermissionsException(namespaceId, bitmask)) - { - } - - public InvalidPermissionsException(String message) - : base(message) - { - } - - public InvalidPermissionsException(String message, Exception ex) - : base(message, ex) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Exceptions/VssApiResourceExceptions.cs b/src/Sdk/WebApi/WebApi/Exceptions/VssApiResourceExceptions.cs deleted file mode 100644 index 5200a2e3d..000000000 --- a/src/Sdk/WebApi/WebApi/Exceptions/VssApiResourceExceptions.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi -{ - /// - /// Exception thrown when the requested API resource location was not found on the server - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssResourceNotFoundException", "GitHub.Services.WebApi.VssResourceNotFoundException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssResourceNotFoundException : VssServiceException - { - public VssResourceNotFoundException(Guid locationId) - : this(WebApiResources.ResourceNotRegisteredMessage(locationId)) - { - } - - public VssResourceNotFoundException(Guid locationId, Uri serverBaseUri) - : this(WebApiResources.ResourceNotFoundOnServerMessage(locationId, serverBaseUri)) - { - } - - public VssResourceNotFoundException(String message) - : base(message) - { - } - } - - /// - /// Base exception class for api resource version exceptions - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssResourceVersionException", "GitHub.Services.WebApi.VssResourceVersionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public abstract class VssResourceVersionException : VssServiceException - { - public VssResourceVersionException(String message) - : base(message) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssInvalidApiResourceVersionException", "GitHub.Services.WebApi.VssInvalidApiResourceVersionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssInvalidApiResourceVersionException : VssResourceVersionException - { - public VssInvalidApiResourceVersionException(String apiResourceVersionString) - : base(WebApiResources.InvalidApiVersionStringMessage(apiResourceVersionString)) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssApiResourceDuplicateIdException", "GitHub.Services.WebApi.VssApiResourceDuplicateIdException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssApiResourceDuplicateIdException: VssApiRouteRegistrationException - { - public VssApiResourceDuplicateIdException(Guid locationId) - : base(WebApiResources.ApiResourceDuplicateIdMessage(locationId)) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssApiResourceDuplicateRouteNameException", "GitHub.Services.WebApi.VssApiResourceDuplicateRouteNameException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssApiResourceDuplicateRouteNameException : VssApiRouteRegistrationException - { - public VssApiResourceDuplicateRouteNameException(string routeName) - : base(WebApiResources.ApiResourceDuplicateRouteNameMessage(routeName)) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssApiRouteRegistrationException", "GitHub.Services.WebApi.VssApiRouteRegistrationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public abstract class VssApiRouteRegistrationException : VssResourceVersionException - { - public VssApiRouteRegistrationException(string message) - : base(message) - { - } - } - - /// - /// Exception thrown when the requested version of a resource is not supported on the server - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssVersionNotSupportedException", "GitHub.Services.WebApi.VssVersionNotSupportedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssVersionNotSupportedException : VssResourceVersionException - { - public VssVersionNotSupportedException(ApiResourceLocation location, Version requestedVersion, Version minSupportedVersion, Uri serverBaseUri) - : base(WebApiResources.ClientResourceVersionNotSupported(location.Area + ":" + location.ResourceName + " " + location.Id, requestedVersion, serverBaseUri, minSupportedVersion)) - { - } - } - - /// - /// Exception thrown when the requested version of a resource is greater than the latest api version the server supports. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - public class VssVersionOutOfRangeException : VssResourceVersionException - { - public VssVersionOutOfRangeException(Version requestedVersion, Version maxSupportedVersion) - : base(WebApiResources.ApiVersionOutOfRange(requestedVersion, maxSupportedVersion)) - { - } - - public VssVersionOutOfRangeException(ApiResourceVersion requestedApiVersion, string routeMatchedExceptVersion) - : base(WebApiResources.ApiVersionOutOfRangeForRoute(requestedApiVersion, routeMatchedExceptVersion)) - { - } - - public VssVersionOutOfRangeException(ApiResourceVersion requestedApiVersion, IEnumerable routesMatchedExceptVersion) - : base(WebApiResources.ApiVersionOutOfRangeForRoutes(requestedApiVersion, string.Join(", ", routesMatchedExceptVersion))) - { - } - - public VssVersionOutOfRangeException(string message) - : base(message) - { - } - } - - /// - /// Exception thrown when the api-version is not supplied for a particular type of request - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssVersionNotSpecifiedException", "GitHub.Services.WebApi.VssVersionNotSpecifiedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssVersionNotSpecifiedException : VssResourceVersionException - { - public VssVersionNotSpecifiedException(String httpMethod) - : base(WebApiResources.VersionNotSuppliedMessage(httpMethod)) - { - } - } - - /// - /// Exception thrown when the requested version of a resource is a "preview" api, but -preview is not supplied in the request's api-version - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssInvalidPreviewVersionException", "GitHub.Services.WebApi.VssInvalidPreviewVersionException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssInvalidPreviewVersionException : VssResourceVersionException - { - public VssInvalidPreviewVersionException(ApiResourceVersion requestedVersion) - : base(WebApiResources.PreviewVersionNotSuppliedMessage(requestedVersion.ToString())) - { - } - } - - /// - /// Exception thrown when a request body's contentType is not supported by a given controller. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssRequestContentTypeNotSupportedException", "GitHub.Services.WebApi.VssRequestContentTypeNotSupportedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssRequestContentTypeNotSupportedException : VssServiceException - { - public VssRequestContentTypeNotSupportedException(String contentType, String httpMethod, IEnumerable validContentTypes) - : base(WebApiResources.RequestContentTypeNotSupported(contentType, httpMethod, String.Join(", ", validContentTypes))) - { - } - } - - /// - /// Exception thrown when a cross-origin request is made using cookie-based authentication from an unsafe domain. - /// - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - public class VssApiUnsafeCrossOriginRequestException : VssServiceException - { - public VssApiUnsafeCrossOriginRequestException(String origin) - : base(WebApiResources.UnsafeCrossOriginRequest(origin)) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/HttpClients/Constants.cs b/src/Sdk/WebApi/WebApi/HttpClients/Constants.cs deleted file mode 100644 index c93c64057..000000000 --- a/src/Sdk/WebApi/WebApi/HttpClients/Constants.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.ComponentModel; - -namespace GitHub.Services -{ - internal static class QueryParameters - { - //Common query parameters - internal const String Properties = "properties"; - - //Account query parameters - internal const String CreatorId = "creatorId"; - internal const String OwnerId = "ownerId"; - internal const String IncludeDisabledAccounts = "includeDisabledAccounts"; - internal const String IncludeOwner = "includeOwner"; - internal const String StatusReason = "statusReason"; - internal const String IncludeDeletedUsers = "includeDeletedUsers"; - internal const String AccountId = "accountId"; - internal const String UsePrecreated = "usePrecreated"; - internal const string UserType = "userType"; - - //Identity query parameters - internal const String SubjectDescriptors = "subjectDescriptors"; - internal const String SocialDescriptors = "socialDescriptors"; - internal const String Descriptors = "descriptors"; - internal const String IdentityIds = "identityIds"; - internal const String SearchFilter = "searchFilter"; - internal const String FilterValue = "filterValue"; - internal const String QueryMembership = "queryMembership"; - internal const String IdentitySequenceId = "identitySequenceId"; - internal const String GroupSequenceId = "groupSequenceId"; - internal const String OrgIdentitySequenceId = "organizationIdentitySequenceId"; - internal const String PageSize = "pageSize"; - internal const String ScopeId = "scopeId"; - internal const String ScopeIds = "scopeIds"; - internal const String Recurse = "recurse"; - internal const String Deleted = "deleted"; - internal const String ScopeName = "scopeName"; - internal const String MemberId = "memberId"; - internal const String IncludeRestrictedVisibility = "includeRestrictedVisibility"; - internal const String ReadAllIdentities = "readAllIdentities"; - internal const String ReadIdentitiesOptions = "options"; - internal const String DomainId = "domainId"; - - //DelegatedAuthorization query parameters - internal const String UserId = "userId"; - internal const String DisplayName = "displayName"; - internal const String ValidTo = "validTo"; - internal const String Scope = "scope"; - internal const String AccessTokenKey = "key"; - internal const String TokenType = "tokenType"; - - //Security query parameters - internal const String AlwaysAllowAdministrators = "alwaysAllowAdministrators"; - internal const String Descriptor = "descriptor"; - internal const String IncludeExtendedInfo = "includeExtendedInfo"; - internal const String LocalOnly = "localonly"; - internal const String Token = "token"; - internal const String Tokens = "tokens"; - internal const String Delimiter = "delimiter"; - - // Security backing store query parameters - internal const String OldSequenceId = "oldSequenceId"; - internal const String InheritFlag = "inheritFlag"; - internal const String UseVsidSubjects = "useVsidSubjects"; - - //Profile query parameters - internal const String Size = "size"; - internal const String ModifiedSince = "modifiedsince"; - internal const String ModifiedAfterRevision = "modifiedafterrevision"; - internal const String Partition = "partition"; - internal const String Details = "details"; - internal const String WithCoreAttributes = "withcoreattributes"; - internal const String CoreAttributes = "coreattributes"; - internal const String ProfilePageType = "profilePageType"; - internal const String IpAddress = "ipaddress"; - - //ClinetNotification query parameters - internal const String ClientId = "clientId"; - - //File container query parameters - internal const String ArtifactUris = "artifactUris"; - internal const String ScopeIdentifier = "scope"; - internal const String ItemPath = "itemPath"; - internal const String includeDownloadTickets = "includeDownloadTickets"; - internal const String isShallow = "isShallow"; - - //Telemetry query parameters for Licensing - internal const String TelemetryPrefix = "t-"; - - } - - public static class IdentityMruRestApiConstants - { - public const String Add = "add"; - public const String Remove = "remove"; - public const String Update = "update"; - public const String Me = "me"; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static class ProfileRestApiConstants - { - public const String Me = "me"; - public const String Value = "value"; - } - - public static class UserRestApiConstants - { - public const String Me = "me"; - public const string JsonMergePatchMediaType = "application/merge-patch+json"; - } - - public static class CustomHttpResponseHeaders - { - public const string ActivityId = "ActivityId"; - } - - public static class ExtensionManagementConstants - { - public const string Me = "me"; - } -} diff --git a/src/Sdk/WebApi/WebApi/HttpClients/FileContainerHttpClient.cs b/src/Sdk/WebApi/WebApi/HttpClients/FileContainerHttpClient.cs deleted file mode 100644 index 57202de4e..000000000 --- a/src/Sdk/WebApi/WebApi/HttpClients/FileContainerHttpClient.cs +++ /dev/null @@ -1,719 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.FileContainer.Client -{ - // until we figure out the TFS location service story for REST apis, we leave the serviceDefinition attribute off the class - //[ServiceDefinition(ServiceInterfaces.FileContainerResource, ServiceIdentifiers.FileContainerResource)] - public class FileContainerHttpClient : VssHttpClientBase - { - public event EventHandler UploadFileReportTrace; - public event EventHandler UploadFileReportProgress; - - static FileContainerHttpClient() - { - s_translatedExceptions = new Dictionary(); - s_translatedExceptions.Add("ArtifactUriNotSupportedException", typeof(ArtifactUriNotSupportedException)); - s_translatedExceptions.Add("ContainerAlreadyExistsException", typeof(ContainerAlreadyExistsException)); - s_translatedExceptions.Add("ContainerItemCopyDuplicateTargetsException", typeof(ContainerItemCopyDuplicateTargetsException)); - s_translatedExceptions.Add("ContainerItemCopySourcePendingUploadException", typeof(ContainerItemCopySourcePendingUploadException)); - s_translatedExceptions.Add("ContainerItemCopyTargetChildOfSourceException", typeof(ContainerItemCopyTargetChildOfSourceException)); - s_translatedExceptions.Add("ContainerItemExistsException", typeof(ContainerItemExistsException)); - s_translatedExceptions.Add("ContainerItemNotFoundException", typeof(ContainerItemNotFoundException)); - s_translatedExceptions.Add("ContainerNoContentException", typeof(ContainerNoContentException)); - s_translatedExceptions.Add("ContainerNotFoundException", typeof(ContainerNotFoundException)); - s_translatedExceptions.Add("ContainerUnexpectedContentTypeException", typeof(ContainerUnexpectedContentTypeException)); - s_translatedExceptions.Add("ContainerWriteAccessDeniedException", typeof(ContainerWriteAccessDeniedException)); - s_translatedExceptions.Add("PendingUploadNotFoundException", typeof(PendingUploadNotFoundException)); - - s_currentApiVersion = new ApiResourceVersion(1.0, 4); - } - - public FileContainerHttpClient(Uri baseUrl, VssCredentials credentials) - : base(baseUrl, credentials) - { - } - - public FileContainerHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings) - : base(baseUrl, credentials, settings) - { - } - - public FileContainerHttpClient(Uri baseUrl, VssCredentials credentials, params DelegatingHandler[] handlers) - : base(baseUrl, credentials, handlers) - { - } - - public FileContainerHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings, params DelegatingHandler[] handlers) - : base(baseUrl, credentials, settings, handlers) - { - } - - public FileContainerHttpClient(Uri baseUrl, HttpMessageHandler pipeline, bool disposeHandler) - : base(baseUrl, pipeline, disposeHandler) - { - } - - /// - /// Queries for file containers - /// - /// List of artifact uris associated with containers. If empty or null will return all containers. - /// - /// - public Task> QueryContainersAsync(List artifactUris, Guid scopeIdentifier, Object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - List> query = AppendContainerQueryString(artifactUris, scopeIdentifier); - return SendAsync>(HttpMethod.Get, FileContainerResourceIds.FileContainer, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Queries for container items in a container. - /// - /// Id of the container to query. - /// Id of the scope to query - /// Path to folder or file. Can be empty or null to query from container root. - /// User state - /// Whether to include download ticket(s) for the container item(s) in the result - /// CancellationToken to cancel the task - /// - public Task> QueryContainerItemsAsync(Int64 containerId, Guid scopeIdentifier, String itemPath = null, Object userState = null, Boolean includeDownloadTickets = false, CancellationToken cancellationToken = default(CancellationToken)) - { - return QueryContainerItemsAsync(containerId, scopeIdentifier, false, itemPath, userState, includeDownloadTickets, cancellationToken); - } - - /// - /// Queries for container items in a container. - /// - /// Id of the container to query. - /// Id of the scope to query - /// Whether to just return immediate children items under the itemPath - /// Path to folder or file. Can be empty or null to query from container root. - /// User state - /// Whether to include download ticket(s) for the container item(s) in the result - /// CancellationToken to cancel the task - public Task> QueryContainerItemsAsync(Int64 containerId, Guid scopeIdentifier, Boolean isShallow, String itemPath = null, Object userState = null, Boolean includeDownloadTickets = false, CancellationToken cancellationToken = default(CancellationToken)) - { - if (containerId < 1) - { - throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId"); - } - - List> query = AppendItemQueryString(itemPath, scopeIdentifier, includeDownloadTickets, isShallow); - return SendAsync>(HttpMethod.Get, FileContainerResourceIds.FileContainer, routeValues: new { containerId = containerId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Uploads a file in chunks to the specified uri. - /// - /// Stream to upload. - /// CancellationToken to cancel the task - /// Http response message. - public async Task UploadFileAsync( - Int64 containerId, - String itemPath, - Stream fileStream, - Guid scopeIdentifier, - CancellationToken cancellationToken = default(CancellationToken), - int chunkSize = c_defaultChunkSize, - bool uploadFirstChunk = false, - Object userState = null, - Boolean compressStream = true) - { - if (containerId < 1) - { - throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId"); - } - - ArgumentUtility.CheckForNull(fileStream, "fileStream"); - - if (fileStream.Length == 0) - { - HttpRequestMessage requestMessage; - List> query = AppendItemQueryString(itemPath, scopeIdentifier); - - // zero byte upload - requestMessage = await CreateRequestMessageAsync(HttpMethod.Put, FileContainerResourceIds.FileContainer, routeValues: new { containerId = containerId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false); - } - - ApiResourceVersion gzipSupportedVersion = new ApiResourceVersion(new Version(1, 0), 2); - ApiResourceVersion requestVersion = await NegotiateRequestVersionAsync(FileContainerResourceIds.FileContainer, s_currentApiVersion, userState, cancellationToken: cancellationToken).ConfigureAwait(false); - - if (compressStream - && (requestVersion.ApiVersion < gzipSupportedVersion.ApiVersion - || (requestVersion.ApiVersion == gzipSupportedVersion.ApiVersion && requestVersion.ResourceVersion < gzipSupportedVersion.ResourceVersion))) - { - compressStream = false; - } - - Stream streamToUpload = fileStream; - Boolean gzipped = false; - long filelength = fileStream.Length; - - try - { - if (compressStream) - { - if (filelength > 65535) // if file greater than 64K use a file - { - String tempFile = Path.GetTempFileName(); - streamToUpload = File.Create(tempFile, 32768, FileOptions.DeleteOnClose | FileOptions.Asynchronous); - } - else - { - streamToUpload = new MemoryStream((int)filelength + 8); - } - - using (GZipStream zippedStream = new GZipStream(streamToUpload, CompressionMode.Compress, true)) - { - await fileStream.CopyToAsync(zippedStream).ConfigureAwait(false); - } - - if (streamToUpload.Length >= filelength) - { - // compression did not help - streamToUpload.Dispose(); - streamToUpload = fileStream; - } - else - { - gzipped = true; - } - - streamToUpload.Seek(0, SeekOrigin.Begin); - } - - return await UploadFileAsync(containerId, itemPath, streamToUpload, null, filelength, gzipped, scopeIdentifier, cancellationToken, chunkSize, uploadFirstChunk: uploadFirstChunk, userState: userState); - } - finally - { - if (gzipped && streamToUpload != null) - { - streamToUpload.Dispose(); - } - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public async Task UploadFileAsync( - Int64 containerId, - String itemPath, - Stream fileStream, - byte[] contentId, - Int64 fileLength, - Boolean isGzipped, - Guid scopeIdentifier, - CancellationToken cancellationToken = default(CancellationToken), - int chunkSize = c_defaultChunkSize, - int chunkRetryTimes = c_defaultChunkRetryTimes, - bool uploadFirstChunk = false, - Object userState = null) - { - if (containerId < 1) - { - throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId"); - } - - if (chunkSize > c_maxChunkSize) - { - chunkSize = c_maxChunkSize; - } - - // if a contentId is specified but the chunk size is not a 2mb multiple error - if (contentId != null && (chunkSize % c_ContentChunkMultiple) != 0) - { - throw new ArgumentException(FileContainerResources.ChunksizeWrongWithContentId(c_ContentChunkMultiple), "chunkSize"); - } - - ArgumentUtility.CheckForNull(fileStream, "fileStream"); - - ApiResourceVersion gzipSupportedVersion = new ApiResourceVersion(new Version(1, 0), 2); - ApiResourceVersion requestVersion = await NegotiateRequestVersionAsync(FileContainerResourceIds.FileContainer, s_currentApiVersion, userState, cancellationToken).ConfigureAwait(false); - - if (isGzipped - && (requestVersion.ApiVersion < gzipSupportedVersion.ApiVersion - || (requestVersion.ApiVersion == gzipSupportedVersion.ApiVersion && requestVersion.ResourceVersion < gzipSupportedVersion.ResourceVersion))) - { - throw new ArgumentException(FileContainerResources.GzipNotSupportedOnServer(), "isGzipped"); - } - - if (isGzipped && fileStream.Length >= fileLength) - { - throw new ArgumentException(FileContainerResources.BadCompression(), "fileLength"); - } - - HttpRequestMessage requestMessage = null; - List> query = AppendItemQueryString(itemPath, scopeIdentifier); - - if (fileStream.Length == 0) - { - // zero byte upload - FileUploadTrace(itemPath, $"Upload zero byte file '{itemPath}'."); - requestMessage = await CreateRequestMessageAsync(HttpMethod.Put, FileContainerResourceIds.FileContainer, routeValues: new { containerId = containerId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false); - } - - bool multiChunk = false; - int totalChunks = 1; - if (fileStream.Length > chunkSize) - { - totalChunks = (int)Math.Ceiling(fileStream.Length / (double)chunkSize); - FileUploadTrace(itemPath, $"Begin chunking upload file '{itemPath}', chunk size '{chunkSize} Bytes', total chunks '{totalChunks}'."); - multiChunk = true; - } - else - { - FileUploadTrace(itemPath, $"File '{itemPath}' will be uploaded in one chunk."); - chunkSize = (int)fileStream.Length; - } - - StreamParser streamParser = new StreamParser(fileStream, chunkSize); - SubStream currentStream = streamParser.GetNextStream(); - HttpResponseMessage response = null; - - Byte[] dataToSend = new Byte[chunkSize]; - int currentChunk = 0; - Stopwatch uploadTimer = new Stopwatch(); - while (currentStream.Length > 0 && !cancellationToken.IsCancellationRequested) - { - currentChunk++; - - for (int attempt = 1; attempt <= chunkRetryTimes && !cancellationToken.IsCancellationRequested; attempt++) - { - if (attempt > 1) - { - TimeSpan backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10)); - FileUploadTrace(itemPath, $"Backoff {backoff.TotalSeconds} seconds before attempt '{attempt}' chunk '{currentChunk}' of file '{itemPath}'."); - await Task.Delay(backoff, cancellationToken).ConfigureAwait(false); - currentStream.Seek(0, SeekOrigin.Begin); - } - - FileUploadTrace(itemPath, $"Attempt '{attempt}' for uploading chunk '{currentChunk}' of file '{itemPath}'."); - - // inorder for the upload to be retryable, we need the content to be re-readable - // to ensure this we copy the chunk into a byte array and send that - // chunk size ensures we can convert the length to an int - int bytesToCopy = (int)currentStream.Length; - using (MemoryStream ms = new MemoryStream(dataToSend)) - { - await currentStream.CopyToAsync(ms, bytesToCopy, cancellationToken).ConfigureAwait(false); - } - - // set the content and the Content-Range header - HttpContent byteArrayContent = new ByteArrayContent(dataToSend, 0, bytesToCopy); - byteArrayContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); - byteArrayContent.Headers.ContentLength = currentStream.Length; - byteArrayContent.Headers.ContentRange = new System.Net.Http.Headers.ContentRangeHeaderValue(currentStream.StartingPostionOnOuterStream, - currentStream.EndingPostionOnOuterStream, - streamParser.Length); - FileUploadTrace(itemPath, $"Generate new HttpRequest for uploading file '{itemPath}', chunk '{currentChunk}' of '{totalChunks}'."); - - try - { - if (requestMessage != null) - { - requestMessage.Dispose(); - requestMessage = null; - } - - requestMessage = await CreateRequestMessageAsync( - HttpMethod.Put, - FileContainerResourceIds.FileContainer, - routeValues: new { containerId = containerId }, - version: s_currentApiVersion, - content: byteArrayContent, - queryParameters: query, - userState: userState, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) - { - // stop re-try on cancellation. - throw; - } - catch (Exception ex) when (attempt < chunkRetryTimes) // not the last attempt - { - FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' fail to create HttpRequest. Error: {ex.ToString()}."); - continue; - } - - if (isGzipped) - { - //add gzip header info - byteArrayContent.Headers.ContentEncoding.Add("gzip"); - byteArrayContent.Headers.Add("x-tfs-filelength", fileLength.ToString(System.Globalization.CultureInfo.InvariantCulture)); - } - - if (contentId != null) - { - byteArrayContent.Headers.Add("x-vso-contentId", Convert.ToBase64String(contentId)); // Base64FormattingOptions.None is default when not supplied - } - - FileUploadTrace(itemPath, $"Start uploading file '{itemPath}' to server, chunk '{currentChunk}'."); - uploadTimer.Restart(); - - try - { - if (response != null) - { - response.Dispose(); - response = null; - } - - response = await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) - { - // stop re-try on cancellation. - throw; - } - catch (Exception ex) when (attempt < chunkRetryTimes) // not the last attempt - { - FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' fail to send request to server. Error: {ex.ToString()}."); - continue; - } - - uploadTimer.Stop(); - FileUploadTrace(itemPath, $"Finished upload chunk '{currentChunk}' of file '{itemPath}', elapsed {uploadTimer.ElapsedMilliseconds} (ms), response code '{response.StatusCode}'."); - - if (multiChunk) - { - FileUploadProgress(itemPath, currentChunk, (int)Math.Ceiling(fileStream.Length / (double)chunkSize)); - } - - if (response.IsSuccessStatusCode) - { - break; - } - else if (IsFastFailResponse(response)) - { - FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request and cannot continue."); - break; - } - else - { - FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request."); - continue; - } - } - - // if we don't have success then bail and return the failed response - if (!response.IsSuccessStatusCode) - { - break; - } - - if (contentId != null && response.StatusCode == HttpStatusCode.Created) - { - // no need to keep uploading since the server said it has all the content - FileUploadTrace(itemPath, $"Stop chunking upload the rest of the file '{itemPath}', since server already has all the content."); - break; - } - - currentStream = streamParser.GetNextStream(); - if (uploadFirstChunk) - { - break; - } - } - - cancellationToken.ThrowIfCancellationRequested(); - - return response; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public async Task> CreateItemsAsync( - Int64 containerId, - List items, - Guid scopeIdentifier, - CancellationToken cancellationToken = default(CancellationToken), - Object userState = null) - { - List updatedItems = items.Select(x => { x.ContainerId = containerId; x.Status = ContainerItemStatus.PendingUpload; return x; }).ToList(); - - try - { - return await PostAsync, List>( - updatedItems, - FileContainerResourceIds.FileContainer, - routeValues: new { containerId = containerId, scopeIdentifier = scopeIdentifier }, - version: s_currentApiVersion, - userState: userState, - cancellationToken: cancellationToken); - } - catch (Exception) - { - //eat until versioning works in options request - return updatedItems; - } - } - - // for back compat with internal use - [EditorBrowsable(EditorBrowsableState.Never)] - public Task UploadFileToTfsAsync( - Int64 containerId, - String itemPath, - Stream fileStream, - Guid scopeIdentifier, - CancellationToken cancellationToken, - int chunkSize = c_defaultChunkSize, - bool uploadFirstChunk = false, - Object userState = null) - { - return UploadFileAsync(containerId, itemPath, fileStream, scopeIdentifier, cancellationToken, chunkSize, uploadFirstChunk, userState); - } - - /// - /// Download a file from the specified container. - /// - /// - /// - /// - /// - /// A stream of the file content. - public Task DownloadFileAsync( - Int64 containerId, - String itemPath, - CancellationToken cancellationToken, - Guid scopeIdentifier, - Object userState = null) - { - return DownloadAsync(containerId, itemPath, "application/octet-stream", cancellationToken, scopeIdentifier, userState); - } - - /// - /// Download a file or folder as a zip file. - /// - /// - /// - /// - /// - /// A stream of the zip file. - public Task DownloadItemAsZipAsync( - Int64 containerId, - String itemPath, - CancellationToken cancellationToken, - Guid scopeIdentifier, - Object userState = null) - { - return DownloadAsync(containerId, itemPath, "application/zip", cancellationToken, scopeIdentifier, userState); - } - - /// - /// Delete a container item - /// - /// - /// - /// - /// - /// - public Task DeleteContainerItem( - Int64 containerId, - String itemPath, - Guid scopeIdentifier, - CancellationToken cancellationToken = default(CancellationToken), - Object userState = null) - { - if (containerId < 1) - { - throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId"); - } - - List> query = AppendItemQueryString(itemPath, scopeIdentifier); - - return DeleteAsync( - FileContainerResourceIds.FileContainer, - new { containerId = containerId }, - s_currentApiVersion, - query, - userState, - cancellationToken); - } - - public bool IsFastFailResponse(HttpResponseMessage response) - { - int statusCode = (int)response?.StatusCode; - return statusCode >= 400 && statusCode <= 499; - } - - protected override bool ShouldThrowError(HttpResponseMessage response) - { - return !response.IsSuccessStatusCode && !IsFastFailResponse(response); - } - - private async Task ContainerGetRequestAsync( - Int64 containerId, - String itemPath, - String contentType, - CancellationToken cancellationToken, - Guid scopeIdentifier, - Object userState = null) - { - if (containerId < 1) - { - throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId"); - } - - List> query = AppendItemQueryString(itemPath, scopeIdentifier); - HttpRequestMessage requestMessage = await CreateRequestMessageAsync(HttpMethod.Get, FileContainerResourceIds.FileContainer, routeValues: new { containerId = containerId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - - if (!String.IsNullOrEmpty(contentType)) - { - requestMessage.Headers.Accept.Clear(); - var header = new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue(contentType); - header.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue(ApiResourceVersionExtensions.c_apiVersionHeaderKey, "1.0")); - header.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue(ApiResourceVersionExtensions.c_legacyResourceVersionHeaderKey, "1")); - requestMessage.Headers.Accept.Add(header); - } - - return await SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, userState, cancellationToken).ConfigureAwait(false); - } - - private List> AppendContainerQueryString(List artifactUris, Guid scopeIdentifier) - { - List> collection = new List>(); - - if (artifactUris != null && artifactUris.Count > 0) - { - String artifactsString = String.Join(",", artifactUris.Select(x => x.AbsoluteUri)); - collection.Add(QueryParameters.ArtifactUris, artifactsString); - } - - collection.Add(QueryParameters.ScopeIdentifier, scopeIdentifier.ToString()); - - return collection; - } - - private List> AppendItemQueryString(String itemPath, Guid scopeIdentifier, Boolean includeDownloadTickets = false, Boolean isShallow = false) - { - List> collection = new List>(); - - if (!String.IsNullOrEmpty(itemPath)) - { - itemPath = FileContainerItem.EnsurePathFormat(itemPath); - collection.Add(QueryParameters.ItemPath, itemPath); - } - - if (includeDownloadTickets) - { - collection.Add(QueryParameters.includeDownloadTickets, "true"); - } - - if (isShallow) - { - collection.Add(QueryParameters.isShallow, "true"); - } - - collection.Add(QueryParameters.ScopeIdentifier, scopeIdentifier.ToString()); - - return collection; - } - - private async Task DownloadAsync( - Int64 containerId, - String itemPath, - String contentType, - CancellationToken cancellationToken, - Guid scopeIdentifier, - Object userState = null) - { - HttpResponseMessage response = await ContainerGetRequestAsync(containerId, itemPath, contentType, cancellationToken, scopeIdentifier, userState).ConfigureAwait(false); - - response.EnsureSuccessStatusCode(); - - if (response.StatusCode == HttpStatusCode.NoContent) - { - throw new ContainerNoContentException(); - } - - if (VssStringComparer.ContentType.Equals(response.Content.Headers.ContentType.MediaType, contentType)) - { - if (response.Content.Headers.ContentEncoding.Contains("gzip", StringComparer.OrdinalIgnoreCase)) - { - return new GZipStream(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), CompressionMode.Decompress); - } - else - { - return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); - } - } - else - { - throw new ContainerUnexpectedContentTypeException(contentType, response.Content.Headers.ContentType.MediaType); - } - } - - private void FileUploadTrace(string file, string message) - { - if (UploadFileReportTrace != null) - { - UploadFileReportTrace(this, new ReportTraceEventArgs(file, message)); - } - } - - private void FileUploadProgress(string file, int currentChunk, int totalChunks) - { - if (UploadFileReportProgress != null) - { - UploadFileReportProgress(this, new ReportProgressEventArgs(file, currentChunk, totalChunks)); - } - } - - /// - /// Exceptions for file container errors - /// - protected override IDictionary TranslatedExceptions - { - get - { - return s_translatedExceptions; - } - } - - private const int c_defaultChunkSize = 8 * 1024 * 1024; - private const int c_defaultChunkRetryTimes = 3; - private const int c_maxChunkSize = 24 * 1024 * 1024; - private const int c_ContentChunkMultiple = 2 * 1024 * 1024; - private static Dictionary s_translatedExceptions; - private static readonly ApiResourceVersion s_currentApiVersion; - } - - public class ReportTraceEventArgs : EventArgs - { - public ReportTraceEventArgs(String file, String message) - { - File = file; - Message = message; - } - - public String File { get; private set; } - public String Message { get; private set; } - } - - public class ReportProgressEventArgs : EventArgs - { - public ReportProgressEventArgs(String file, int currentChunk, int totalChunks) - { - File = file; - CurrentChunk = currentChunk; - TotalChunks = totalChunks; - } - - public String File { get; private set; } - public int CurrentChunk { get; private set; } - public int TotalChunks { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/HttpClients/IdentityHttpClient.cs b/src/Sdk/WebApi/WebApi/HttpClients/IdentityHttpClient.cs deleted file mode 100644 index e63aea129..000000000 --- a/src/Sdk/WebApi/WebApi/HttpClients/IdentityHttpClient.cs +++ /dev/null @@ -1,1167 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.DelegatedAuthorization; -using GitHub.Services.WebApi; -using GitHub.Services.WebApi.Exceptions; -using GitHub.Services.Common.Internal; -using System.Linq; -using GitHub.Services.WebApi.Patch.Json; - -namespace GitHub.Services.Identity.Client -{ - [ResourceArea(IdentityResourceIds.AreaId)] - [ClientCircuitBreakerSettings(timeoutSeconds: 100, failurePercentage:80, MaxConcurrentRequests = 110)] - public class IdentityHttpClient : VssHttpClientBase - { - static IdentityHttpClient() - { - s_translatedExceptions = new Dictionary(); - - // 400 (Bad Request) - s_translatedExceptions.Add("IdentityDomainMismatchException", typeof(IdentityDomainMismatchException)); - s_translatedExceptions.Add("AddMemberCyclicMembershipException", typeof(AddMemberCyclicMembershipException)); - s_translatedExceptions.Add("IdentityPropertyRequiredException", typeof(IdentityPropertyRequiredException)); - s_translatedExceptions.Add("IdentityExpressionException", typeof(IdentityExpressionException)); - s_translatedExceptions.Add("InvalidDisplayNameException", typeof(InvalidDisplayNameException)); - s_translatedExceptions.Add("GroupNameNotRecognizedException", typeof(GroupNameNotRecognizedException)); - s_translatedExceptions.Add("IdentityMapReadOnlyException", typeof(IdentityMapReadOnlyException)); - s_translatedExceptions.Add("IdentityNotServiceIdentityException", typeof(IdentityNotServiceIdentityException)); - s_translatedExceptions.Add("InvalidServiceIdentityNameException", typeof(InvalidServiceIdentityNameException)); - s_translatedExceptions.Add("IllegalIdentityException", typeof(IllegalIdentityException)); - s_translatedExceptions.Add("MissingRequiredParameterException", typeof(MissingRequiredParameterException)); - s_translatedExceptions.Add("IncompatibleScopeException", typeof(IncompatibleScopeException)); - - // 403 (Forbidden) - s_translatedExceptions.Add("RemoveAccountOwnerFromAdminGroupException", typeof(RemoveAccountOwnerFromAdminGroupException)); - s_translatedExceptions.Add("RemoveSelfFromAdminGroupException", typeof(RemoveSelfFromAdminGroupException)); - s_translatedExceptions.Add("AddGroupMemberIllegalMemberException", typeof(AddGroupMemberIllegalMemberException)); - s_translatedExceptions.Add("AddGroupMemberIllegalWindowsIdentityException", typeof(AddGroupMemberIllegalWindowsIdentityException)); - s_translatedExceptions.Add("AddGroupMemberIllegalInternetIdentityException", typeof(AddGroupMemberIllegalInternetIdentityException)); - s_translatedExceptions.Add("RemoveSpecialGroupException", typeof(RemoveSpecialGroupException)); - s_translatedExceptions.Add("NotApplicationGroupException", typeof(NotApplicationGroupException)); - s_translatedExceptions.Add("ModifyEveryoneGroupException", typeof(ModifyEveryoneGroupException)); - s_translatedExceptions.Add("NotASecurityGroupException", typeof(NotASecurityGroupException)); - s_translatedExceptions.Add("RemoveMemberServiceAccountException", typeof(RemoveMemberServiceAccountException)); - s_translatedExceptions.Add("AccountPreferencesAlreadyExistException", typeof(AccountPreferencesAlreadyExistException)); - - // 404 (NotFound) - s_translatedExceptions.Add("RemoveGroupMemberNotMemberException", typeof(RemoveGroupMemberNotMemberException)); - s_translatedExceptions.Add("RemoveNonexistentGroupException", typeof(RemoveNonexistentGroupException)); - s_translatedExceptions.Add("FindGroupSidDoesNotExistException", typeof(FindGroupSidDoesNotExistException)); - s_translatedExceptions.Add("GroupScopeDoesNotExistException", typeof(GroupScopeDoesNotExistException)); - s_translatedExceptions.Add("IdentityNotFoundException", typeof(IdentityNotFoundException)); - - // 409 (Conflict) - s_translatedExceptions.Add("GroupCreationException", typeof(GroupCreationException)); - s_translatedExceptions.Add("GroupScopeCreationException", typeof(GroupScopeCreationException)); - s_translatedExceptions.Add("AddMemberIdentityAlreadyMemberException", typeof(AddMemberIdentityAlreadyMemberException)); - s_translatedExceptions.Add("GroupRenameException", typeof(GroupRenameException)); - s_translatedExceptions.Add("IdentityAlreadyExistsException", typeof(IdentityAlreadyExistsException)); - s_translatedExceptions.Add("IdentityAccountNameAlreadyInUseException", typeof(IdentityAccountNameAlreadyInUseException)); - s_translatedExceptions.Add("IdentityAliasAlreadyInUseException", typeof(IdentityAliasAlreadyInUseException)); - s_translatedExceptions.Add("AddProjectGroupProjectMismatchException", typeof(AddProjectGroupProjectMismatchException)); - - // 500 (InternalServerError) - s_translatedExceptions.Add("IdentitySyncException", typeof(IdentitySyncException)); - - // 503 (ServiceUnavailable) - s_translatedExceptions.Add("IdentityProviderUnavailableException", typeof(IdentityProviderUnavailableException)); - - s_currentApiVersion = new ApiResourceVersion(1.0); - } - - public IdentityHttpClient(Uri baseUrl, VssCredentials credentials) - : base(baseUrl, credentials) - { - } - - public IdentityHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings) - : base(baseUrl, credentials, settings) - { - } - - public IdentityHttpClient(Uri baseUrl, VssCredentials credentials, params DelegatingHandler[] handlers) - : base(baseUrl, credentials, handlers) - { - } - - public IdentityHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings, params DelegatingHandler[] handlers) - : base(baseUrl, credentials, settings, handlers) - { - } - - public IdentityHttpClient(Uri baseUrl, HttpMessageHandler pipeline, bool disposeHandler) - : base(baseUrl, pipeline, disposeHandler) - { - } - - #region Operations on Identities Controller - #region ReadIdentities overloads - /// - /// Reads all identities - /// - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public Task ReadIdentitiesAsync( - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - var queryParams = new List>(); - - return ReadIdentitiesAsyncInternal(queryParams, queryMembership, propertyNameFilters, includeRestrictedVisibility, requestHeadersContext: null, userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Returns identities matching the passed in descriptors - /// - /// List of IdentityDescriptors to query for. - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public virtual Task ReadIdentitiesAsync( - IList descriptors, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return ReadIdentitiesAsync(descriptors, requestHeadersContext: null, queryMembership: queryMembership, - propertyNameFilters: propertyNameFilters, includeRestrictedVisibility: includeRestrictedVisibility, - userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Returns identities matching the passed in descriptors - /// - /// List of IdentityDescriptors to query for. - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public virtual Task ReadIdentitiesAsync( - IList descriptors, - RequestHeadersContext requestHeadersContext, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(descriptors, "descriptors"); - - if (descriptors.Count > maxDescriptors) - { - return ReadIdentitiesBatchAsyncInternal( - descriptors, - queryMembership, - propertyNameFilters, - includeRestrictedVisibility, - requestHeadersContext, - userState, cancellationToken); - } - else - { - var pages = new List>(); - - pages.AddMultiple(QueryParameters.Descriptors, descriptors, SerializeDescriptor); - - return ReadIdentitiesAsyncInternal(pages, queryMembership, propertyNameFilters, includeRestrictedVisibility, requestHeadersContext, userState, cancellationToken); - } - } - - /// - /// Returns identities matching the passed in subject descriptors - /// - /// List of SocialDescriptors to query for. - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public virtual Task ReadIdentitiesAsync( - IList socialDescriptors, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return ReadIdentitiesAsync(socialDescriptors, requestHeadersContext: null, queryMembership: queryMembership, - propertyNameFilters: propertyNameFilters, includeRestrictedVisibility: includeRestrictedVisibility, - userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Returns identities matching the passed in descriptors - /// - /// List of SubjectDescriptors to query for. - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - internal virtual Task ReadIdentitiesAsync( - IList socialDescriptors, - RequestHeadersContext requestHeadersContext, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(socialDescriptors, nameof(socialDescriptors)); - - if (socialDescriptors.Count > maxDescriptors) - { - return ReadIdentitiesBatchAsyncInternal( - socialDescriptors, - queryMembership, - propertyNameFilters, - includeRestrictedVisibility, - requestHeadersContext, - userState, cancellationToken); - } - else - { - var pages = new List>(); - - pages.AddMultiple(QueryParameters.SocialDescriptors, socialDescriptors.Select(descriptor => descriptor.ToString()).ToList()); - - return ReadIdentitiesAsyncInternal(pages, queryMembership, propertyNameFilters, includeRestrictedVisibility, requestHeadersContext, userState, cancellationToken); - } - } - - /// - /// Returns identities matching the passed in subject descriptors - /// - /// List of SubjectDescriptors to query for. - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public virtual Task ReadIdentitiesAsync( - IList subjectDescriptors, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return ReadIdentitiesAsync(subjectDescriptors, requestHeadersContext: null, queryMembership: queryMembership, - propertyNameFilters: propertyNameFilters, includeRestrictedVisibility: includeRestrictedVisibility, - userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Returns identities matching the passed in descriptors - /// - /// List of SubjectDescriptors to query for. - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - internal virtual Task ReadIdentitiesAsync( - IList subjectDescriptors, - RequestHeadersContext requestHeadersContext, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(subjectDescriptors, nameof(subjectDescriptors)); - - if (subjectDescriptors.Count > maxDescriptors) - { - return ReadIdentitiesBatchAsyncInternal( - subjectDescriptors, - queryMembership, - propertyNameFilters, - includeRestrictedVisibility, - requestHeadersContext, - userState, cancellationToken); - } - else - { - var pages = new List>(); - - pages.AddMultiple(QueryParameters.SubjectDescriptors, subjectDescriptors.Select(descriptor => descriptor.ToString()).ToList()); - - return ReadIdentitiesAsyncInternal(pages, queryMembership, propertyNameFilters, includeRestrictedVisibility, requestHeadersContext, userState, cancellationToken); - } - } - - /// - /// Returns identities matching the passed in identifiers - /// - /// Guids representing unique identifiers for the identities - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public virtual Task ReadIdentitiesAsync( - IList identityIds, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return ReadIdentitiesAsync(identityIds, requestHeadersContext: null, queryMembership: queryMembership, - propertyNameFilters: propertyNameFilters, includeRestrictedVisibility: includeRestrictedVisibility, - userState: userState, cancellationToken: cancellationToken); - } - - /// - /// Returns identities matching the passed in identifiers - /// - /// Guids representing unique identifiers for the identities - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - internal virtual Task ReadIdentitiesAsync( - IList identityIds, - RequestHeadersContext requestHeadersContext, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - bool includeRestrictedVisibility = false, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(identityIds, "identityIds"); - - if (identityIds.Count > maxIds) - { - return ReadIdentitiesBatchAsyncInternal( - identityIds, - queryMembership, - propertyNameFilters, - includeRestrictedVisibility, - userState, - requestHeadersContext, - cancellationToken); - } - else - { - var pages = new List>(); - - pages.AddMultiple(QueryParameters.IdentityIds, identityIds, (id) => id.ToString("N")); - - return ReadIdentitiesAsyncInternal(pages, queryMembership, propertyNameFilters, includeRestrictedVisibility, requestHeadersContext, userState, cancellationToken); - } - } - - public Task ReadIdentitiesAsync( - IdentitySearchFilter searchFilter, - string filterValue, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return ReadIdentitiesAsync(searchFilter, filterValue, ReadIdentitiesOptions.None, queryMembership, propertyNameFilters, userState, cancellationToken); - } - - /// - /// Returns identities matching the requested search factor and value - /// - /// - /// - /// Instructs the server whether to query for membership information. - /// Instructs the server which extended properties to query for. - /// Additional client state passed by caller. - /// A Task which when complete, contains the list of identities. - public virtual Task ReadIdentitiesAsync( - IdentitySearchFilter searchFilter, - string filterValue, - ReadIdentitiesOptions options, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckStringForNullOrEmpty(filterValue, "filterValue"); - - List> searchQuery = new List>(); - - searchQuery.Add(QueryParameters.SearchFilter, searchFilter.ToString()); - searchQuery.Add(QueryParameters.FilterValue, filterValue); - searchQuery.Add(QueryParameters.ReadIdentitiesOptions, options.ToString()); - - return ReadIdentitiesAsyncInternal(searchQuery, queryMembership, propertyNameFilters, includeRestrictedVisibility: false, requestHeadersContext: null, userState: userState, cancellationToken: cancellationToken); - } - - public virtual Task ReadIdentitiesAsync( - Guid scopeId, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - var query = new List>(); - query.Add(QueryParameters.ScopeId, scopeId.ToString("N")); - - return ReadIdentitiesAsyncInternal(query, queryMembership, propertyNameFilters, includeRestrictedVisibility: false, requestHeadersContext: null, userState: userState, cancellationToken: cancellationToken); - } - #endregion - - #region ReadIdentity overloads - public Task ReadIdentityAsync( - string identityPuid, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckStringForNullOrEmpty(identityPuid, "identityPuid"); - - return ReadIdentityAsyncInternal( - identityPuid, - queryMembership, - propertyNameFilters, - userState, cancellationToken); - } - - public Task ReadIdentityAsync( - Guid identityId, - QueryMembership queryMembership = QueryMembership.None, - IEnumerable propertyNameFilters = null, - object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckForEmptyGuid(identityId, "identityId"); - - return ReadIdentityAsyncInternal( - identityId.ToString("D"), - queryMembership, - propertyNameFilters, - userState, cancellationToken); - } - #endregion - - public async Task> UpdateIdentitiesAsync(IList identities, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "UpdateIdentities")) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(identities, "identities"); - - IdentitiesCollection collection = new IdentitiesCollection(identities); - HttpContent content = new ObjectContent>(new VssJsonCollectionWrapper(collection), base.Formatter); - - return await SendAsync>(HttpMethod.Put, IdentityResourceIds.Identity, version: s_currentApiVersion, content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task UpdateIdentityAsync(Identity identity, object userState, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "UpdateIdentity")) - { - ArgumentUtility.CheckForNull(identity, "identity"); - - HttpContent content = new ObjectContent(identity, base.Formatter); - return await SendAsync(HttpMethod.Put, IdentityResourceIds.Identity, new { identityId = identity.Id }, s_currentApiVersion, content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task SwapIdentityAsync(Guid id1, Guid id2, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "SwapIdentity")) - { - ArgumentUtility.CheckForEmptyGuid(id1, "id1"); - ArgumentUtility.CheckForEmptyGuid(id2, "id2"); - - HttpContent content = new ObjectContent(typeof(SwapIdentityInfo), new SwapIdentityInfo(id1, id2), this.Formatter); - - return await SendAsync(HttpMethod.Post, IdentityResourceIds.SwapLocationId, version: s_currentApiVersion, content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - //REST USAGE NON-STANDARD: Get operations on the same endpoint should return the same resources. This is a different - //resource. - public async Task GetIdentityChangesAsync(int identitySequenceId, int groupSequenceId, Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - int unspecifiedSequenceId = -1; - return await this.GetIdentityChangesAsync(identitySequenceId, groupSequenceId, unspecifiedSequenceId, scopeId, userState, cancellationToken).ConfigureAwait(false); - } - - public async Task GetIdentityChangesAsync(int identitySequenceId, int groupSequenceId, int organizationIdentitySequenceId, Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return await this.GetIdentityChangesAsync(identitySequenceId, groupSequenceId, organizationIdentitySequenceId, 0, scopeId, userState, cancellationToken).ConfigureAwait(false); - } - - public async Task GetIdentityChangesAsync(int identitySequenceId, int groupSequenceId, int organizationIdentitySequenceId, int pageSize, Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetIdentityChanges")) - { - List> query = new List>(); - query.Add(QueryParameters.IdentitySequenceId, identitySequenceId.ToString()); - query.Add(QueryParameters.GroupSequenceId, groupSequenceId.ToString()); - query.Add(QueryParameters.OrgIdentitySequenceId, organizationIdentitySequenceId.ToString()); - query.Add(QueryParameters.PageSize, pageSize.ToString()); - query.Add(QueryParameters.ScopeId, scopeId.ToString("N")); - - return await SendAsync(HttpMethod.Get, IdentityResourceIds.Identity, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task> GetUserIdentityIdsByDomainIdAsync( - Guid domainId, - object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, nameof(GetUserIdentityIdsByDomainIdAsync))) - { - ArgumentUtility.CheckForEmptyGuid(domainId, nameof(domainId)); - var query = new List>(); - query.Add(QueryParameters.DomainId, domainId.ToString("N")); - return - await - SendAsync>( - method: HttpMethod.Get, - locationId: IdentityResourceIds.Identity, - version: s_currentApiVersion, - queryParameters: query, - userState: userState, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - #endregion - - #region Operations on IdentitySelf Controller - - public async Task GetIdentitySelfAsync(object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetIdentitySelf")) - { - return await SendAsync(HttpMethod.Get, IdentityResourceIds.IdentitySelf, version: s_currentApiVersion, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - #endregion - - #region Operations on IdentityTenant Controller - - public async Task GetTenant(string tenantId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetTenant")) - { - //NOTE [RR]: Having to re-create ApiResourceLocation here since /_apis is currently not - //Anonymous and using underlying SendAsync<> overloads throws a ObjectNullRefernceException - //when a null credential, indicating anonymous request, is - var resourceLocation = new ApiResourceLocation - { - Id = IdentityResourceIds.IdentityTenant, - ResourceName = IdentityResourceIds.IdentityTenantResource, - RouteTemplate = "_apis/identities/tenant/{tenantId}", - ResourceVersion = 1, - MinVersion = new Version(1, 0), - MaxVersion = new Version(2, 0), - ReleasedVersion = new Version(0, 0) - }; - - using (var requestMessage = CreateRequestMessage(HttpMethod.Get, resourceLocation, new { tenantId = tenantId }, version: s_currentApiVersion)) - using (var client = new HttpClient()) - { - var response = await client.SendAsync(requestMessage, cancellationToken: cancellationToken); - response.EnsureSuccessStatusCode(); - return await response.Content.ReadAsAsync(new[] { this.Formatter }, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - } - - #endregion - - #region Operations on service identities controller - - public async Task CreateFrameworkIdentityAsync(FrameworkIdentityType identityType, string role, string identifier, string displayName, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "CreateServiceIdentity")) - { - if (identityType == FrameworkIdentityType.None) - { - throw new ArgumentException(CommonResources.EmptyStringNotAllowed(), "identityType"); - } - - ArgumentUtility.CheckStringForNullOrEmpty(displayName, "role"); - ArgumentUtility.CheckStringForNullOrEmpty(displayName, "identifier"); - ArgumentUtility.CheckStringForNullOrEmpty(displayName, "displayName"); - - HttpContent content = new ObjectContent( - typeof(FrameworkIdentityInfo), - new FrameworkIdentityInfo - { - IdentityType = identityType, - Role = role, - Identifier = identifier, - DisplayName = displayName - }, - this.Formatter); - - return await SendAsync(HttpMethod.Put, IdentityResourceIds.FrameworkIdentity, version: s_currentApiVersion, content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - #endregion - - #region Operations on Groups Controller - public virtual async Task ListGroupsAsync(Guid[] scopeIds = null, bool recurse = false, bool deleted = false, IEnumerable propertyNameFilters = null, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ListGroups")) - { - List> query = null; - - if (scopeIds != null || recurse != false || propertyNameFilters != null) - { - query = new List>(); - - if (scopeIds != null) - { - query.AddMultiple(QueryParameters.ScopeIds, scopeIds, (val) => val.ToString("N")); - } - - if (recurse != false) - { - query.Add(QueryParameters.Recurse, "true"); - } - - if (deleted != false) - { - query.Add(QueryParameters.Deleted, "true"); - } - - if (propertyNameFilters != null) - { - query.AddMultiple(QueryParameters.Properties, propertyNameFilters); - } - } - - return await SendAsync(HttpMethod.Get, IdentityResourceIds.Group, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public Task DeleteGroupAsync(IdentityDescriptor descriptor, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return DeleteGroupAsyncInternal(SerializeDescriptor(descriptor), userState, cancellationToken: cancellationToken); - } - - public Task DeleteGroupAsync(Guid groupId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return DeleteGroupAsyncInternal(groupId.ToString(), userState, cancellationToken); - } - - public async Task CreateGroupsAsync(Guid scopeId, IList groups, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "CreateGroup")) - { - ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - ArgumentUtility.CheckEnumerableForNullOrEmpty(groups, "groups"); - - HttpContent content = new ObjectContent(new CreateGroupsInfo(scopeId, groups), this.Formatter); - - return await SendAsync(HttpMethod.Post, IdentityResourceIds.Group, version: s_currentApiVersion, content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - #endregion - - #region Operations on Scopes Controller - public async Task GetScopeAsync(string scopeName, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetScope")) - { - ArgumentUtility.CheckStringForNullOrEmpty(scopeName, "scopeName"); - - List> query = new List>(); - query.Add(QueryParameters.ScopeName, scopeName); - - return await SendAsync(HttpMethod.Get, IdentityResourceIds.Scope, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task GetScopeAsync(Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetScopeById")) - { - ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - - return await SendAsync(HttpMethod.Get, IdentityResourceIds.Scope, new { scopeId = scopeId }, version: s_currentApiVersion, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task CreateScopeAsync(Guid scopeId, Guid parentScopeId, GroupScopeType scopeType, string scopeName, string adminGroupName, string adminGroupDescription, Guid creatorId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "CreateScope")) - { - ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - - //REST USAGE NON-STANDARD: A POST to create a resource should be a reprensentation of the resource being created, in this case an IdentityScope. However, - //the create operation takes parameters not present in the new resource: specifically the adminGroupName and adminGroupDescription. We either need - //to set these in a different way -- on the correct resource -- or include them as part of IdentityScope. - - // Constructor Validates params - CreateScopeInfo info = new CreateScopeInfo(parentScopeId, scopeType, scopeName, adminGroupName, adminGroupDescription, creatorId); - - HttpContent content = new ObjectContent(info, this.Formatter); - - return await SendAsync(HttpMethod.Put, IdentityResourceIds.Scope, new { scopeId = scopeId }, version: s_currentApiVersion, content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task RenameScopeAsync(Guid scopeId, string newName, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "RenameScope")) - { - ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - ArgumentUtility.CheckStringForNullOrEmpty(newName, "newName"); - - IdentityScope rename = new IdentityScope(scopeId, newName); - HttpContent content = new ObjectContent(rename, this.Formatter); - - return await SendAsync(new HttpMethod("PATCH"), IdentityResourceIds.Scope, new { scopeId = scopeId }, version: s_currentApiVersion, content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - // code for version 2 of the API - lets switch to this after the new api version has been in for a sprint - //ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - //ArgumentUtility.CheckStringForNullOrEmpty(newName, "newName"); - //return await UpdateScopeAsync(scopeId, nameof(IdentityScope.Name), newName, userState, cancellationToken); - } - - public async Task DeleteScopeAsync(Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "DeleteScope")) - { - ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - - return await SendAsync(HttpMethod.Delete, IdentityResourceIds.Scope, new { scopeId = scopeId }, version: s_currentApiVersion, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task RestoreGroupScopeAsync(Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckForEmptyGuid(scopeId, "scopeId"); - return await UpdateScopeAsync(scopeId, nameof(IdentityScope.IsActive), true, userState, cancellationToken).ConfigureAwait(false); - } - - private async Task UpdateScopeAsync(Guid scopeId, String property, object value, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using(new OperationScope(IdentityResourceIds.AreaName, "UpdateScope")) - { - JsonPatchDocument patchDocument = new JsonPatchDocument{ - new JsonPatchOperation - { - Operation = WebApi.Patch.Operation.Replace, - Path = "/" + property, - Value = value - } - }; - - HttpContent content = new ObjectContent(patchDocument, new VssJsonMediaTypeFormatter(true), "application/json-patch+json"); - - return await SendAsync(new HttpMethod("PATCH"), IdentityResourceIds.Scope, new { scopeId = scopeId }, version: new ApiResourceVersion(5.0, 2), content: content, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - #endregion - - #region Operations on Members\MembersOf Controllers\ - //These methods have analogs on the Members\MemberOf controllers but are unused... - //Task ReadMembershipsAsync(String memberId, QueryMembership queryMembership = QueryMembership.Direct) - - //This one called by IsMember, but not exposed directly - //Task ReadMembershipsAsync(String memberId, String containerId, QueryMembership queryMembership = QueryMembership.Direct) - - //Task ReadMembersAsync(String containerId, QueryMembership queryMembership = QueryMembership.Direct) - - //Task ReadMemberAsync(String containerId, String memberId, QueryMembership queryMembership = QueryMembership.Direct) - - public Task AddMemberToGroupAsync(IdentityDescriptor containerId, Guid memberId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return AddMemberToGroupAsyncInternal(new { containerId = SerializeDescriptor(containerId), memberId = memberId }, new List>(), userState, cancellationToken); - } - - public Task AddMemberToGroupAsync(IdentityDescriptor containerId, IdentityDescriptor memberId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - //REST USAGE NON-STANDARD: This should not be a query param, as this ends up being a PUT, which should address the resource directly - // (and also see the internal method on non-standard use of PUT). But the memberId may contain a colon, which will cause it to - //be rejected by ASP.NET as dangerous (even if escaped) so doing this as a workaround. - List> query = new List>(); - query.Add(QueryParameters.MemberId, SerializeDescriptor(memberId)); - - return AddMemberToGroupAsyncInternal(new { containerId = SerializeDescriptor(containerId) }, query, userState, cancellationToken); - } - - public async Task RemoveMemberFromGroupAsync(IdentityDescriptor containerId, IdentityDescriptor memberId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "RemoveMemberFromGroup")) - { - //REST USAGE NON-STANDARD: This should not be a query param, as this DELETE which should address the resource directly - //but the memberId may contain a colon, which will cause it to be rejected by ASP.NET as dangerous (even if escaped) so doing - //this as a workaround. - List> query = new List>(); - query.Add(QueryParameters.MemberId, SerializeDescriptor(memberId)); - - return await SendAsync(HttpMethod.Delete, IdentityResourceIds.Member, new { containerId = SerializeDescriptor(containerId) }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task IsMember(IdentityDescriptor containerId, IdentityDescriptor memberId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "IsMember")) - { - List> query = new List>(); - query.Add(QueryParameters.QueryMembership, QueryMembership.Expanded.ToString()); - - //Consider: Can this actually return null? This is how IdentityHttpComponent works... - IdentityDescriptor result = await SendAsync(HttpMethod.Get, IdentityResourceIds.MemberOf, - new { memberId = SerializeDescriptor(memberId), containerId = SerializeDescriptor(containerId) }, - version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - - return result != null; - } - } - #endregion - - #region Operations on IdentitySnapshot controller - public async Task GetIdentitySnapshotAsync(Guid scopeId, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetIdentitySnapshot")) - { - return await SendAsync(HttpMethod.Get, IdentityResourceIds.IdentitySnapshot, version: s_currentApiVersion, routeValues: new { scopeId = scopeId }, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - #endregion - - #region Operations on SignoutToken controller - public async Task GetSignoutToken(object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetSignoutToken")) - { - return await SendAsync( - HttpMethod.Get, - IdentityResourceIds.SignoutToken, - version: s_currentApiVersion, - routeValues: new object { }, - userState: userState, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - #endregion - - #region Operations on SignedInToken controller - public async Task GetSignedInToken(object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetSignedInToken")) - { - return await SendAsync( - HttpMethod.Get, - IdentityResourceIds.SignedInToken, - version: s_currentApiVersion, - routeValues: new object { }, - userState: userState, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - #endregion - - #region Operations on IdentitySequenceId Controller - public async Task GetMaxSequenceIdAsync(object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "GetMaxSequenceId")) - { - return await SendAsync(HttpMethod.Get, IdentityResourceIds.IdentityMaxSequenceId, version: s_currentApiVersion, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - #endregion Operations on IdentitySequenceId Controller - - #region Operations on Claims Controller - public async Task CreateOrBindIdentity(Identity sourceIdentity, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "CreateOrBindWithClaims")) - { - ArgumentUtility.CheckForNull(sourceIdentity, nameof(sourceIdentity)); - ArgumentUtility.CheckForNull(sourceIdentity.Descriptor, nameof(sourceIdentity.Descriptor)); - - HttpContent content = new ObjectContent(sourceIdentity, this.Formatter); - - return await SendAsync(HttpMethod.Put, - IdentityResourceIds.Claims, - version: s_currentApiVersion, - userState: userState, - content: content, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - #endregion Operations on Claims Controller - - #region Operations on IdentityDescriptor Controller - /// - /// [Preview API] - /// - /// - /// - /// - /// The cancellation token to cancel operation. - public async Task GetDescriptorByIdAsync( - Guid id, - bool? isMasterId = null, - object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - object routeValues = new { id = id }; - - var queryParams = new List>(); - if (isMasterId != null) - { - queryParams.Add("isMasterId", isMasterId.Value.ToString()); - } - - return await SendAsync( - HttpMethod.Get, - IdentityResourceIds.DescriptorsResourceLocationId, - routeValues: routeValues, - version: new ApiResourceVersion("3.2-preview.1"), - queryParameters: queryParams, - userState: userState, - cancellationToken: - cancellationToken).ConfigureAwait(false); - } - #endregion Operations on IdentityDescriptor Controller - - #region Private Helpers - private async Task ReadIdentitiesAsyncInternal(List> searchQuery, QueryMembership queryMembership, IEnumerable propertyNameFilters, bool includeRestrictedVisibility, RequestHeadersContext requestHeadersContext, object userState, CancellationToken cancellationToken) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ReadIdentities")) - { - AppendQueryString(searchQuery, queryMembership, propertyNameFilters, includeRestrictedVisibility); - var additionalHeaders = RequestHeadersContext.HeadersUtils.PopulateRequestHeaders(requestHeadersContext); - - return await SendAsync(HttpMethod.Get, additionalHeaders, IdentityResourceIds.Identity, version: s_currentApiVersion, queryParameters: searchQuery, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - private async Task ReadIdentitiesBatchAsyncInternal( - IList socialDescriptors, - QueryMembership queryMembership, - IEnumerable propertyNameFilters, - bool includeRestrictedVisibility, - RequestHeadersContext requestHeadersContext, - object userState, CancellationToken cancellationToken) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ReadIdentitiesBatch")) - { - IdentityBatchInfo info = new IdentityBatchInfo(socialDescriptors, queryMembership, propertyNameFilters, includeRestrictedVisibility); - - HttpContent content = new ObjectContent(info, base.Formatter); - - var queryParams = new List>() - { - {IdentityBatchTelemetryConstants.QueryMembershipHint, queryMembership.ToString()}, - {IdentityBatchTelemetryConstants.FlavorHint, IdentityBatchTelemetryConstants.BySocialDescriptorFlavor }, - {IdentityBatchTelemetryConstants.CountHint, (socialDescriptors?.Count ?? 0).ToString() }, - }; - - var additionalHeaders = RequestHeadersContext.HeadersUtils.PopulateRequestHeaders(requestHeadersContext); - - return await SendAsync( - HttpMethod.Post, - additionalHeaders, - IdentityResourceIds.IdentityBatch, - version: s_currentApiVersion, - content: content, - userState: userState, - queryParameters: queryParams, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - private async Task ReadIdentitiesBatchAsyncInternal( - IList subjectDescriptors, - QueryMembership queryMembership, - IEnumerable propertyNameFilters, - bool includeRestrictedVisibility, - RequestHeadersContext requestHeadersContext, - object userState, CancellationToken cancellationToken) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ReadIdentitiesBatch")) - { - IdentityBatchInfo info = new IdentityBatchInfo(subjectDescriptors, queryMembership, propertyNameFilters, includeRestrictedVisibility); - - HttpContent content = new ObjectContent(info, base.Formatter); - - var queryParams = new List>() - { - {IdentityBatchTelemetryConstants.QueryMembershipHint, queryMembership.ToString()}, - {IdentityBatchTelemetryConstants.FlavorHint, IdentityBatchTelemetryConstants.BySubjectDescriptorFlavor }, - {IdentityBatchTelemetryConstants.CountHint, (subjectDescriptors?.Count ?? 0).ToString() }, - }; - - var additionalHeaders = RequestHeadersContext.HeadersUtils.PopulateRequestHeaders(requestHeadersContext); - - return await SendAsync( - HttpMethod.Post, - additionalHeaders, - IdentityResourceIds.IdentityBatch, - version: s_currentApiVersion, - content: content, - userState: userState, - queryParameters: queryParams, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - private async Task ReadIdentitiesBatchAsyncInternal( - IList descriptors, - QueryMembership queryMembership, - IEnumerable propertyNameFilters, - bool includeRestrictedVisibility, - RequestHeadersContext requestHeadersContext, - object userState, CancellationToken cancellationToken) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ReadIdentitiesBatch")) - { - IdentityBatchInfo info = new IdentityBatchInfo(descriptors, queryMembership, propertyNameFilters, includeRestrictedVisibility); - - HttpContent content = new ObjectContent(info, base.Formatter); - - var queryParams = new List>() - { - {IdentityBatchTelemetryConstants.QueryMembershipHint, queryMembership.ToString()}, - {IdentityBatchTelemetryConstants.FlavorHint, IdentityBatchTelemetryConstants.ByDescriptorFlavor }, - {IdentityBatchTelemetryConstants.CountHint, (descriptors?.Count ?? 0).ToString() }, - }; - - var additionalHeaders = RequestHeadersContext.HeadersUtils.PopulateRequestHeaders(requestHeadersContext); - - return await SendAsync( - HttpMethod.Post, - additionalHeaders, - IdentityResourceIds.IdentityBatch, - version: s_currentApiVersion, - content: content, - userState: userState, - queryParameters: queryParams, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - private async Task ReadIdentitiesBatchAsyncInternal( - IList identityIds, - QueryMembership queryMembership, - IEnumerable propertyNameFilters, - bool includeRestrictedVisibility, - object userState, - RequestHeadersContext requestHeadersContext, - CancellationToken cancellationToken) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ReadIdentitiesBatch")) - { - IdentityBatchInfo info = new IdentityBatchInfo(identityIds, queryMembership, propertyNameFilters, includeRestrictedVisibility); - - HttpContent content = new ObjectContent(info, base.Formatter); - - var queryParams = new List> - { - {IdentityBatchTelemetryConstants.QueryMembershipHint, queryMembership.ToString()}, - {IdentityBatchTelemetryConstants.FlavorHint, IdentityBatchTelemetryConstants.ByIdFlavor }, - {IdentityBatchTelemetryConstants.CountHint, (identityIds?.Count ?? 0).ToString() }, - }; - - var additionalHeaders = RequestHeadersContext.HeadersUtils.PopulateRequestHeaders(requestHeadersContext); - - return await SendAsync( - HttpMethod.Post, - additionalHeaders, - IdentityResourceIds.IdentityBatch, - version: s_currentApiVersion, - content: content, - userState: userState, - queryParameters: queryParams, - cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - //Separate endpoint for identity and identities - private async Task ReadIdentityAsyncInternal( - string identityId, - QueryMembership queryMembership, - IEnumerable propertyNameFilters, - object userState, CancellationToken cancellationToken) - { - using (new OperationScope(IdentityResourceIds.AreaName, "ReadIdentity")) - { - var query = new List>(); - AppendQueryString(query, queryMembership, propertyNameFilters, false); - - return await SendAsync(HttpMethod.Get, IdentityResourceIds.Identity, new { identityId = identityId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - private async Task DeleteGroupAsyncInternal(string groupId, object userState, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "DeleteGroup")) - { - return await SendAsync(HttpMethod.Delete, IdentityResourceIds.Group, new { groupId = groupId }, version: s_currentApiVersion, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task AddMemberToGroupAsyncInternal(object routeParams, IEnumerable> query, object userState = null, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(IdentityResourceIds.AreaName, "AddMemberToGroup")) - { - //REST USAGE NON-STANDARD: This is modeled as a PUT operation, but contains no body. PUT should create or replace the resource at this - //address, but in this case, there is no resource, it is adding a link between resources. This should be done differently - return await SendAsync(HttpMethod.Put, IdentityResourceIds.Member, routeParams, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - private void AppendQueryString(List> queryParams, QueryMembership queryMembership, IEnumerable propertyNameFilters, bool includeRestrictedVisibility) - { - queryParams.Add(QueryParameters.QueryMembership, queryMembership.ToString()); - - queryParams.AddMultiple(QueryParameters.Properties, propertyNameFilters); - - if (includeRestrictedVisibility) - { - queryParams.Add(QueryParameters.IncludeRestrictedVisibility, "true"); - } - } - - private static string SerializeDescriptor(IdentityDescriptor descriptor) - { - if (descriptor == null) - { - return string.Empty; - } - else - { - return string.Join(";", descriptor.IdentityType, descriptor.Identifier); - } - } - - - #endregion - - /// - /// Exceptions for account errors - /// - protected override IDictionary TranslatedExceptions - { - get - { - return s_translatedExceptions; - } - } - - private static class IdentityBatchTelemetryConstants - { - public const string QueryMembershipHint = "queryMembership"; - public const string FlavorHint = "flavor"; - public const string CountHint = "count"; - - public const string ByIdFlavor = "id"; - public const string ByDescriptorFlavor = "descriptor"; - public const string BySubjectDescriptorFlavor = "subjectDescriptor"; - public const string BySocialDescriptorFlavor = "socialDescriptor"; - } - - private static Dictionary s_translatedExceptions; - private static readonly ApiResourceVersion s_currentApiVersion; - private const int maxDescriptors = 5 /* 256 for descriptor + 64 for type + 1 */; - private const int maxIds = 50; - } -} diff --git a/src/Sdk/WebApi/WebApi/HttpClients/LocationHttpClient.cs b/src/Sdk/WebApi/WebApi/HttpClients/LocationHttpClient.cs deleted file mode 100644 index ab6f465ed..000000000 --- a/src/Sdk/WebApi/WebApi/HttpClients/LocationHttpClient.cs +++ /dev/null @@ -1,184 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.Location.Client -{ - [ClientCircuitBreakerSettings(timeoutSeconds: 15, failurePercentage: 80)] - [ClientCancellationTimeout(timeoutSeconds: 30)] - public class LocationHttpClient : VssHttpClientBase - { - static LocationHttpClient() - { - s_translatedExceptions = new Dictionary(); - s_translatedExceptions.Add("ServiceDefinitionDoesNotExistException", typeof(ServiceDefinitionDoesNotExistException)); - s_translatedExceptions.Add("InvalidAccessPointException", typeof(InvalidAccessPointException)); - s_translatedExceptions.Add("InvalidServiceDefinitionException", typeof(InvalidServiceDefinitionException)); - s_translatedExceptions.Add("ParentDefinitionNotFoundException", typeof(ParentDefinitionNotFoundException)); - s_translatedExceptions.Add("CannotChangeParentDefinitionException", typeof(CannotChangeParentDefinitionException)); - s_translatedExceptions.Add("ActionDeniedBySubscriberException", typeof(ActionDeniedBySubscriberException)); - } - - public LocationHttpClient(Uri baseUrl, VssCredentials credentials) - : base(baseUrl, credentials) - { - } - - public LocationHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings) - : base(baseUrl, credentials, settings) - { - } - - public LocationHttpClient(Uri baseUrl, VssCredentials credentials, params DelegatingHandler[] handlers) - : base(baseUrl, credentials, handlers) - { - } - - public LocationHttpClient(Uri baseUrl, VssCredentials credentials, VssHttpRequestSettings settings, params DelegatingHandler[] handlers) - : base(baseUrl, credentials, settings, handlers) - { - } - - public LocationHttpClient(Uri baseUrl, HttpMessageHandler pipeline, bool disposeHandler) - : base(baseUrl, pipeline, disposeHandler) - { - } - - public async Task GetConnectionDataAsync(ConnectOptions connectOptions, Int64 lastChangeId, CancellationToken cancellationToken = default(CancellationToken), Object userState = null) - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "GetConnectionData")) - { - var uri = new Uri(PathUtility.Combine(BaseAddress.GetLeftPart(UriPartial.Path), connectSubUrl)); - var uriBuilder = new UriBuilder(uri) { Query = BaseAddress.Query }; - - var query = new List> - { - new KeyValuePair("connectOptions", ((Int32)connectOptions).ToString(CultureInfo.InvariantCulture)), - new KeyValuePair("lastChangeId", ((Int32)lastChangeId).ToString(CultureInfo.InvariantCulture)), - new KeyValuePair("lastChangeId64", lastChangeId.ToString(CultureInfo.InvariantCulture)) - }; - - uri = uriBuilder.Uri.AppendQuery(query); - - var message = new HttpRequestMessage(HttpMethod.Get, uri.ToString()); - message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - - return await SendAsync(message, userState, cancellationToken).ConfigureAwait(false); - } - } - - public async Task UpdateServiceDefinitionsAsync(IEnumerable definitions, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "UpdateServiceDefinitions")) - { - ArgumentUtility.CheckEnumerableForNullOrEmpty(definitions, "definitions"); - - HttpContent content = new ObjectContent>>(new VssJsonCollectionWrapper>(definitions), base.Formatter); - await SendAsync(new HttpMethod("PATCH"), LocationResourceIds.ServiceDefinitions, null, s_currentApiVersion, content, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task DeleteServiceDefinitionAsync(String serviceType, Guid identifier, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "DeleteServiceDefinitions")) - { - return await SendAsync(HttpMethod.Delete, LocationResourceIds.ServiceDefinitions, new { serviceType = serviceType, identifier = identifier }, s_currentApiVersion, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task> GetServiceDefinitionsAsync() - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "GetServiceDefinitions")) - { - return await SendAsync>(HttpMethod.Get, LocationResourceIds.ServiceDefinitions, null, s_currentApiVersion).ConfigureAwait(false); - } - } - - public async Task> GetServiceDefinitionsAsync(String serviceType) - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "GetServiceDefinitions")) - { - return await SendAsync>(HttpMethod.Get, LocationResourceIds.ServiceDefinitions, new { serviceType = serviceType }, s_currentApiVersion).ConfigureAwait(false); - } - } - - public Task GetServiceDefinitionAsync(String serviceType, Guid identifier, CancellationToken cancellationToken = default(CancellationToken)) - { - return GetServiceDefinitionAsync(serviceType, identifier, allowFaultIn: true, previewFaultIn: false, cancellationToken: cancellationToken); - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public async Task GetServiceDefinitionAsync(String serviceType, Guid identifier, Boolean allowFaultIn, Boolean previewFaultIn, CancellationToken cancellationToken = default(CancellationToken)) - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "GetServiceDefinitions")) - { - List> query = new List>(); - - if (!allowFaultIn) - { - query.Add("allowFaultIn", Boolean.FalseString); - } - - if (previewFaultIn) - { - if (!allowFaultIn) - { - throw new InvalidOperationException("Cannot preview a service definition fault in if we do not allow the fault in."); - } - - query.Add("previewFaultIn", Boolean.TrueString); - } - - return await SendAsync(HttpMethod.Get, LocationResourceIds.ServiceDefinitions, new { serviceType = serviceType, identifier = identifier }, s_currentApiVersion, queryParameters: query, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public async Task FlushSpsServiceDefinitionAsync(Guid hostId, CancellationToken cancellationToken = default(CancellationToken)) - { - // Used when migrating an SPS host to update all registered service definitions across other VSO instances. - using (new OperationScope(LocationResourceIds.LocationServiceArea, "FlushSpsServiceDefinition")) - { - return await SendAsync(HttpMethod.Put, LocationResourceIds.SpsServiceDefinition, new { hostId = hostId }, s_currentApiVersion, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - public async Task> GetResourceAreasAsync() - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "GetResourceAreas")) - { - return await SendAsync>(HttpMethod.Get, LocationResourceIds.ResourceAreas, null, new ApiResourceVersion("3.2-preview.1")).ConfigureAwait(false); - } - } - - public async Task GetResourceAreaAsync(Guid areaId) - { - using (new OperationScope(LocationResourceIds.LocationServiceArea, "GetResourceAreas")) - { - return await SendAsync(HttpMethod.Get, LocationResourceIds.ResourceAreas, new { areaId = areaId } , new ApiResourceVersion("3.2-preview.1")).ConfigureAwait(false); - } - } - - /// - /// Exceptions for location errors - /// - protected override IDictionary TranslatedExceptions - { - get - { - return s_translatedExceptions; - } - } - - private static Dictionary s_translatedExceptions; - private const String connectSubUrl = "_apis/connectionData"; - protected static readonly ApiResourceVersion s_currentApiVersion = new ApiResourceVersion(1.0); - } -} diff --git a/src/Sdk/WebApi/WebApi/IdentityRef.cs b/src/Sdk/WebApi/WebApi/IdentityRef.cs deleted file mode 100644 index 106611864..000000000 --- a/src/Sdk/WebApi/WebApi/IdentityRef.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.ComponentModel; -using System.Runtime.Serialization; -using GitHub.Services.Common; -using GitHub.Services.Graph.Client; -using GitHub.Services.WebApi.Xml; -using Newtonsoft.Json; - -namespace GitHub.Services.WebApi -{ - [JsonObject(MemberSerialization = MemberSerialization.OptIn)] - [XmlSerializableDataContract(EnableCamelCaseNameCompat = true)] - public class IdentityRef : GraphSubjectBase, ISecuredObject - { - // The following "new" properties are inherited from the base class, - // but are reimplemented with public setters for back compat. - - public new SubjectDescriptor Descriptor - { - get { return base.Descriptor; } - set { base.Descriptor = value; } - } - - public new string DisplayName - { - get { return base.DisplayName; } - set { base.DisplayName = value; } - } - - public new string Url - { - get { return base.Url; } - set { base.Url = value; } - } - - public new ReferenceLinks Links - { - get { return base.Links; } - set { base.Links = value; } - } - - [DataMember(Name = "id")] - [JsonProperty(PropertyName = "id")] - public String Id { get; set; } - - // Deprecated. See https://dev.azure.com/mseng/VSOnline/_wiki/wikis/VSOnline.wiki?wikiVersion=GBwikiMaster&pagePath=%2FTeam%20Pages%2FPipelines%2FPublic%20projects&anchor=obsolete-identity-fields - /// - /// Deprecated - use Domain+PrincipalName instead - /// - [DataMember(Name = "uniqueName", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "uniqueName", DefaultValueHandling = DefaultValueHandling.Ignore)] - [JsonConverter(typeof(DefaultValueOnPublicAccessJsonConverter))] - public String UniqueName { get; set; } - - /// - /// Deprecated - Can be retrieved by querying the Graph user referenced in the "self" entry of the IdentityRef "_links" dictionary - /// - [DataMember(Name = "directoryAlias", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "directoryAlias", DefaultValueHandling = DefaultValueHandling.Ignore)] - [JsonConverter(typeof(DefaultValueOnPublicAccessJsonConverter))] - public String DirectoryAlias { get; set; } - - /// - /// Deprecated - not in use in most preexisting implementations of ToIdentityRef - /// - [DataMember(Name = "profileUrl", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "profileUrl", DefaultValueHandling = DefaultValueHandling.Ignore)] - [JsonConverter(typeof(DefaultValueOnPublicAccessJsonConverter))] - public String ProfileUrl { get; set; } - - /// - /// Deprecated - Available in the "avatar" entry of the IdentityRef "_links" dictionary - /// - [DataMember(Name = "imageUrl", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "imageUrl", DefaultValueHandling = DefaultValueHandling.Ignore)] - [JsonConverter(typeof(DefaultValueOnPublicAccessJsonConverter))] - public String ImageUrl { get; set; } - - /// - /// Deprecated - Can be inferred from the subject type of the descriptor (Descriptor.IsGroupType) - /// - [DataMember(Name = "isContainer", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "isContainer", DefaultValueHandling = DefaultValueHandling.Ignore)] - public Boolean IsContainer { get; set; } - - /// - /// Deprecated - Can be inferred from the subject type of the descriptor (Descriptor.IsAadUserType/Descriptor.IsAadGroupType) - /// - [DataMember(Name = "isAadIdentity", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "isAadIdentity", DefaultValueHandling = DefaultValueHandling.Ignore)] - public Boolean IsAadIdentity { get; set; } - - /// - /// Deprecated - Can be retrieved by querying the Graph membership state referenced in the "membershipState" entry of the GraphUser "_links" dictionary - /// - [DataMember(Name = "inactive", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "inactive", DefaultValueHandling = DefaultValueHandling.Ignore)] - public Boolean Inactive { get; set; } - - [DataMember(Name = "isDeletedInOrigin", EmitDefaultValue = false)] - [JsonProperty(PropertyName = "isDeletedInOrigin", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] - public Boolean IsDeletedInOrigin { get; set; } - - /// - /// This property is for xml compat only. - /// - [DataMember(Name = "displayName", EmitDefaultValue = false)] - [JsonIgnore, Obsolete, EditorBrowsable(EditorBrowsableState.Never)] - public string DisplayNameForXmlSerialization { get => base.DisplayName; set => base.DisplayName = value; } - - /// - /// This property is for xml compat only. - /// - [DataMember(Name = "url", EmitDefaultValue = false)] - [JsonIgnore, Obsolete, EditorBrowsable(EditorBrowsableState.Never)] - public string UrlForXmlSerialization { get => base.Url; set => base.Url = value; } - - Guid ISecuredObject.NamespaceId => GraphSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => GraphSecurityConstants.ReadByPublicIdentifier; - - string ISecuredObject.GetToken() => GraphSecurityConstants.RefsToken; - } -} diff --git a/src/Sdk/WebApi/WebApi/JsonUtility.cs b/src/Sdk/WebApi/WebApi/JsonUtility.cs deleted file mode 100644 index b8cbd911d..000000000 --- a/src/Sdk/WebApi/WebApi/JsonUtility.cs +++ /dev/null @@ -1,258 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi -{ - public static class JsonUtility - { - public static JsonSerializer CreateJsonSerializer() - { - return JsonSerializer.Create(s_serializerSettings.Value); - } - - public static T FromString(String toDeserialize) - { - return FromString(toDeserialize, s_serializerSettings.Value); - } - - public static T FromString( - String toDeserialize, - JsonSerializerSettings settings) - { - if (String.IsNullOrEmpty(toDeserialize)) - { - return default(T); - } - - using (StringReader sr = new StringReader(toDeserialize)) - using (JsonTextReader jsonReader = new JsonTextReader(sr)) - { - JsonSerializer s = JsonSerializer.Create(settings); - return s.Deserialize(jsonReader); - } - } - - public static void Populate( - String toDeserialize, - Object target) - { - using (StringReader sr = new StringReader(toDeserialize)) - using (JsonTextReader jsonReader = new JsonTextReader(sr)) - { - JsonSerializer s = JsonSerializer.Create(s_serializerSettings.Value); - s.Populate(jsonReader, target); - } - } - - public static String ToString(Object toSerialize) - { - return ToString(toSerialize, false); - } - - public static String ToString(IList toSerialize) - { - if (toSerialize == null || toSerialize.Count == 0) - { - return null; - } - - return ToString(toSerialize, false); - } - - public static String ToString( - Object toSerialize, - Boolean indent) - { - if (toSerialize == null) - { - return null; - } - - StringBuilder sb = new StringBuilder(); - using (StringWriter sw = new StringWriter(sb)) - using (JsonTextWriter jsonWriter = new JsonTextWriter(sw)) - { - JsonSerializer s = JsonSerializer.Create(indent ? s_indentSettings.Value : s_serializerSettings.Value); - s.Serialize(jsonWriter, toSerialize); - } - - return sb.ToString(); - } - - public static T Deserialize(Stream streamToRead) - { - return Deserialize(streamToRead, false); - } - - public static T Deserialize( - Stream streamToRead, - Boolean leaveOpen) - { - if (streamToRead == null) - { - return default(T); - } - - using (StreamReader sr = new StreamReader(streamToRead, s_UTF8NoBOM, true, 80 * 1024, leaveOpen)) - using (JsonTextReader jsonReader = new JsonTextReader(sr)) - { - JsonSerializer s = JsonSerializer.Create(s_serializerSettings.Value); - return s.Deserialize(jsonReader); - } - } - - - public static T Deserialize(Byte[] toDeserialize) - { - return Deserialize(toDeserialize, s_serializerSettings.Value); - } - - public static T Deserialize( - Byte[] toDeserialize, - JsonSerializerSettings settings) - { - if (toDeserialize == null || toDeserialize.Length == 0) - { - return default(T); - } - - using (MemoryStream ms = new MemoryStream(toDeserialize)) - { - Stream streamToRead = ms; - if (IsGZipStream(toDeserialize)) - { - streamToRead = new GZipStream(ms, CompressionMode.Decompress); - } - - using (StreamReader sr = new StreamReader(streamToRead, s_UTF8NoBOM, true)) - using (JsonTextReader jsonReader = new JsonTextReader(sr)) - { - JsonSerializer s = JsonSerializer.Create(settings); - return s.Deserialize(jsonReader); - } - } - } - - public static JToken Map( - this JToken token, - Dictionary> mapFuncs) - { - // no map funcs, just clones - mapFuncs = mapFuncs ?? new Dictionary>(); - - Func mapperFunc; - - // process token - switch (token.Type) - { - case JTokenType.Array: - JArray newArray = new JArray(); - foreach (JToken item in token.Children()) - { - JToken child = item; - if (child.HasValues) - { - child = child.Map(mapFuncs); - } - - if (mapFuncs.TryGetValue(child.Type, out mapperFunc)) - { - child = mapperFunc(child); - } - - newArray.Add(child); - } - - return newArray; - - case JTokenType.Object: - JObject copy = new JObject(); - foreach (JProperty prop in token.Children()) - { - JToken child = prop.Value; - if (child.HasValues) - { - child = child.Map(mapFuncs); - } - - if (mapFuncs.TryGetValue(child.Type, out mapperFunc)) - { - child = mapperFunc(child); - } - - copy.Add(prop.Name, child); - } - - return copy; - - case JTokenType.String: - if (mapFuncs.TryGetValue(JTokenType.String, out mapperFunc)) - { - return mapperFunc(token); - } - - return token; - - case JTokenType.Boolean: - case JTokenType.Null: - case JTokenType.Guid: - return token; - - default: - throw new NotSupportedException(WebApiResources.UnexpectedTokenType()); - } - } - - public static Byte[] Serialize( - Object toSerialize, - Boolean compress = true) - { - return Serialize(toSerialize, compress, s_UTF8NoBOM); - } - - public static Byte[] Serialize( - Object toSerialize, - Boolean compress, - Encoding encoding) - { - if (toSerialize == null) - { - return null; - } - - using (MemoryStream ms = new MemoryStream()) - { - Stream streamToWrite = ms; - if (compress) - { - streamToWrite = new GZipStream(ms, CompressionMode.Compress); - } - - using (StreamWriter sw = new StreamWriter(streamToWrite, encoding ?? s_UTF8NoBOM)) - using (JsonTextWriter jsonWriter = new JsonTextWriter(sw)) - { - JsonSerializer s = JsonSerializer.Create(s_serializerSettings.Value); - s.Serialize(jsonWriter, toSerialize); - } - - return ms.ToArray(); - } - } - - private static Boolean IsGZipStream(Byte[] data) - { - return data != null && data.Length > FullGzipHeaderLength && data[0] == GzipHeader[0] && data[1] == GzipHeader[1]; - } - - private const Int32 FullGzipHeaderLength = 10; - private static readonly Byte[] GzipHeader = { 0x1F, 0x8B }; - private static readonly Encoding s_UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); - private static readonly Lazy s_serializerSettings = new Lazy(() => new VssJsonMediaTypeFormatter().SerializerSettings); - private static readonly Lazy s_indentSettings = new Lazy(() => { var s = new VssJsonMediaTypeFormatter().SerializerSettings; s.Formatting = Formatting.Indented; return s; }); - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/IJsonWebTokenHeaderProvider.cs b/src/Sdk/WebApi/WebApi/Jwt/IJsonWebTokenHeaderProvider.cs deleted file mode 100644 index 831392961..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/IJsonWebTokenHeaderProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.WebApi.Jwt -{ - internal interface IJsonWebTokenHeaderProvider - { - void SetHeaders(IDictionary headers); - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/JsonWebToken.cs b/src/Sdk/WebApi/WebApi/Jwt/JsonWebToken.cs deleted file mode 100644 index 73c507688..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/JsonWebToken.cs +++ /dev/null @@ -1,687 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Reflection; -using System.Runtime.Serialization; -using System.Security.Claims; -using System.Text; -using GitHub.Services.Common; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi.Jwt -{ - //while the spec defined other possible algorithms - //in practice these are the only two that are used - [DataContract] - public enum JWTAlgorithm - { - [EnumMember] - None, - - [EnumMember] - HS256, - - [EnumMember] - RS256 - } - - //JsonWebToken is marked as DataContract so - //it can me nested in the Payload as an actor token - //note that the only member serialized is the - //EncodedToken property, and the OnDeserialized method - //decodes everything back out - [DataContract] - [JsonConverter(typeof(JsonWebTokenConverter))] - public sealed class JsonWebToken : IssuedToken - { - //Default lifetime for a JsonWebToken set to 300 seconds (5 minutes) - private const int DefaultLifetime = 300; - - #region Factory Methods - //We chose factory methods for creation, because creation - //generally involves signing the token, which is a bigger operation - //than just using a constructor implies - - //this method is used to instantiate the "self-signed" token for obtaining - //the access token - public static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, VssSigningCredentials credentials) - { - return Create(issuer, audience, validFrom, validTo, default(DateTime), null, null, null, credentials, allowExpiredCertificate: false); - } - - //use this method to instantiate the token with user information - public static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, IEnumerable additionalClaims, JsonWebToken actor) - { - //if you are calling this version of the method additionalClaims and actor cannot be null - ArgumentUtility.CheckForNull(additionalClaims, nameof(additionalClaims)); - ArgumentUtility.CheckForNull(actor, nameof(actor)); - - return Create(issuer, audience, validFrom, validTo, default(DateTime), additionalClaims, actor, null, null, allowExpiredCertificate: false); - } - - //use this method to instantiate the token with user information - public static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, IEnumerable additionalClaims, string actorToken) - { - //if you are calling this version of the method additionalClaims and actor cannot be null - ArgumentUtility.CheckForNull(additionalClaims, nameof(additionalClaims)); - ArgumentUtility.CheckStringForNullOrEmpty(actorToken, nameof(actorToken)); - - return Create(issuer, audience, validFrom, validTo, default(DateTime), additionalClaims, null, actorToken, null, allowExpiredCertificate: false); - } - - public static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, IEnumerable additionalClaims, VssSigningCredentials credentials) - { - //if you are calling this version claims can't be null - ArgumentUtility.CheckForNull(additionalClaims, nameof(additionalClaims)); - - return Create(issuer, audience, validFrom, validTo, default(DateTime), additionalClaims, null, null, credentials, allowExpiredCertificate: false); - } - - public static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, IEnumerable additionalClaims, VssSigningCredentials credentials, bool allowExpiredCertificate) - { - //if you are calling this version claims can't be null - ArgumentUtility.CheckForNull(additionalClaims, nameof(additionalClaims)); - - return Create(issuer, audience, validFrom, validTo, default(DateTime), additionalClaims, null, null, credentials, allowExpiredCertificate); - } - - public static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, DateTime issuedAt, IEnumerable additionalClaims, VssSigningCredentials credentials) - { - //if you are calling this version claims can't be null - ArgumentUtility.CheckForNull(additionalClaims, nameof(additionalClaims)); - - return Create(issuer, audience, validFrom, validTo, issuedAt, additionalClaims, null, null, credentials, allowExpiredCertificate: false); - } - - private static JsonWebToken Create(string issuer, string audience, DateTime validFrom, DateTime validTo, DateTime issuedAt, IEnumerable additionalClaims, JsonWebToken actor, string actorToken, VssSigningCredentials credentials, bool allowExpiredCertificate) - { - ArgumentUtility.CheckStringForNullOrEmpty(issuer, nameof(issuer)); - ArgumentUtility.CheckStringForNullOrEmpty(audience, nameof(audience)); // Audience isn't actually required... - - validFrom = validFrom == default(DateTime) ? DateTime.UtcNow : validFrom.ToUniversalTime(); - validTo = validTo == default(DateTime) ? DateTime.UtcNow + TimeSpan.FromSeconds(DefaultLifetime) : validTo.ToUniversalTime(); - //issuedAt is optional, and breaks certain scenarios if it is present, and breaks others if it is not. - //so only include it if it is explicitly set. - issuedAt = issuedAt == default(DateTime) ? default(DateTime) : issuedAt.ToUniversalTime(); - - JWTHeader header = GetHeader(credentials, allowExpiredCertificate); - JWTPayload payload = new JWTPayload(additionalClaims) { Issuer = issuer, Audience = audience, ValidFrom = validFrom, ValidTo = validTo, IssuedAt = issuedAt }; - - if (actor != null) - { - payload.Actor = actor; - } - else if (actorToken != null) - { - payload.ActorToken = actorToken; - } - - byte[] signature = GetSignature(header, payload, header.Algorithm, credentials); - - return new JsonWebToken(header, payload, signature); - } - - public static JsonWebToken Create(string jwtEncodedString) - { - ArgumentUtility.CheckStringForNullOrEmpty(jwtEncodedString, nameof(jwtEncodedString)); - - JValue value = new JValue(jwtEncodedString); - - return value.ToObject(); - } - #endregion - - #region .ctors - private JsonWebToken() { } - - private JsonWebToken(JWTHeader header, JWTPayload payload, byte[] signature) - { - ArgumentUtility.CheckForNull(header, nameof(header)); - ArgumentUtility.CheckForNull(payload, nameof(payload)); - //signature allowed to be null - _header = header; - _payload = payload; - _signature = signature; - } - #endregion - - #region Base Class Overrides - protected internal override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.S2S; - } - } - - internal override void ApplyTo(IHttpRequest request) - { - request.Headers.SetValue(Common.Internal.HttpHeaders.Authorization, $"Bearer {this.EncodedToken}"); - } - #endregion - - #region Private Fields - JWTHeader _header; - JWTPayload _payload; - byte[] _signature; - string _encodedToken; - #endregion - - #region Public Properties - public string TokenType => _header.Type; - - public JWTAlgorithm Algorithm => _header.Algorithm; - - public string CertificateThumbprint => _header.CertificateThumbprint; - - public string Audience => _payload.Audience; - - public string Issuer => _payload.Issuer; - - public string Subject => _payload.Subject; - - public string NameIdentifier => _payload.NameIdentifier; - - public string IdentityProvider => _payload.IdentityProvider; - - public DateTime ValidTo => _payload.ValidTo; - - public DateTime ValidFrom => _payload.ValidFrom; - - public DateTime IssuedAt => _payload.IssuedAt; - - public bool TrustedForDelegation => _payload.TrustedForDelegation; - - public JsonWebToken Actor => _payload.Actor; - - public string ApplicationIdentifier => _payload.ApplicationIdentifier; - - public string EncodedToken - { - get - { - if (string.IsNullOrEmpty(_encodedToken)) - { - _encodedToken = this.Encode(); - } - return _encodedToken; - } - private set - { - this._encodedToken = value; - } - } - - public string Scopes => _payload.Scopes; - - #endregion - - #region Public \ Protected Overrides - public override string ToString() - { - return string.Format("{0}.{1}", - this._header.ToString(), this._payload.ToString()); - } - #endregion - - #region Internal Properties - internal IDictionary Header => this._header; - - internal IDictionary Payload => this._payload; - - internal byte[] Signature => this._signature; - - #endregion - - #region Private Helpers - private static JWTHeader GetHeader(VssSigningCredentials credentials, bool allowExpired) - { - //note credentials are allowed to be null here, see ValidateSigningCredentials - JWTHeader header = new JWTHeader(); - - JWTAlgorithm alg = JsonWebTokenUtilities.ValidateSigningCredentials(credentials, allowExpired); - - header.Algorithm = alg; - - if (alg != JWTAlgorithm.None) - { - // Some signing credentials may need to set headers for the JWT - var jwtHeaderProvider = credentials as IJsonWebTokenHeaderProvider; - if (jwtHeaderProvider != null) - { - jwtHeaderProvider.SetHeaders(header); - } - } - - return header; - } - - private static byte[] GetSignature(JWTHeader header, JWTPayload payload, VssSigningCredentials credentials, bool allowExpired) - { - JWTAlgorithm alg = JsonWebTokenUtilities.ValidateSigningCredentials(credentials, allowExpired); - - return GetSignature(header, payload, alg, credentials); - } - - //if we alread have the alg, we assume that the creds have been validated already, - //to save the expense of validating twice in the create function... - private static byte[] GetSignature(JWTHeader header, JWTPayload payload, JWTAlgorithm alg, VssSigningCredentials signingCredentials) - { - if (alg == JWTAlgorithm.None) - { - return null; - } - - ArgumentUtility.CheckForNull(header, nameof(header)); - ArgumentUtility.CheckForNull(payload, nameof(payload)); - - string encoding = string.Format("{0}.{1}", header.JsonEncode(), payload.JsonEncode()); - - byte[] bytes = Encoding.UTF8.GetBytes(encoding); - - switch (alg) - { - case JWTAlgorithm.HS256: - case JWTAlgorithm.RS256: - return signingCredentials.SignData(bytes); - - default: - throw new InvalidOperationException(); - } - } - - private string Encode() - { - string encodedHeader = JsonWebTokenUtilities.JsonEncode(this._header); - string encodedPayload = JsonWebTokenUtilities.JsonEncode(this._payload); - string encodedSignature = null; - if (this._signature != null) - { - encodedSignature = this._signature.ToBase64StringNoPadding(); - } - - return string.Format("{0}.{1}.{2}", encodedHeader, encodedPayload, encodedSignature); - } - - //OnDeserialized never gets called by serializer because we have a custom converter, so call this - //from there... - //[OnDeserialized] - private void OnDeserialized(/*StreamingContext context*/) - { - if (string.IsNullOrEmpty(this._encodedToken)) - throw new JsonWebTokenDeserializationException(); - - string[] fields = this._encodedToken.Split('.'); - - if (fields.Length != 3) - throw new JsonWebTokenDeserializationException(); - - this._header = JsonWebTokenUtilities.JsonDecode(fields[0]); - this._payload = JsonWebTokenUtilities.JsonDecode(fields[1]); - if(!string.IsNullOrEmpty(fields[2])) - { - this._signature = fields[2].FromBase64StringNoPadding(); - } - } - #endregion - - #region Nested Types - [JsonDictionary] - private abstract class JWTSectionBase : Dictionary - { - public override string ToString() - { - return JsonConvert.SerializeObject(this, JsonWebTokenUtilities.DefaultSerializerSettings); - } - - protected T TryGetValueOrDefault(string key) - { - object ret; - if(TryGetValue(key, out ret)) - { - //we have to special case DateTime - if (typeof(T) == typeof(DateTime)) - { - return (T)(object)ConvertDateTime(ret); - } - if (typeof(T).GetTypeInfo().IsEnum && ret is string) - { - return (T)Enum.Parse(typeof(T), (string)ret); - } - return (T)Convert.ChangeType(ret, typeof(T)); - } - - return default(T); - } - - protected System.DateTime ConvertDateTime(object obj) - { - if(obj is DateTime) - { - return (DateTime)obj; - } - else - { - //try to convert to a long, then - //convert from there, we expect it - //to be a Unix time - long longVal = Convert.ToInt64(obj); - - return longVal.FromUnixEpochTime(); - } - - } - } - - //these nested types comprise the header and the payload - //of the JWT, they are [DataContracts] so we can use JSON.NET - //to produce the JSON - - private class JWTHeader : JWTSectionBase - { - public JWTHeader() : base() - { - this.Type = "JWT"; - } - - internal string Type - { - get - { - return TryGetValueOrDefault(JsonWebTokenHeaderParameters.Type); - } - set - { - if (string.IsNullOrEmpty(value)) - { - this.Remove(JsonWebTokenHeaderParameters.Type); - } - else - { - this[JsonWebTokenHeaderParameters.Type] = value; - } - } - } - - internal JWTAlgorithm Algorithm - { - get - { - return TryGetValueOrDefault(JsonWebTokenHeaderParameters.Algorithm); - } - set - { - this[JsonWebTokenHeaderParameters.Algorithm] = value; - } - } - - internal string CertificateThumbprint - { - get - { - return TryGetValueOrDefault(JsonWebTokenHeaderParameters.X509CertificateThumbprint); - } - set - { - if(string.IsNullOrEmpty(value)) - { - this.Remove(JsonWebTokenHeaderParameters.X509CertificateThumbprint); - } - else - { - this[JsonWebTokenHeaderParameters.X509CertificateThumbprint] = value; - } - } - } - } - - private class JWTPayload : JWTSectionBase - { - public JWTPayload() { } - - internal JWTPayload(IEnumerable claims) - { - this.AddRange(JsonWebTokenUtilities.TranslateToJwtClaims(claims.AsEmptyIfNull())); - } - - internal string Audience - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.Audience); - } - set - { - ArgumentUtility.CheckStringForNullOrEmpty(value, nameof(Audience)); - - this[JsonWebTokenClaims.Audience] = value; - } - } - - internal string Issuer - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.Issuer); - } - set - { - ArgumentUtility.CheckStringForNullOrEmpty(value, nameof(Issuer)); - - this[JsonWebTokenClaims.Issuer] = value; - } - } - - internal string Subject - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.Subject); - } - set - { - ArgumentUtility.CheckStringForNullOrEmpty(value, nameof(Subject)); - - this[JsonWebTokenClaims.Subject] = value; - } - } - - internal string NameIdentifier - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.NameId); - } - set - { - if (string.IsNullOrEmpty(value)) - { - this.Remove(JsonWebTokenClaims.NameId); - } - else - { - this[JsonWebTokenClaims.NameId] = value; - } - } - } - - internal string IdentityProvider - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.IdentityProvider); - } - set - { - if (string.IsNullOrEmpty(value)) - { - this.Remove(JsonWebTokenClaims.IdentityProvider); - } - else - { - this[JsonWebTokenClaims.IdentityProvider] = value; - } - } - } - - internal DateTime ValidTo - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.ValidTo); - } - set - { - this[JsonWebTokenClaims.ValidTo] = value; - } - } - - internal DateTime ValidFrom - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.ValidFrom); - } - set - { - this[JsonWebTokenClaims.ValidFrom] = value; - } - } - - internal DateTime IssuedAt - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.IssuedAt); - } - set - { - if (value == default(DateTime)) - { - this.Remove(JsonWebTokenClaims.IssuedAt); - } - else - { - this[JsonWebTokenClaims.IssuedAt] = value; - } - } - } - - - internal bool TrustedForDelegation - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.TrustedForDelegation); - } - set - { - this[JsonWebTokenClaims.TrustedForDelegation] = value; - } - } - - internal string ApplicationIdentifier - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.AppId); - } - set - { - if (string.IsNullOrEmpty(value)) - { - this.Remove(JsonWebTokenClaims.AppId); - } - else - { - this[JsonWebTokenClaims.AppId] = value; - } - } - } - - internal JsonWebToken Actor - { - get - { - if (_actorToken == null && TryGetValueOrDefault(JsonWebTokenClaims.ActorToken) != null) - { - _actorToken = JsonConvert.DeserializeObject((string)this[JsonWebTokenClaims.ActorToken], JsonWebTokenUtilities.DefaultSerializerSettings); - } - return _actorToken; - } - set - { - if (value == null) - { - this.Remove(JsonWebTokenClaims.ActorToken); - } - else - { - this[JsonWebTokenClaims.ActorToken] = JsonConvert.SerializeObject(value); - } - } - } - - internal string ActorToken - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.ActorToken); - } - set - { - this[JsonWebTokenClaims.ActorToken] = value; - } - } - - internal string Scopes - { - get - { - return TryGetValueOrDefault(JsonWebTokenClaims.Scopes); - } - set - { - this[JsonWebTokenClaims.Scopes] = value; - } - } - - private JsonWebToken _actorToken; - } - - //this coverter converts back and forth from the JWT encoded string - //and this full type - internal class JsonWebTokenConverter : VssSecureJsonConverter - { - public override bool CanConvert(Type objectType) - { - return (objectType == typeof(JsonWebToken)); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) return null; - else if (reader.TokenType == JsonToken.String) - { - var ret = new JsonWebToken { EncodedToken = (string)reader.Value }; - ret.OnDeserialized(); - return ret; - } - else - throw new JsonWebTokenDeserializationException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - base.WriteJson(writer, value, serializer); - if (!(value is JsonWebToken)) throw new JsonWebTokenSerializationException(); - - writer.WriteValue(((JsonWebToken)value).EncodedToken); - } - } - #endregion - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenConstants.cs b/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenConstants.cs deleted file mode 100644 index af08b3c28..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenConstants.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Security.Claims; - -namespace GitHub.Services.WebApi.Jwt -{ - public static class JsonWebTokenClaims - { - public const string ActorToken = "actort"; - public const string Audience = "aud"; - public const string IssuedAt = "iat"; - public const string Issuer = "iss"; - public const string NameId = "nameid"; - public const string IdentityProvider = "identityprovider"; - public const string ValidTo = "exp"; - public const string ValidFrom = "nbf"; - public const string Scopes = "scp"; - public const string RefreshToken = "ret"; - public const string Source = "src"; - public const string Subject = "sub"; - public const string TrustedForDelegation = "trustedfordelegation"; - public const string NameIdLongName = ClaimTypes.NameIdentifier; - public const string IdentityProviderLongName = "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider"; - public const string TenantId = "tid"; - public const string TenantIdLongName = "http://schemas.microsoft.com/identity/claims/tenantid"; - public const string TokenId = "jti"; - public const string AppId = "appid"; - } - - internal static class JsonWebTokenHeaderParameters - { - internal const string Algorithm = "alg"; - internal const string Type = "typ"; - internal const string X509CertificateThumbprint = "x5t"; - internal const string JWTType = "JWT"; - internal const string JWTURNType = "urn:ietf:params:oauth:token-type:jwt"; - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenExceptions.cs b/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenExceptions.cs deleted file mode 100644 index 6e726795c..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenExceptions.cs +++ /dev/null @@ -1,230 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi.Jwt -{ - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "JsonWebTokenException", "GitHub.Services.WebApi.Jwt.JsonWebTokenException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class JsonWebTokenException : VssServiceException - { - public JsonWebTokenException(string message) - : base(message) - { - } - - public JsonWebTokenException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "JsonWebTokenValidationException", "GitHub.Services.WebApi.Jwt.JsonWebTokenValidationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class JsonWebTokenValidationException : JsonWebTokenException - { - public JsonWebTokenValidationException(string message) - : base(message) - { - } - - public JsonWebTokenValidationException(string message, Exception innerException) - : base(message, innerException) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "JsonWebTokenSerializationException", "GitHub.Services.WebApi.Jwt.JsonWebTokenSerializationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class JsonWebTokenSerializationException : JsonWebTokenException - { - public JsonWebTokenSerializationException() : base(JwtResources.SerializationException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "JsonWebTokenDeserializationException", "GitHub.Services.WebApi.Jwt.JsonWebTokenDeserializationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class JsonWebTokenDeserializationException : JsonWebTokenException - { - public JsonWebTokenDeserializationException() - : base(JwtResources.DeserializationException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "DigestUnsupportedException", "GitHub.Services.WebApi.Jwt.DigestUnsupportedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class DigestUnsupportedException : JsonWebTokenException - { - public DigestUnsupportedException(string supportedDigest, string invalidDigest) - : base(JwtResources.DigestUnsupportedException(supportedDigest, invalidDigest)) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidCredentialsException", "GitHub.Services.WebApi.Jwt.InvalidCredentialsException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidCredentialsException : JsonWebTokenException - { - public InvalidCredentialsException(string message) - : base(message) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "SignatureAlgorithmUnsupportedException", "GitHub.Services.WebApi.Jwt.SignatureAlgorithmUnsupportedException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class SignatureAlgorithmUnsupportedException : JsonWebTokenException - { - public SignatureAlgorithmUnsupportedException(string invalidAlgorithm) - : base(JwtResources.SignatureAlgorithmUnsupportedException(invalidAlgorithm)) - { - } - - public SignatureAlgorithmUnsupportedException(int providerType) - : base(JwtResources.ProviderTypeUnsupported(providerType)) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidClockSkewException", "GitHub.Services.WebApi.Jwt.InvalidClockSkewException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidClockSkewException : JsonWebTokenException - { - public InvalidClockSkewException() - : base(JwtResources.InvalidClockSkewException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidValidFromValueException", "GitHub.Services.WebApi.Jwt.InvalidValidFromValueException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidValidFromValueException : JsonWebTokenException - { - public InvalidValidFromValueException() - : base(JwtResources.InvalidValidFromValueException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidValidToValueException", "GitHub.Services.WebApi.Jwt.InvalidValidToValueException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidValidToValueException : JsonWebTokenException - { - public InvalidValidToValueException() - : base(JwtResources.InvalidValidToValueException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ValidFromAfterValidToException", "GitHub.Services.WebApi.Jwt.ValidFromAfterValidToException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ValidFromAfterValidToException : JsonWebTokenException - { - public ValidFromAfterValidToException() - : base(JwtResources.ValidFromAfterValidToException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "ActorValidationException", "GitHub.Services.WebApi.Jwt.ActorValidationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ActorValidationException : JsonWebTokenValidationException - { - public ActorValidationException() - : base(JwtResources.ActorValidationException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "TokenNotYetValidException", "GitHub.Services.WebApi.Jwt.TokenNotYetValidException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class TokenNotYetValidException : JsonWebTokenValidationException - { - public TokenNotYetValidException() - : base(JwtResources.TokenNotYetValidException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "TokenExpiredException", "GitHub.Services.WebApi.Jwt.TokenExpiredException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class TokenExpiredException : JsonWebTokenValidationException - { - public TokenExpiredException() - : base(JwtResources.TokenExpiredException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidAudienceException", "GitHub.Services.WebApi.Jwt.InvalidAudienceException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidAudienceException : JsonWebTokenValidationException - { - public InvalidAudienceException() - : base(JwtResources.InvalidAudienceException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidTokenException", "GitHub.Services.WebApi.Jwt.InvalidTokenException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidTokenException : JsonWebTokenValidationException - { - public InvalidTokenException(string message) - : base(message) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "SignatureValidationException", "GitHub.Services.WebApi.Jwt.SignatureValidationException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class SignatureValidationException : JsonWebTokenValidationException - { - public SignatureValidationException() - : base(JwtResources.SignatureValidationException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidIssuerException", "GitHub.Services.WebApi.Jwt.InvalidIssuerException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidIssuerException : JsonWebTokenValidationException - { - public InvalidIssuerException() - : base(JwtResources.InvalidIssuerException()) - { - } - } - - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "InvalidScopeException", "GitHub.Services.WebApi.Jwt.InvalidScopeException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class InvalidScopeException : JsonWebTokenValidationException - { - public InvalidScopeException() - : base(JwtResources.TokenScopeNotAuthorizedException()) - { - - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenUtilities.cs b/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenUtilities.cs deleted file mode 100644 index d296666b7..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenUtilities.cs +++ /dev/null @@ -1,321 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Text; -using GitHub.Services.Common; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace GitHub.Services.WebApi.Jwt -{ - public static class JsonWebTokenUtilities - { - static JsonWebTokenUtilities() - { - DefaultSerializerSettings = new JsonSerializerSettings(); - DefaultSerializerSettings.Converters.Add(new UnixEpochDateTimeConverter()); - DefaultSerializerSettings.Converters.Add(new StringEnumConverter()); - } - - internal static readonly JsonSerializerSettings DefaultSerializerSettings; - - internal static readonly short MinKeySize = 2048; - - internal static string JsonEncode(this T obj) - { - return JsonEncode((object)obj); - } - - internal static string JsonEncode(object o) - { - ArgumentUtility.CheckForNull(o, nameof(o)); - - string json = JsonConvert.SerializeObject(o, DefaultSerializerSettings); - - return Encoding.UTF8.GetBytes(json).ToBase64StringNoPadding(); - } - - internal static T JsonDecode(string encodedString) - { - ArgumentUtility.CheckStringForNullOrEmpty(encodedString, nameof(encodedString)); - - byte[] bytes = encodedString.FromBase64StringNoPadding(); - - string json = Encoding.UTF8.GetString(bytes); - - return JsonConvert.DeserializeObject(json, DefaultSerializerSettings); - } - - internal static IDictionary TranslateToJwtClaims(IEnumerable claims) - { - ArgumentUtility.CheckForNull(claims, nameof(claims)); - - Dictionary ret = new Dictionary(); - - //there are two claim names that get special treatment - foreach (Claim claim in claims) - { - string claimName = claim.Type; - if (string.Compare(claimName, JsonWebTokenClaims.NameIdLongName, StringComparison.Ordinal) == 0) - { - claimName = JsonWebTokenClaims.NameId; - } - else if (string.Compare(claimName, JsonWebTokenClaims.IdentityProviderLongName, StringComparison.Ordinal) == 0) - { - claimName = JsonWebTokenClaims.IdentityProvider; - } - - ret.Add(claimName, claim.Value); - } - - return ret; - } - - internal static IEnumerable TranslateFromJwtClaims(IDictionary claims) - { - ArgumentUtility.CheckForNull(claims, nameof(claims)); - - List ret = new List(); - - //there are two claim names that get special treatment - foreach (var claim in claims) - { - string claimName = claim.Key; - if (string.Compare(claimName, JsonWebTokenClaims.NameId, StringComparison.Ordinal) == 0) - { - claimName = JsonWebTokenClaims.NameIdLongName; - } - else if (string.Compare(claimName, JsonWebTokenClaims.IdentityProvider, StringComparison.Ordinal) == 0) - { - claimName = JsonWebTokenClaims.IdentityProviderLongName; - } - - ret.Add(new Claim(claimName, claim.Value.ToString())); - } - - return ret; - } - - internal static IEnumerable ExtractClaims(this JsonWebToken token) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - - return TranslateFromJwtClaims(token.Payload); - } - - public static bool IsExpired(this JsonWebToken token) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - - return DateTime.UtcNow > token.ValidTo; - } - - internal static JWTAlgorithm ValidateSigningCredentials(VssSigningCredentials credentials, bool allowExpiredToken = false) - { - if (credentials == null) - { - return JWTAlgorithm.None; - } - - if (!credentials.CanSignData) - { - throw new InvalidCredentialsException(JwtResources.SigningTokenNoPrivateKey()); - } - - if (!allowExpiredToken && credentials.ValidTo.ToUniversalTime() < (DateTime.UtcNow - TimeSpan.FromMinutes(5))) - { - throw new InvalidCredentialsException(JwtResources.SigningTokenExpired()); - } - - return credentials.SignatureAlgorithm; - } - - public static ClaimsPrincipal ValidateToken(this JsonWebToken token, JsonWebTokenValidationParameters parameters) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(parameters, nameof(parameters)); - - ClaimsIdentity actorIdentity = ValidateActor(token, parameters); - ValidateLifetime(token, parameters); - ValidateAudience(token, parameters); - ValidateSignature(token, parameters); - ValidateIssuer(token, parameters); - - ClaimsIdentity identity = new ClaimsIdentity("Federation", parameters.IdentityNameClaimType, ClaimTypes.Role); - - if (actorIdentity != null) - { - identity.Actor = actorIdentity; - } - - IEnumerable claims = token.ExtractClaims(); - - foreach (Claim claim in claims) - { - identity.AddClaim(new Claim(claim.Type, claim.Value, claim.ValueType, token.Issuer)); - } - - return new ClaimsPrincipal(identity); - } - - private static ClaimsIdentity ValidateActor(JsonWebToken token, JsonWebTokenValidationParameters parameters) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(parameters, nameof(parameters)); - - if (!parameters.ValidateActor) - { - return null; - } - - //this recursive call with check the parameters - ClaimsPrincipal principal = token.Actor.ValidateToken(parameters.ActorValidationParameters); - - if (!(principal?.Identity is ClaimsIdentity)) - { - throw new ActorValidationException(); - } - - return (ClaimsIdentity)principal.Identity; - } - - private static void ValidateLifetime(JsonWebToken token, JsonWebTokenValidationParameters parameters) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(parameters, nameof(parameters)); - - if ((parameters.ValidateNotBefore || parameters.ValidateExpiration) && (parameters.ClockSkewInSeconds < 0)) - { - throw new InvalidClockSkewException(); - } - - TimeSpan skew = TimeSpan.FromSeconds(parameters.ClockSkewInSeconds); - - if (parameters.ValidateNotBefore && token.ValidFrom == default(DateTime)) - { - throw new InvalidValidFromValueException(); - } - - if (parameters.ValidateExpiration && token.ValidTo == default(DateTime)) - { - throw new InvalidValidToValueException(); - } - - if (parameters.ValidateExpiration && parameters.ValidateNotBefore && (token.ValidFrom > token.ValidTo)) - { - throw new ValidFromAfterValidToException(); - } - - if (parameters.ValidateNotBefore && (token.ValidFrom > (DateTime.UtcNow + skew))) - { - throw new TokenNotYetValidException(); //validation exception - } - - if (parameters.ValidateExpiration && (token.ValidTo < (DateTime.UtcNow - skew))) - { - throw new TokenExpiredException(); //validation exception - } - } - - private static void ValidateAudience(JsonWebToken token, JsonWebTokenValidationParameters parameters) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(parameters, nameof(parameters)); - - if (!parameters.ValidateAudience) - { - return; - } - - ArgumentUtility.CheckStringForNullOrEmpty(token.Audience, nameof(token.Audience)); - ArgumentUtility.CheckEnumerableForNullOrEmpty(parameters.AllowedAudiences, nameof(parameters.AllowedAudiences)); - - foreach (string audience in parameters.AllowedAudiences) - { - if (string.Compare(audience, token.Audience, StringComparison.OrdinalIgnoreCase) == 0) - { - return; - } - } - - throw new InvalidAudienceException(); //validation exception; - } - - private static void ValidateSignature(JsonWebToken token, JsonWebTokenValidationParameters parameters) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(parameters, nameof(parameters)); - - if (!parameters.ValidateSignature) - { - return; - } - - string encodedData = token.EncodedToken; - - string[] parts = encodedData.Split('.'); - - if (parts.Length != 3) - { - throw new InvalidTokenException(JwtResources.EncodedTokenDataMalformed()); //validation exception - } - - if (string.IsNullOrEmpty(parts[2])) - { - throw new InvalidTokenException(JwtResources.SignatureNotFound()); //validation exception - } - - if (token.Algorithm == JWTAlgorithm.None) - { - throw new InvalidTokenException(JwtResources.InvalidSignatureAlgorithm()); //validation exception - } - - ArgumentUtility.CheckForNull(parameters.SigningCredentials, nameof(parameters.SigningCredentials)); - - //ArgumentUtility.CheckEnumerableForNullOrEmpty(parameters.SigningToken.SecurityKeys, nameof(parameters.SigningToken.SecurityKeys)); - - byte[] sourceInput = Encoding.UTF8.GetBytes(string.Format("{0}.{1}", parts[0], parts[1])); - - byte[] sourceSignature = parts[2].FromBase64StringNoPadding(); - - - try - { - if (parameters.SigningCredentials.VerifySignature(sourceInput, sourceSignature)) - { - return; - } - } - catch (Exception) - { - //swallow exceptions here, we'll throw if nothing works... - } - - throw new SignatureValidationException(); //valiation exception - } - - private static void ValidateIssuer(JsonWebToken token, JsonWebTokenValidationParameters parameters) - { - ArgumentUtility.CheckForNull(token, nameof(token)); - ArgumentUtility.CheckForNull(parameters, nameof(parameters)); - - if (!parameters.ValidateIssuer) - { - return; - } - - ArgumentUtility.CheckStringForNullOrEmpty(token.Issuer, nameof(token.Issuer)); - ArgumentUtility.CheckEnumerableForNullOrEmpty(parameters.ValidIssuers, nameof(parameters.ValidIssuers)); - - foreach (string issuer in parameters.ValidIssuers) - { - if (string.Compare(issuer, token.Issuer, StringComparison.OrdinalIgnoreCase) == 0) - { - return; - } - } - - throw new InvalidIssuerException(); //validation exception; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenValidationParameters.cs b/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenValidationParameters.cs deleted file mode 100644 index 9e039fe23..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/JsonWebTokenValidationParameters.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System.Collections.Generic; -using System.Security.Claims; - -namespace GitHub.Services.WebApi.Jwt -{ - public sealed class JsonWebTokenValidationParameters - { - public JsonWebTokenValidationParameters() - { - ValidateActor = false; - ValidateAudience = true; - ValidateIssuer = true; - ValidateExpiration = true; - ValidateNotBefore = false; - ValidateSignature = true; - ClockSkewInSeconds = 300; - IdentityNameClaimType = ClaimTypes.NameIdentifier; - } - - public bool ValidateActor - { - get; - set; - } - - public bool ValidateAudience - { - get; - set; - } - - public bool ValidateIssuer - { - get; - set; - } - - public bool ValidateExpiration - { - get; - set; - } - - public bool ValidateNotBefore - { - get; - set; - } - - public bool ValidateSignature - { - get; - set; - } - - public JsonWebTokenValidationParameters ActorValidationParameters - { - get; - set; - } - - public IEnumerable AllowedAudiences - { - get; - set; - } - - public int ClockSkewInSeconds - { - get; - set; - } - - public VssSigningCredentials SigningCredentials - { - get; - set; - } - - public IEnumerable ValidIssuers - { - get; - set; - } - - public string IdentityNameClaimType - { - get; - set; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Jwt/UnixEpochDateTimeConverter.cs b/src/Sdk/WebApi/WebApi/Jwt/UnixEpochDateTimeConverter.cs deleted file mode 100644 index a2cbf66d0..000000000 --- a/src/Sdk/WebApi/WebApi/Jwt/UnixEpochDateTimeConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using GitHub.Services.Common; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace GitHub.Services.WebApi.Jwt -{ - class UnixEpochDateTimeConverter : DateTimeConverterBase - { - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - long unixVal = reader.Value is string ? long.Parse((string) reader.Value) : (long)reader.Value; - - return unixVal.FromUnixEpochTime(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - long unixVal = ((DateTime)value).ToUnixEpochTime(); - - writer.WriteValue(unixVal); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Location/Interfaces.cs b/src/Sdk/WebApi/WebApi/Location/Interfaces.cs deleted file mode 100644 index 487d09189..000000000 --- a/src/Sdk/WebApi/WebApi/Location/Interfaces.cs +++ /dev/null @@ -1,592 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Location; - -namespace GitHub.Services.WebApi.Location -{ - /// - /// The service responsible for providing a connection to a Team - /// Foundation Server as well as the locations of other services that - /// are available on it. - /// - [VssClientServiceImplementation(typeof(LocationService))] - public interface ILocationService : IVssClientService - { - /// - /// Gets the provider of location data specified by the given location area guid. - /// The provider could be local or remote depending on where the area data is hosted - /// in the location hierarchy in relation to this service instance. Returns null if - /// the area could not be found - /// - /// - /// - ILocationDataProvider GetLocationData(Guid locationAreaIdentifier); - - /// - /// Gets the URL of the location service for the given location area guid and access mapping moniker. - /// If the area could not be found this method will return null. This is useful for getting the - /// base URL of service hosts, or of other service instances or resource areas. - /// - /// To find a specific service definition contained in the given location area and to formulate - /// the proper URL for a specific resource in that location area, you would need to - /// retrieve the location data for that area. This operation is simplified by calling GetLocationData - /// - /// - /// - String GetLocationServiceUrl(Guid locationAreaIdentifier); - - /// - /// Gets the URL of the location service for the given location area guid and access mapping moniker. - /// If the area could not be found this method will return null. This is useful for getting the - /// base URL of service hosts, or of other service instances or resource areas. - /// - /// To find a specific service definition contained in the given location area and to formulate - /// the proper URL for a specific resource in that location area, you would need to - /// retrieve the location data for that area. This operation is simplified by calling GetLocationData - /// - /// - /// - /// - String GetLocationServiceUrl(Guid locationAreaIdentifier, String accessMappingMoniker); - - #region Async APIs - - /// - /// Gets the provider of location data specified by the given location area guid. - /// The provider could be local or remote depending on where the area data is hosted - /// in the location hierarchy in relation to this service instance. Returns null if - /// the area could not be found - /// - /// - /// - /// - Task GetLocationDataAsync( - Guid locationAreaIdentifier, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Gets the URL of the location service for the given location area guid and access mapping moniker. - /// If the area could not be found this method will return null. This is useful for getting the - /// base URL of service hosts, or of other service instances or resource areas. - /// - /// To find a specific service definition contained in the given location area and to formulate - /// the proper URL for a specific resource in that location area, you would need to - /// retrieve the location data for that area. This operation is simplified by calling GetLocationData - /// - /// - /// - /// - /// - Task GetLocationServiceUrlAsync( - Guid locationAreaIdentifier, - String accessMappingMoniker = null, - CancellationToken cancellationToken = default(CancellationToken)); - - #endregion - } - - /// - /// The service responsible for providing a connection to a Team - /// Foundation Server as well as the locations of other services that - /// are available on it. - /// - public interface ILocationDataProvider - { - /// - /// The unique identifier for this server. - /// - Guid InstanceId { get; } - - - /// - /// The identifier of the type of server instance. - /// - Guid InstanceType { get; } - - /// - /// The AccessMapping for the current connection to the server. Note, it is - /// possible that the current ClientAccessMapping is not a member of the - /// ConfiguredAccessMappings if the access point this client used to connect to - /// the server has not been configured on it. This will never be null. - /// - AccessMapping ClientAccessMapping { get; } - - /// - /// The default AccessMapping for this location service. This will never be null. - /// - AccessMapping DefaultAccessMapping { get; } - - /// - /// All of the AccessMappings that this location service knows about. Because a - /// given location service can inherit AccessMappings from its parent these - /// AccessMappings may exist on this location service or its parent. - /// - IEnumerable ConfiguredAccessMappings { get; } - - // - // Saves the provided ServiceDefinition within the location service. This - // operation will assign the Identifier property on the ServiceDefinition object - // if one is not already assigned. Any AccessMappings referenced in the - // LocationMappings property must already be configured with the location - // service. - // - // - // The ServiceDefinition to save. This object will be updated with a new - // Identifier if one is not already assigned. - // - //void SaveServiceDefinition( - // ServiceDefinition serviceDefinition); - - // - // Saves the provided ServiceDefinitions within the location service. This - // operation will assign the Identifier property on the ServiceDefinition - // objects if one is not already assigned. Any AccessMappings referenced in - // the LocationMappings property must already be configured with the location - // service. - // - // - // The ServiceDefinitions to save. These objects will be updated with a new - // Identifier if one is not already assigned. - // - //void SaveServiceDefinitions( - // IEnumerable serviceDefinitions); - - // - // Removes the ServiceDefinition with the specified service type and - // service identifier from the location serivce. - // - // - // The service type of the ServiceDefinition to remove. - // - // - // The service identifier of the ServiceDefinition to remove. - // - //void RemoveServiceDefinition( - // String serviceType, - // Guid serviceIdentifier); - - // - // Removes the specified ServiceDefinition from the location service. - // - // - // The ServiceDefinition to remove. This must be a ServiceDefinition that is - // already registered in the location service. - // Equality is decided by matching the service type and the identifier. - // - //void RemoveServiceDefinition( - // ServiceDefinition serviceDefinition); - - // - // Removes the specified ServiceDefinitions from the location service. - // - // - // The ServiceDefinitions to remove. These must be ServiceDefinitions that are - // already registered in the location service. - // Equality is decided by matching the service type and the identifier. - // - //void RemoveServiceDefinitions( - // IEnumerable serviceDefinitions); - - /// - /// Finds the ServiceDefinition with the specified service type and service - /// identifier. If no matching ServiceDefinition exists, null is returned. - /// - /// - /// The service type of the ServiceDefinition to find. - /// - /// - /// The service identifier of the ServiceDefinition - /// to find. - /// - /// - /// The ServiceDefinition with the specified service type and service identifier. - /// If no matching ServiceDefinition exists, null is returned. - /// - ServiceDefinition FindServiceDefinition( - String serviceType, - Guid serviceIdentifier); - - /// - /// Finds the ServiceDefinitions for all of the services with the - /// specified service type. If no ServiceDefinitions of this type - /// exist, an empty enumeration will be returned. - /// - /// - /// The case-insensitive string that identifies what type of service is being - /// requested. If this value is null, ServiceDefinitions for all services - /// registered with this location service will be returned. - /// - /// - /// ServiceDefinitions for all of the services with the specified service type. - /// If no ServiceDefinitions of this type exist, an empty enumeration will be - /// returned. - /// - IEnumerable FindServiceDefinitions( - String serviceType); - - /// - /// Returns the location for the ServiceDefintion associated with the ServiceType - /// and ServiceIdentifier that should be used based on the current connection. - /// If a ServiceDefinition with the ServiceType and ServiceIdentifier does not - /// exist then null will be returned. If a ServiceDefinition with the ServiceType - /// and ServiceIdentifier is found then a location will be returned if the - /// ServiceDefinition is well formed (otherwise an exception will be thrown). - /// - /// When determining what location to return for the ServiceDefinition and - /// current connection the following rules will be applied: - /// - /// 1. Try to find a location for the ClientAccessMapping. - /// 2. Try to find a location for the DefaultAccessMapping. - /// 3. Use the first location in the LocationMappings list. - /// - /// - /// The service type of the ServiceDefinition to find the location for. - /// - /// - /// The service identifier of the ServiceDefinition to find the location for. - /// - /// - /// The location for the ServiceDefinition with the provided service type and - /// identifier that should be used based on the current connection. - /// - String LocationForCurrentConnection( - String serviceType, - Guid serviceIdentifier); - - /// - /// Returns the location for the ServiceDefintion that should be used based on - /// the current connection. This method will never return null or empty. If it - /// succeeds it will return a targetable location for the provided - /// ServiceDefinition. - /// - /// When determining what location to return for the ServiceDefinition and - /// current connection the following rules will be applied: - /// - /// 1. Try to find a location for the ClientAccessMapping. - /// 2. Try to find a location for the DefaultAccessMapping. - /// 3. Use the first location in the LocationMappings list. - /// - /// - /// The ServiceDefinition to find the location for. - /// - /// - /// The location for the given ServiceDefinition that should be - /// used based on the current connection. - /// - String LocationForCurrentConnection( - ServiceDefinition serviceDefinition); - - /// - /// Returns the location for the ServiceDefinition that has the specified - /// service type and service identifier for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - /// - /// The service type of the ServiceDefinition to find the location for. - /// - /// - /// The service identifier of the ServiceDefinition to find the location for. - /// - /// The AccessMapping to find the location for. - /// - /// The location for the ServiceDefinition for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - String LocationForAccessMapping( - String serviceType, - Guid serviceIdentifier, - AccessMapping accessMapping); - - /// - /// Returns the location for the ServiceDefinition for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - /// - /// The ServiceDefinition to find the location for. - /// - /// The AccessMapping to find the location for. - /// - /// The location for the ServiceDefinition for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - String LocationForAccessMapping( - ServiceDefinition serviceDefinition, - AccessMapping accessMapping); - - // - // Configures the AccessMapping with the provided moniker to have the provided - // display name and access point. This function also allows for this - // AccessMapping to be made the default AccessMapping. - // - // - // A string that uniquely identifies this AccessMapping. This value cannot be - // null or empty. - // - // - // Display name for this AccessMapping. This value cannot be null or empty. - // - // - // This is the base url for the server that will map to this AccessMapping. - // This value cannot be null or empty. - // - // The access point should consist of the scheme, authority, port and web - // application virtual path of the targetable server address. For example, an - // access point will most commonly look like this: - // - // http://server:8080/tfs/ - // - // - // If true, this AccessMapping will be made the default AccessMapping. If false, - // the default AccessMapping will not change. - // - // The AccessMapping object that was just configured. - //AccessMapping ConfigureAccessMapping( - // String moniker, - // String displayName, - // String accessPoint, - // Boolean makeDefault); - - // - // Sets the default AccessMapping to the AccessMapping passed in. - // - // - // The AccessMapping that should become the default AccessMapping. This - // AccessMapping must already be configured with this location service. - // - //void SetDefaultAccessMapping( - // AccessMapping accessMapping); - - /// - /// Gets the AccessMapping with the specified moniker. Returns null - /// if an AccessMapping with the supplied moniker does not exist. - /// - /// - /// The moniker for the desired AccessMapping. This value cannot be null or - /// empty. - /// - /// - /// The AccessMapping with the supplied moniker or null if one does not exist. - /// - AccessMapping GetAccessMapping( - String moniker); - - // - // Removes an AccessMapping and all of the locations that are mapped - // to it within ServiceDefinitions. - // - // The moniker for the AccessMapping to remove. - //void RemoveAccessMapping( - // String moniker); - - /// - /// Get the API resource locations -- a collection of versioned URL paths that - /// are keyed by a location identitifer - /// - /// - ApiResourceLocationCollection GetResourceLocations(); - - #region Async APIs - - /// - /// The unique identifier for this server. - /// - Task GetInstanceIdAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// The identifier of the type of server instance. - /// - Task GetInstanceTypeAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// The AccessMapping for the current connection to the server. Note, it is - /// possible that the current ClientAccessMapping is not a member of the - /// ConfiguredAccessMappings if the access point this client used to connect to - /// the server has not been configured on it. This will never be null. - /// - /// - /// - Task GetClientAccessMappingAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// The default AccessMapping for this location service. This will never be null. - /// - /// - /// - Task GetDefaultAccessMappingAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// All of the AccessMappings that this location service knows about. Because a - /// given location service can inherit AccessMappings from its parent these - /// AccessMappings may exist on this location service or its parent. - /// - /// - /// - Task> GetConfiguredAccessMappingsAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Finds the ServiceDefinition with the specified service type and service - /// identifier. If no matching ServiceDefinition exists, null is returned. - /// - /// - /// The service type of the ServiceDefinition to find. - /// - /// - /// The service identifier of the ServiceDefinition - /// to find. - /// - /// - /// The ServiceDefinition with the specified service type and service identifier. - /// If no matching ServiceDefinition exists, null is returned. - /// - Task FindServiceDefinitionAsync( - String serviceType, - Guid serviceIdentifier, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Finds the ServiceDefinitions for all of the services with the - /// specified service type. If no ServiceDefinitions of this type - /// exist, an empty enumeration will be returned. - /// - /// - /// The case-insensitive string that identifies what type of service is being - /// requested. If this value is null, ServiceDefinitions for all services - /// registered with this location service will be returned. - /// - /// - /// ServiceDefinitions for all of the services with the specified service type. - /// If no ServiceDefinitions of this type exist, an empty enumeration will be - /// returned. - /// - Task> FindServiceDefinitionsAsync( - String serviceType, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Returns the location for the ServiceDefintion associated with the ServiceType - /// and ServiceIdentifier that should be used based on the current connection. - /// If a ServiceDefinition with the ServiceType and ServiceIdentifier does not - /// exist then null will be returned. If a ServiceDefinition with the ServiceType - /// and ServiceIdentifier is found then a location will be returned if the - /// ServiceDefinition is well formed (otherwise an exception will be thrown). - /// - /// When determining what location to return for the ServiceDefinition and - /// current connection the following rules will be applied: - /// - /// 1. Try to find a location for the ClientAccessMapping. - /// 2. Try to find a location for the DefaultAccessMapping. - /// 3. Use the first location in the LocationMappings list. - /// - /// - /// The service type of the ServiceDefinition to find the location for. - /// - /// - /// The service identifier of the ServiceDefinition to find the location for. - /// - /// - /// The location for the ServiceDefinition with the provided service type and - /// identifier that should be used based on the current connection. - /// - Task LocationForCurrentConnectionAsync( - String serviceType, - Guid serviceIdentifier, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Returns the location for the ServiceDefintion that should be used based on - /// the current connection. This method will never return null or empty. If it - /// succeeds it will return a targetable location for the provided - /// ServiceDefinition. - /// - /// When determining what location to return for the ServiceDefinition and - /// current connection the following rules will be applied: - /// - /// 1. Try to find a location for the ClientAccessMapping. - /// 2. Try to find a location for the DefaultAccessMapping. - /// 3. Use the first location in the LocationMappings list. - /// - /// - /// The ServiceDefinition to find the location for. - /// - /// - /// The location for the given ServiceDefinition that should be - /// used based on the current connection. - /// - Task LocationForCurrentConnectionAsync( - ServiceDefinition serviceDefinition, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Returns the location for the ServiceDefinition that has the specified - /// service type and service identifier for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - /// - /// The service type of the ServiceDefinition to find the location for. - /// - /// - /// The service identifier of the ServiceDefinition to find the location for. - /// - /// The AccessMapping to find the location for. - /// - /// The location for the ServiceDefinition for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - Task LocationForAccessMappingAsync( - String serviceType, - Guid serviceIdentifier, - AccessMapping accessMapping, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Returns the location for the ServiceDefinition for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - /// - /// The ServiceDefinition to find the location for. - /// - /// The AccessMapping to find the location for. - /// - /// The location for the ServiceDefinition for the provided - /// AccessMapping. If this ServiceDefinition is FullyQualified and no - /// LocationMapping exists for this AccessMapping then null will be returned. - /// - Task LocationForAccessMappingAsync( - ServiceDefinition serviceDefinition, - AccessMapping accessMapping, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Gets the AccessMapping with the specified moniker. Returns null - /// if an AccessMapping with the supplied moniker does not exist. - /// - /// - /// The moniker for the desired AccessMapping. This value cannot be null or - /// empty. - /// - /// - /// The AccessMapping with the supplied moniker or null if one does not exist. - /// - Task GetAccessMappingAsync( - String moniker, - CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Get the API resource locations -- a collection of versioned URL paths that - /// are keyed by a location identitifer - /// - /// - Task GetResourceLocationsAsync(CancellationToken cancellationToken = default(CancellationToken)); - - #endregion - } -} diff --git a/src/Sdk/WebApi/WebApi/Location/LocationCacheManager.cs b/src/Sdk/WebApi/WebApi/Location/LocationCacheManager.cs deleted file mode 100644 index aad8fc550..000000000 --- a/src/Sdk/WebApi/WebApi/Location/LocationCacheManager.cs +++ /dev/null @@ -1,941 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Threading; -using System.Xml; -using GitHub.Services.Common; -using GitHub.Services.Location; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.WebApi.Location -{ - /// - /// This class is responsible for managing both the in-memory and disk cache - /// for the location service. - /// - internal class LocationCacheManager - { - /// - /// Creates a new cache manager for the serverGuid passed in. - /// - /// - public LocationCacheManager(Guid serverGuid, Guid serviceOwner, Uri connectionBaseUrl) - { - m_cacheAvailable = (serverGuid.Equals(Guid.Empty)) ? false : true; - - m_lastChangeId = -1; - m_cacheExpirationDate = DateTime.MinValue; - -#if !NETSTANDARD - ClientCacheTimeToLive = VssClientSettings.ClientCacheTimeToLive; -#endif - if (serviceOwner == Guid.Empty) - { - // For a legacy server (which didn't return serviceOwner in the connectionData), let's not try to break anything - // just use the old path. - // We should be able to remove this case eventually. - m_cacheFilePath = Path.Combine(Path.Combine(VssClientSettings.ClientCacheDirectory, serverGuid.ToString()), - s_cacheFileName); - } - else - { - m_cacheFilePath = Path.Combine(Path.Combine(Path.Combine(VssClientSettings.ClientCacheDirectory, serverGuid.ToString()), serviceOwner.ToString()), - s_cacheFileName); - } - - m_cacheLocallyFresh = false; - m_accessMappings = new Dictionary(VssStringComparer.AccessMappingMoniker); - m_services = new Dictionary>(VssStringComparer.ServiceType); - m_cachedMisses = new HashSet(VssStringComparer.ServiceType); - - m_connectionBaseUrl = connectionBaseUrl; - m_locationXmlOperator = new LocationXmlOperator(true); - } - - /// - /// True if there is a cache on disk available for this server - /// - public Boolean LocalCacheAvailable - { - get - { - EnsureDiskCacheLoaded(); - - return m_cacheAvailable; - } - } - - /// - /// Whether or not the cached data has expired (and should be refreshed) - /// - internal Boolean CacheDataExpired - { - get - { - // A) Cache is available (i.e. we're not relying solely on the memory cache because the disk cache file was unavailable) - // and B) The memory cache is correct with the disk cache (necessary to enforce expiration) - // and C) It is after the expiration time - return m_cacheAvailable && m_cacheLocallyFresh && DateTime.UtcNow >= m_cacheExpirationDate; - } - } - - public AccessMapping ClientAccessMapping - { - get - { - m_accessLock.EnterReadLock(); - - try - { - return !CacheDataExpired ? m_clientAccessMapping : null; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - } - - public AccessMapping DefaultAccessMapping - { - get - { - m_accessLock.EnterReadLock(); - - try - { - return !CacheDataExpired ? m_defaultAccessMapping : null; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - } - - public String WebApplicationRelativeDirectory - { - get - { - return m_webApplicationRelativeDirectory; - } - set - { - m_webApplicationRelativeDirectory = String.IsNullOrEmpty(value) ? m_webApplicationRelativeDirectory : value; - } - } - - public void ClearIfCacheNotFresh(Int32 serverLastChangeId) - { - if (serverLastChangeId != m_lastChangeId) - { - m_accessLock.EnterWriteLock(); - - try - { - if (serverLastChangeId != m_lastChangeId) - { - m_accessMappings.Clear(); - m_services.Clear(); - m_cachedMisses.Clear(); - m_lastChangeId = -1; - m_cacheExpirationDate = DateTime.MinValue; - } - } - finally - { - m_accessLock.ExitWriteLock(); - } - } - } - - /// - /// Removes services from both the in-memory cache and the disk cache. - /// - /// The service definitions to remove. - /// The lastChangeId the server returned when - /// it performed this operation. - public void RemoveServices(IEnumerable serviceDefinitions, Int32 lastChangeId) - { - EnsureDiskCacheLoaded(); - - m_accessLock.EnterWriteLock(); - - try - { - foreach (ServiceDefinition serviceDefinition in serviceDefinitions) - { - Dictionary definitions = null; - if (!m_services.TryGetValue(serviceDefinition.ServiceType, out definitions)) - { - continue; - } - - // If the entry is removed and there are no more definitions of this type, remove that - // entry from the services structure - if (definitions.Remove(serviceDefinition.Identifier) && definitions.Count == 0) - { - m_services.Remove(serviceDefinition.ServiceType); - } - } - - SetLastChangeId(lastChangeId, false); - Debug.Assert(m_lastChangeId == -1 || m_services.Count > 0); - WriteCacheToDisk(); - } - finally - { - m_accessLock.ExitWriteLock(); - } - } - - /// - /// Returns the access mapping for the provided moniker. - /// - /// The moniker of the access mapping to - /// return. - /// The access mapping for the provided moniker or null - /// if an access mapping for the moniker doesn't exist.. - public AccessMapping GetAccessMapping(String moniker) - { - ArgumentUtility.CheckStringForNullOrEmpty(moniker, "moniker"); - EnsureDiskCacheLoaded(); - m_accessLock.EnterReadLock(); - - try - { - if (CacheDataExpired) - { - return null; - } - - AccessMapping accessMapping; - m_accessMappings.TryGetValue(moniker, out accessMapping); - - return accessMapping; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - - /// - /// Returns the service definition for the service with the - /// provided service type and identifier. Null will be returned - /// if there is no entry in the cache for this service. - /// - /// The service type we are looking for. - /// The identifier for the specific - /// service instance we are looking for. - /// The service definition for the service with the - /// provided service type and identifier. Null will be returned - /// if there is no entry in the cache for this service. - public Boolean TryFindService(String serviceType, Guid serviceIdentifier, out ServiceDefinition serviceDefinition) - { - EnsureDiskCacheLoaded(); - m_accessLock.EnterReadLock(); - - try - { - Dictionary services = null; - serviceDefinition = null; - - if (CacheDataExpired) - { - return false; - } - - if (m_services.TryGetValue(serviceType, out services)) - { - if (services.TryGetValue(serviceIdentifier, out serviceDefinition)) - { - return true; - } - } - - // Look in our cachedMisses to see if we can find it there. - if (m_cachedMisses.Contains(BuildCacheMissString(serviceType, serviceIdentifier))) - { - // We found an entry in cached misses so return true. - return true; - } - - return false; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - - /// - /// Finds all services with the provided service type. - /// - /// The service type we are looking for. - /// All of the service definitions with the serviceType that - /// are in the cache or null if none are in the cache. - public IEnumerable FindServices(String serviceType) - { - EnsureDiskCacheLoaded(); - m_accessLock.EnterReadLock(); - - try - { - - Debug.Assert(m_lastChangeId == -1 || m_services.Count > 0); - - if (CacheDataExpired) - { - return null; - } - - // We either have all of the services or none. If we have none then return null. - if (m_services.Count == 0) - { - return null; - } - - // If service type is null, return all services as long as we know - // that we have all of the services - IEnumerable> dictionaries; - if (String.IsNullOrEmpty(serviceType)) - { - dictionaries = m_services.Values; - } - else - { - Dictionary services = null; - if (!m_services.TryGetValue(serviceType, out services)) - { - return null; - } - - dictionaries = new Dictionary[] { services }; - } - - // Make a copy of all of the service definitions to pass back. - List serviceDefinitions = new List(); - foreach (Dictionary dict in dictionaries) - { - foreach (ServiceDefinition definition in dict.Values) - { - serviceDefinitions.Add(definition.Clone()); - } - } - - return serviceDefinitions; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - - /// - /// Loads the service data into the in-memory cache and writes the values to disk. - /// - /// The data to write to the cache. - /// Copies of the service definitions created by this load - public void LoadServicesData(LocationServiceData locationServiceData, Boolean allServicesIncluded) - { - m_accessLock.EnterWriteLock(); - - try - { - // If the server is telling us our client cache isn't fresh and we agree - // with it, clear the storage. The reason we check to see if we agree with it - // is that because of the way we cache based on filters, we may sometimes - // tell the server that our last change id is -1 because we don't have a given - // filter cached. In this case, the server will tell us our cache is out of - // date even though it isn't. - if (!locationServiceData.ClientCacheFresh && locationServiceData.LastChangeId != m_lastChangeId) - { - m_accessMappings = new Dictionary(VssStringComparer.AccessMappingMoniker); - m_services = new Dictionary>(VssStringComparer.ServiceType); - m_cachedMisses = new HashSet(VssStringComparer.ServiceType); - m_lastChangeId = -1; - m_cacheExpirationDate = DateTime.MinValue; - } - else - { - EnsureDiskCacheLoadedHelper(); - } - - // We have to update the lastChangeId outside of the above if check because there - // are cases such as a register service where we cause the lastChangeId to be incremented - // and our cache isn't out of date. - SetLastChangeId(locationServiceData.LastChangeId, allServicesIncluded); - - // Use the client value if provided (this lets clients override the server) - // otherwise just use the server specified TTL. - Int32 clientCacheTimeToLive = (ClientCacheTimeToLive != null) ? ClientCacheTimeToLive.Value : locationServiceData.ClientCacheTimeToLive; - m_cacheExpirationDate = DateTime.UtcNow.AddSeconds(clientCacheTimeToLive); - - ICollection accessMappings = locationServiceData.AccessMappings; - if (accessMappings != null && accessMappings.Count > 0) - { - // Get all of the access mappings - foreach (AccessMapping accessMapping in accessMappings) - { - // We can't remove this compat code from the client library yet since - // we still support newer clients talking to older TFS servers - // which might not send VirtualDirectory - // Older server means earlier than TFS 2015 CU2 - if (accessMapping.VirtualDirectory == null && - !String.IsNullOrEmpty(WebApplicationRelativeDirectory)) - { - String absoluteUriTrimmed = accessMapping.AccessPoint.TrimEnd('/'); - String relativeDirectoryTrimmed = WebApplicationRelativeDirectory.TrimEnd('/'); - - if (VssStringComparer.ServerUrl.EndsWith(absoluteUriTrimmed, relativeDirectoryTrimmed)) - { - accessMapping.AccessPoint = absoluteUriTrimmed.Substring(0, absoluteUriTrimmed.Length - relativeDirectoryTrimmed.Length); - } - } - - // if we can find it, update the values so the objects that reference this - // access mapping are updated as well - AccessMapping existingAccessMapping; - if (m_accessMappings.TryGetValue(accessMapping.Moniker, out existingAccessMapping)) - { - existingAccessMapping.DisplayName = accessMapping.DisplayName; - existingAccessMapping.AccessPoint = accessMapping.AccessPoint; - existingAccessMapping.VirtualDirectory = accessMapping.VirtualDirectory; - } - else - { - // We didn't find it, so just set it - existingAccessMapping = accessMapping; - m_accessMappings[accessMapping.Moniker] = accessMapping; - } - } - - DetermineClientAndDefaultZones(locationServiceData.DefaultAccessMappingMoniker); - } - - if (locationServiceData.ServiceDefinitions != null) - { - // Get all of the services - foreach (ServiceDefinition definition in locationServiceData.ServiceDefinitions) - { - Dictionary definitions = null; - if (!m_services.TryGetValue(definition.ServiceType, out definitions)) - { - definitions = new Dictionary(); - m_services[definition.ServiceType] = definitions; - } - - definitions[definition.Identifier] = definition; - } - } - - // Even if the cache file wasn't previously available, let's give ourselves another opportunity to update the cache. - m_cacheAvailable = true; - WriteCacheToDisk(); - } - finally - { - Debug.Assert(m_lastChangeId == -1 || m_services.Count > 0); - - m_accessLock.ExitWriteLock(); - } - } - - private void DetermineClientAndDefaultZones(String defaultAccessMappingMoniker) - { - Debug.Assert(m_accessLock.IsWriteLockHeld); - - m_defaultAccessMapping = null; - m_clientAccessMapping = null; - - // For comparisons below we MUST use .ToString() here instead of .AbsoluteUri. .AbsoluteUri will return the path - // portion of the query string as encoded if it contains characters that are unicode, .ToString() - // will not return them encoded. We must not have them encoded so that the comparison below works - // correctly. Also, we do not need to worry about the downfalls of using ToString() instead of AbsoluteUri - // here because any urls that are generated with the generated access point will be placed back into a - // Uri object before they are used in a web request. - String relativeDirectoryTrimmed = (WebApplicationRelativeDirectory != null) ? WebApplicationRelativeDirectory.TrimEnd('/') : String.Empty; - - foreach (AccessMapping accessMapping in m_accessMappings.Values) - { - if (VssStringComparer.ServerUrl.StartsWith(m_connectionBaseUrl.ToString(), accessMapping.AccessPoint.TrimEnd('/')) && - (accessMapping.VirtualDirectory == null || - VssStringComparer.UrlPath.Equals(accessMapping.VirtualDirectory, relativeDirectoryTrimmed))) - { - m_clientAccessMapping = accessMapping; - } - } - - m_defaultAccessMapping = m_accessMappings[defaultAccessMappingMoniker]; - - if (m_clientAccessMapping == null) - { - String accessPoint = m_connectionBaseUrl.ToString().TrimEnd('/'); - String virtualDirectory = String.Empty; - - if (!String.IsNullOrEmpty(WebApplicationRelativeDirectory)) - { - if (VssStringComparer.ServerUrl.EndsWith(accessPoint, relativeDirectoryTrimmed)) - { - accessPoint = accessPoint.Substring(0, accessPoint.Length - relativeDirectoryTrimmed.Length); - virtualDirectory = relativeDirectoryTrimmed; - } - } - - // Looks like we are in an unregistered zone, make up our own. - m_clientAccessMapping = new AccessMapping() - { - Moniker = accessPoint, - DisplayName = accessPoint, - AccessPoint = accessPoint, - VirtualDirectory = virtualDirectory - }; - } - } - - /// - /// Returns the AccessMappings that this location service cache knows about. - /// Note that each time this property is accessed, the list is copied and - /// returned. - /// - public IEnumerable AccessMappings - { - get - { - EnsureDiskCacheLoaded(); - m_accessLock.EnterReadLock(); - - try - { - // return a copy to prevent race conditions - List accessMappings = new List(); - - if (!CacheDataExpired) - { - foreach (AccessMapping accessMapping in m_accessMappings.Values) - { - accessMappings.Add(accessMapping); - } - } - - return accessMappings; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - } - - /// - /// Removes the access mapping with the provided access mapping moniker - /// and all of the location mapping entries that have this access - /// zone. - /// - /// The moniker of the access mapping to remove. - /// - public void RemoveAccessMapping(String moniker) - { - EnsureDiskCacheLoaded(); - - m_accessLock.EnterWriteLock(); - - try - { - // Remove it from the access mappings - m_accessMappings.Remove(moniker); - - // Remove each instance from the service definitions - foreach (Dictionary serviceGroup in m_services.Values) - { - foreach (ServiceDefinition definition in serviceGroup.Values) - { - // We know that it is illegal to delete an access mapping that is the default access mapping of - // a service definition so we don't have to update any of those values. - - // Remove the mapping that has the removed access mapping - for (int i = 0; i < definition.LocationMappings.Count; i++) - { - // If this one needs to be removed, swap it with the end and update the end counter - if (VssStringComparer.AccessMappingMoniker.Equals(moniker, definition.LocationMappings[i].AccessMappingMoniker)) - { - definition.LocationMappings.RemoveAt(i); - break; - } - } - } - } - - WriteCacheToDisk(); - } - finally - { - m_accessLock.ExitWriteLock(); - } - } - - /// - /// Adds a cached miss to the location service data, if the last change ID presented - /// matches the current value. - /// - public void AddCachedMiss(String serviceType, Guid serviceIdentifier, int missedLastChangeId) - { - if (missedLastChangeId < 0) - { - return; - } - - EnsureDiskCacheLoaded(); - m_accessLock.EnterWriteLock(); - - try - { - if (missedLastChangeId == m_lastChangeId && - m_cachedMisses.Add(BuildCacheMissString(serviceType, serviceIdentifier))) - { - WriteCacheToDisk(); - } - } - finally - { - m_accessLock.ExitWriteLock(); - } - } - - /// - /// Returns the id of the last change that this cache is aware of. - /// - public Int32 GetLastChangeId() - { - EnsureDiskCacheLoaded(); - m_accessLock.EnterReadLock(); - - try - { - return m_lastChangeId; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - - /// - /// Returns the time of the cache expiration. - /// - /// - internal DateTime GetCacheExpirationDate() - { - EnsureDiskCacheLoaded(); - - m_accessLock.EnterReadLock(); - - try - { - return m_cacheExpirationDate; - } - finally - { - m_accessLock.ExitReadLock(); - } - } - - private void SetLastChangeId(Int32 lastChangeId, Boolean allServicesUpdated) - { - Debug.Assert(m_accessLock.IsWriteLockHeld); - - if (m_lastChangeId != -1 || allServicesUpdated) - { - // We only update our last change id if the last change id was valid before - // and this is an incremental update or this data includes all services. - m_lastChangeId = lastChangeId; - } - } - - private static String BuildCacheMissString(String serviceType, Guid serviceIdentifier) - { - return String.Concat(serviceType, "_", serviceIdentifier.ToString()); - } - - /// - /// - /// - internal void EnsureDiskCacheLoaded() - { - if (m_cacheLocallyFresh || !m_cacheAvailable) - { - return; - } - - m_accessLock.EnterWriteLock(); - - try - { - EnsureDiskCacheLoadedHelper(); - } - finally - { - m_accessLock.ExitWriteLock(); - } - } - - private void EnsureDiskCacheLoadedHelper() - { - Debug.Assert(m_accessLock.IsWriteLockHeld); - - FileStream unusedFile = null; - - try - { - if (m_cacheLocallyFresh || !m_cacheAvailable) - { - return; - } - - // actually load the cache from disk - // Open the file, allowing concurrent reads. - // Do not create the file if it does not exist. - XmlDocument document = XmlUtility.OpenXmlFile(out unusedFile, m_cacheFilePath, FileShare.Read, saveFile: false); - - if (document != null) - { - m_accessMappings = new Dictionary(VssStringComparer.AccessMappingMoniker); - m_services = new Dictionary>(VssStringComparer.ServiceType); - m_cachedMisses = new HashSet(VssStringComparer.ServiceType); - - // There is an existing cache, load it - m_lastChangeId = m_locationXmlOperator.ReadLastChangeId(document); - m_cacheExpirationDate = m_locationXmlOperator.ReadCacheExpirationDate(document); - String defaultAccessMappingMoniker = m_locationXmlOperator.ReadDefaultAccessMappingMoniker(document); - m_webApplicationRelativeDirectory = m_locationXmlOperator.ReadVirtualDirectory(document); - - // Read and organize the access mappings - List accessMappings = m_locationXmlOperator.ReadAccessMappings(document); - foreach (AccessMapping accessMapping in accessMappings) - { - m_accessMappings[accessMapping.Moniker] = accessMapping; - } - - if (accessMappings.Count > 0) - { - DetermineClientAndDefaultZones(defaultAccessMappingMoniker); - } - else - { - m_cacheAvailable = false; - m_lastChangeId = -1; - return; - } - - // Read and organize the service definitions - List serviceDefinitions = m_locationXmlOperator.ReadServices(document, m_accessMappings); - foreach (ServiceDefinition definition in serviceDefinitions) - { - Dictionary serviceTypeSet; - if (!m_services.TryGetValue(definition.ServiceType, out serviceTypeSet)) - { - serviceTypeSet = new Dictionary(); - m_services.Add(definition.ServiceType, serviceTypeSet); - } - - serviceTypeSet[definition.Identifier] = definition; - } - - List cachedMisses = m_locationXmlOperator.ReadCachedMisses(document); - foreach (String cachedMiss in cachedMisses) - { - m_cachedMisses.Add(cachedMiss); - } - } - - // Hook up the file system watcher if we haven't already - if (m_fileSystemWatcher == null) - { - m_fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(m_cacheFilePath), s_cacheFileName); - m_fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; - m_fileSystemWatcher.Changed += new FileSystemEventHandler(m_fileSystemWatcher_Changed); - } - - Debug.Assert(m_lastChangeId == -1 || m_services.Count > 0); - } - catch (Exception) - { - // It looks as though we don't have access to the cache file. Eat - // this exception and mark the cache as unavailable so we don't - // repeatedly try to access it - m_cacheAvailable = false; - m_lastChangeId = -1; - } - finally - { - m_cacheLocallyFresh = true; - - if (unusedFile != null) - { - unusedFile.Dispose(); - } - } - } - - /// - /// - /// - /// - /// - void m_fileSystemWatcher_Changed(object sender, FileSystemEventArgs e) - { - m_cacheLocallyFresh = false; - } - - /// - /// Writes the cache to disk. Callers of this function should have a writer - /// lock. - /// - private void WriteCacheToDisk() - { - Debug.Assert(m_accessLock.IsWriteLockHeld); - - if (!m_cacheAvailable) - { - return; - } - - try - { - Debug.Assert(m_lastChangeId == -1 || m_services.Count > 0); - // Get an exclusive lock on the file - using (FileStream file = XmlUtility.OpenFile(m_cacheFilePath, FileShare.None, true)) - { - XmlDocument document = new XmlDocument(); - - XmlNode documentNode = document.CreateNode(XmlNodeType.Element, s_docStartElement, null); - document.AppendChild(documentNode); - - m_locationXmlOperator.WriteLastChangeId(documentNode, m_lastChangeId); - m_locationXmlOperator.WriteCacheExpirationDate(documentNode, m_cacheExpirationDate); - m_locationXmlOperator.WriteDefaultAccessMappingMoniker(documentNode, m_defaultAccessMapping.Moniker); - m_locationXmlOperator.WriteVirtualDirectory(documentNode, m_webApplicationRelativeDirectory); - m_locationXmlOperator.WriteAccessMappings(documentNode, m_accessMappings.Values); - - // Build up a list of the service definitions for writing - List serviceDefinitions = new List(); - foreach (Dictionary serviceTypeSet in m_services.Values) - { - serviceDefinitions.AddRange(serviceTypeSet.Values); - } - - m_locationXmlOperator.WriteServices(documentNode, serviceDefinitions); - m_locationXmlOperator.WriteCachedMisses(documentNode, m_cachedMisses); - - // Reset the file stream. - file.SetLength(0); - file.Position = 0; - - // Save the file. - document.Save(file); - } - } - catch (Exception) - { - // It looks as though we don't have access to the cache file. Eat - // this exception and mark the cache as unavailable so we don't - // repeatedly try to access it - m_cacheAvailable = false; - } - } - - /// - /// This setting controls the amount of time before the cache expires - /// - internal Int32? ClientCacheTimeToLive - { - get; - set; - } - - /// - /// This is the set of services available from this service location - /// service. - /// - private Dictionary> m_services; - - /// - /// This is the set of services that have been queried since our last update - /// from the server that we know don't exist. - /// - private HashSet m_cachedMisses; - - /// - /// Keeps track of all access mappings that have been given to us by the server. - /// The key is their identifier. - /// - private Dictionary m_accessMappings; - - /// - /// Keeps track of the lastChangeId for the last change that was put in this cache. - /// - private Int32 m_lastChangeId; - - /// - /// The time after which the local cache data is invalid. This is used to prematurely expire the client cache - /// even if we don't know (yet) whether or not the server changed. By expiring the client cache we - /// can ensure that clients will be forced to check for server updates periodically rather than relying on the - /// client cache indefinitely in the degenerate case where no client tools ever explicitly call Connect() (such as tf.exe) - /// - private DateTime m_cacheExpirationDate; - - /// - /// This is used to protect the services in-memory store. - /// - private ReaderWriterLockSlim m_accessLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - - private String m_webApplicationRelativeDirectory; - - /// - /// Only let one process write to a cache at a time. - /// - private static Object s_cacheMutex = new Object(); - - /// - /// This object is used to keep track of whether or not our cache is fresh - /// with respect to what we have on disk. - /// - private Boolean m_cacheLocallyFresh; - - /// - /// This is true if we do not have access to the cache file - /// - private Boolean m_cacheAvailable; - - /// - /// This is used to watch for others changing our cache so we can respond to - /// those changes - /// - private FileSystemWatcher m_fileSystemWatcher; - - private Uri m_connectionBaseUrl; - - /// - /// The two calculated access mappings that this manager caches. - /// - private AccessMapping m_clientAccessMapping; - private AccessMapping m_defaultAccessMapping; - - /// - /// persistent cache file name values - /// - private static readonly String s_cacheFileName = "LocationServiceData.config"; - private String m_cacheFilePath; - - private LocationXmlOperator m_locationXmlOperator; - - /// - /// xml document related constants - /// - private const String s_docStartElement = "LocationServiceConfiguration"; - } -} diff --git a/src/Sdk/WebApi/WebApi/Location/LocationServerMapCache.cs b/src/Sdk/WebApi/WebApi/Location/LocationServerMapCache.cs deleted file mode 100644 index 4ae355634..000000000 --- a/src/Sdk/WebApi/WebApi/Location/LocationServerMapCache.cs +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Xml; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.WebApi.Location -{ - /// - /// - /// - internal class ServerMapData - { - /// - /// - /// - public ServerMapData() - : this(Guid.Empty, Guid.Empty) - { - } - - /// - /// - /// - /// - /// - public ServerMapData(Guid serverId, Guid serviceOwner) - { - ServerId = serverId; - ServiceOwner = serviceOwner; - } - - /// - /// - /// - public Guid ServerId - { - get; - set; - } - - /// - /// - /// - public Guid ServiceOwner - { - get; - set; - } - } - - internal static class LocationServerMapCache - { - /// - /// Finds the location for the specified guid. If it is not found, null - /// is returned. - /// - /// The server instance id associated with the - /// desired location service url. - /// The location of the location service for this server or null - /// if the guid is not found. - public static String ReadServerLocation(Guid serverId, Guid serviceOwner) - { - try - { - EnsureCacheLoaded(); - s_accessLock.EnterReadLock(); - - // Iterate through the dictionary to find the location we are looking for - foreach (KeyValuePair pair in s_serverMappings) - { - if (Guid.Equals(serverId, pair.Value.ServerId) && - Guid.Equals(serviceOwner, pair.Value.ServiceOwner)) - { - return pair.Key; - } - } - - return null; - } - finally - { - if (s_accessLock.IsReadLockHeld) - { - s_accessLock.ExitReadLock(); - } - } - } - - /// - /// - /// - /// - /// The guid for this location or Guid.Empty if the location - /// does not have an entry. - public static ServerMapData ReadServerData(String location) - { - try - { - EnsureCacheLoaded(); - s_accessLock.EnterReadLock(); - - ServerMapData serverData; - if (!s_serverMappings.TryGetValue(location, out serverData)) - { - return new ServerMapData(); - } - - return serverData; - } - finally - { - if (s_accessLock.IsReadLockHeld) - { - s_accessLock.ExitReadLock(); - } - } - } - - /// - /// If this call is not a change, nothing will be done. - /// - /// - /// - /// - /// True if this is the first time the mapping was written. - public static Boolean EnsureServerMappingExists(String location, Guid serverId, Guid serviceOwner) - { - try - { - EnsureCacheLoaded(); - s_accessLock.EnterWriteLock(); - - // See if this is an update or an add to optimize writing the disk. - Boolean isNew = true; - ServerMapData storedData; - if (s_serverMappings.TryGetValue(location, out storedData)) - { - if (storedData.ServerId.Equals(serverId) && - storedData.ServiceOwner.Equals(serviceOwner)) - { - return false; - } - isNew = false; - } - - // Make the change in the cache - s_serverMappings[location] = new ServerMapData(serverId, serviceOwner); - - s_accessLock.ExitWriteLock(); - - // Persist the change - return TryWriteMappingToDisk(location, serverId, serviceOwner, isNew); - } - finally - { - if (s_accessLock.IsWriteLockHeld) - { - s_accessLock.ExitWriteLock(); - } - } - } - - private static void EnsureCacheLoaded() - { - if (s_cacheFreshLocally || s_cacheUnavailable) - { - return; - } - - FileStream file = null; - - try - { - s_accessLock.EnterWriteLock(); - - if (s_cacheFreshLocally) - { - return; - } - - // actually load the cache from disk - // Open the file, allowing concurrent reads. - // Do not create the file if it does not exist. - XmlDocument document = XmlUtility.OpenXmlFile(out file, FilePath, FileShare.Read, false); - - if (document != null) - { - // This is an existing document, get the root node - XmlNode documentNode = document.ChildNodes[0]; - - // Load all of the mappings - foreach (XmlNode mappingNode in documentNode.ChildNodes) - { - String location = mappingNode.Attributes[s_locationAttribute].InnerText; - Guid guid = XmlConvert.ToGuid(mappingNode.Attributes[s_guidAttribute].InnerText); - - // Legacy server case: Don't error out if the existing file doesn't have the owner attribute. - // Once the server is updated the next connect call should update this record - Guid serviceOwner = Guid.Empty; - if (mappingNode.Attributes[s_ownerAttribute] != null) - { - serviceOwner = XmlConvert.ToGuid(mappingNode.Attributes[s_ownerAttribute].InnerText); - } - - // If the service owner is absent, then the server is on-prem - if (Guid.Empty == serviceOwner) - { - serviceOwner = ServiceInstanceTypes.TFSOnPremises; - } - - s_serverMappings[location] = new ServerMapData(guid, serviceOwner); - } - } - - // Hook up the file system watcher so we know if we need to invalidate our cache - if (s_fileWatcher == null) - { - String directoryToWatch = VssClientSettings.ClientCacheDirectory; - - // Ensure the directory exists, otherwise FileSystemWatcher will throw. - if (!Directory.Exists(directoryToWatch)) - { - Directory.CreateDirectory(directoryToWatch); - } - - s_fileWatcher = new FileSystemWatcher(directoryToWatch, s_fileName); - s_fileWatcher.NotifyFilter = NotifyFilters.LastWrite; - s_fileWatcher.Changed += new FileSystemEventHandler(s_fileWatcher_Changed); - } - } - catch (Exception) - { - // It looks like something is wrong witht he cahce, lets just hide this - // exception and work without it. - s_cacheUnavailable = true; - } - finally - { - s_cacheFreshLocally = true; - - if (file != null) - { - file.Close(); - } - - if (s_accessLock.IsWriteLockHeld) - { - s_accessLock.ExitWriteLock(); - } - } - } - - static void s_fileWatcher_Changed(object sender, FileSystemEventArgs e) - { - s_cacheFreshLocally = false; - } - - /// - /// Writes the mapping to disk if the cache is available. - /// - /// - /// - /// - /// True if the write succeeded - private static Boolean TryWriteMappingToDisk(String location, Guid serverGuid, Guid serviceOwner, Boolean isNew) - { - if (s_cacheUnavailable) - { - return false; - } - - FileStream file = null; - - try - { - // Open the file with an exclusive lock - XmlDocument existingDocument = XmlUtility.OpenXmlFile(out file, FilePath, FileShare.None, true); - - // Only allow one writer at a time - lock (s_cacheMutex) - { - XmlNode documentNode = null; - if (existingDocument == null) - { - // This is a new document, create the xml - existingDocument = new XmlDocument(); - - // This is the first entry, create the document node and add the child - documentNode = existingDocument.CreateNode(XmlNodeType.Element, s_documentXmlText, null); - existingDocument.AppendChild(documentNode); - - AddMappingNode(documentNode, location, serverGuid, serviceOwner); - } - else - { - // Get the root document node - documentNode = existingDocument.ChildNodes[0]; - - // If this is a new mapping, just add it to the document node - if (isNew) - { - AddMappingNode(documentNode, location, serverGuid, serviceOwner); - } - else - { - // This is some form of update. Find the node with the location and update - // the guid. - foreach (XmlNode mappingNode in documentNode.ChildNodes) - { - if (StringComparer.OrdinalIgnoreCase.Equals(mappingNode.Attributes[s_locationAttribute].InnerText, location)) - { - // This is the one we have to update, do so now - mappingNode.Attributes[s_guidAttribute].InnerText = XmlConvert.ToString(serverGuid); - - // For compatibility with older OMs with the same major version, persist the on-prem service owner as empty. - if (ServiceInstanceTypes.TFSOnPremises == serviceOwner) - { - serviceOwner = Guid.Empty; - } - - // Legacy server case: Let's be resilient to the persisted document not already having an owner attribute - XmlAttribute ownerAttribute = existingDocument.CreateAttribute(s_ownerAttribute); - ownerAttribute.InnerText = XmlConvert.ToString(serviceOwner); - mappingNode.Attributes.Append(ownerAttribute); - } - } - } - } - - // Reset the file stream. - file.SetLength(0); - file.Position = 0; - - // Save the file. - existingDocument.Save(file); - - return true; - } - } - catch (Exception) - { - // It looks like we are being denied access to the cache, lets just hide this - // exception and work without it. - s_cacheUnavailable = true; - return false; - } - finally - { - if (file != null) - { - file.Close(); - } - } - } - - private static void AddMappingNode(XmlNode parentNode, String location, Guid guid, Guid owner) - { - XmlNode mappingNode = parentNode.OwnerDocument.CreateNode(XmlNodeType.Element, s_mappingXmlText, null); - parentNode.AppendChild(mappingNode); - - // Write the mapping as attributes - XmlUtility.AddXmlAttribute(mappingNode, s_locationAttribute, location); - XmlUtility.AddXmlAttribute(mappingNode, s_guidAttribute, XmlConvert.ToString(guid)); - - // For compatibility with older OMs with the same major version, persist the on-prem service owner as empty. - if (ServiceInstanceTypes.TFSOnPremises == owner) - { - owner = Guid.Empty; - } - - // Legacy server case: If the server did not send back ServiceOwner in the connectionData - // let's just do what we used to do to not break anything. - // Eventually we can remove this if-guard - if (owner != Guid.Empty) - { - XmlUtility.AddXmlAttribute(mappingNode, s_ownerAttribute, XmlConvert.ToString(owner)); - } - } - - private static String FilePath - { - get - { - if (s_filePath == null) - { - s_filePath = Path.Combine(VssClientSettings.ClientCacheDirectory, s_fileName); - } - - return s_filePath; - } - } - - private static ReaderWriterLockSlim s_accessLock = new ReaderWriterLockSlim(); - - private static Dictionary s_serverMappings = new Dictionary(StringComparer.OrdinalIgnoreCase); - - private static String s_filePath; - - private static FileSystemWatcher s_fileWatcher; - - /// - /// This is used to keep track of whether or not our in-memory cache is fresh with regards - /// to our persistent cache on disk. - /// - private static Boolean s_cacheFreshLocally = false; - - /// - /// This is true if we do not have access to the cache file - /// - private static Boolean s_cacheUnavailable = false; - - private static readonly String s_fileName = "LocationServerMap.xml"; - private static readonly String s_documentXmlText = "LocationServerMappings"; - private static readonly String s_mappingXmlText = "ServerMapping"; - private static readonly String s_locationAttribute = "location"; - private static readonly String s_guidAttribute = "guid"; - private static readonly String s_ownerAttribute = "owner"; - - private static Object s_cacheMutex = new Object(); - } -} diff --git a/src/Sdk/WebApi/WebApi/Location/LocationService.cs b/src/Sdk/WebApi/WebApi/Location/LocationService.cs deleted file mode 100644 index f5839d391..000000000 --- a/src/Sdk/WebApi/WebApi/Location/LocationService.cs +++ /dev/null @@ -1,281 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common.Internal; -using GitHub.Services.Location; - -namespace GitHub.Services.WebApi.Location -{ - /// - /// - /// - internal class LocationService : ILocationService - { - /// - /// - /// - /// - public virtual void Initialize( - VssConnection connection) - { - m_connection = connection; - } - - /// - /// - /// - /// - /// - public ILocationDataProvider GetLocationData( - Guid locationAreaIdentifier) - { - return GetLocationDataAsync(locationAreaIdentifier).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - public async Task GetLocationDataAsync( - Guid locationAreaIdentifier, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (locationAreaIdentifier == Guid.Empty || - locationAreaIdentifier == LocationServiceConstants.SelfReferenceIdentifier) - { - return LocalDataProvider; - } - else - { - // These methods might make a server call but generally it will be accessing cached data - Guid instanceId = await LocalDataProvider.GetInstanceIdAsync(cancellationToken).ConfigureAwait(false); - Guid instanceType = await LocalDataProvider.GetInstanceTypeAsync(cancellationToken).ConfigureAwait(false); - - if (locationAreaIdentifier == instanceId || - locationAreaIdentifier == instanceType || - instanceType == ServiceInstanceTypes.TFSOnPremises) - { - // Never do location traversal for OnPrem - return LocalDataProvider; - } - else - { - return await ResolveLocationDataAsync(locationAreaIdentifier, cancellationToken).ConfigureAwait(false); - } - } - } - - /// - /// - /// - /// - /// - /// - private async Task ResolveLocationDataAsync( - Guid locationAreaIdentifier, - CancellationToken cancellationToken = default(CancellationToken)) - { - ILocationDataProvider locationData = null; - ProviderCache providerLookup = m_providerLookup; - - if (providerLookup == null) - { - providerLookup = new ProviderCache(); - - // Create and seed the cache with the local url - String location = await LocalDataProvider.LocationForCurrentConnectionAsync( - ServiceInterfaces.LocationService2, - LocationServiceConstants.SelfReferenceIdentifier, - cancellationToken).ConfigureAwait(false); - - if (location != null) - { - providerLookup.GetOrAdd(location, LocalDataProvider); - } - - ProviderCache actualProvider = Interlocked.CompareExchange(ref m_providerLookup, providerLookup, null); - - // Did we lose the race? Pick the winner - if (actualProvider != null) - { - providerLookup = actualProvider; - } - } - - if (!providerLookup.TryGetValue(locationAreaIdentifier, out locationData)) - { - // First, check our current provider (see if a direct pointer is registered) - String location = await LocalDataProvider.LocationForCurrentConnectionAsync( - ServiceInterfaces.LocationService2, - locationAreaIdentifier, - cancellationToken).ConfigureAwait(false); - - // Next, check and see if we have a root pointer - if (location == null && - locationAreaIdentifier != LocationServiceConstants.ApplicationIdentifier && - locationAreaIdentifier != LocationServiceConstants.RootIdentifier) // Don't infinitely recurse - { - ILocationDataProvider rootProvider = await ResolveLocationDataAsync( - LocationServiceConstants.RootIdentifier, - cancellationToken).ConfigureAwait(false); - - if (rootProvider != null && - !Object.ReferenceEquals(rootProvider, LocalDataProvider)) - { - location = await rootProvider.LocationForCurrentConnectionAsync( - ServiceInterfaces.LocationService2, - locationAreaIdentifier, - cancellationToken).ConfigureAwait(false); - } - } - - if (location != null) - { - // The caller could be asking for a serviceIdentifier which resolves to a URL - // for which we already have a cached provider. - // This is typical when serviceIdentifier is a ResourceArea guid. - if (!providerLookup.TryGetValue(location, out locationData)) - { - locationData = await CreateDataProviderAsync(location, cancellationToken).ConfigureAwait(false); - locationData = providerLookup.GetOrAdd(location, locationData); - } - - providerLookup[locationAreaIdentifier] = locationData; - } - } - - return locationData; - } - - /// - /// - /// - /// - /// - public String GetLocationServiceUrl( - Guid locationAreaIdentifier) - { - return GetLocationServiceUrlAsync(locationAreaIdentifier, null).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - public String GetLocationServiceUrl( - Guid locationAreaIdentifier, - String accessMappingMoniker = null) - { - return GetLocationServiceUrlAsync(locationAreaIdentifier, accessMappingMoniker).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - /// - public async Task GetLocationServiceUrlAsync( - Guid locationAreaIdentifier, - String accessMappingMoniker = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - ILocationDataProvider locationData = await GetLocationDataAsync(locationAreaIdentifier, cancellationToken).ConfigureAwait(false); - - if (locationData == null) - { - return null; - } - - AccessMapping accessMapping = await locationData.GetAccessMappingAsync(accessMappingMoniker ?? AccessMappingConstants.PublicAccessMappingMoniker).ConfigureAwait(false); - - if (accessMapping == null) - { - accessMapping = await locationData.GetClientAccessMappingAsync().ConfigureAwait(false); - } - - return await locationData.LocationForAccessMappingAsync( - ServiceInterfaces.LocationService2, - LocationServiceConstants.SelfReferenceIdentifier, - accessMapping, - cancellationToken).ConfigureAwait(false); - } - - /// - /// - /// - /// - /// - /// - protected virtual async Task CreateDataProviderAsync( - String location, - CancellationToken cancellationToken = default(CancellationToken)) - { - VssClientHttpRequestSettings locationServiceRequestSettings = VssClientHttpRequestSettings.Default.Clone(); - locationServiceRequestSettings.SendTimeout = TimeSpan.FromSeconds(30); // If not set here, the send timeout will use the default of 100 seconds, which is too long. - VssConnection connection = new VssConnection(new Uri(location), m_connection.Credentials, locationServiceRequestSettings); - IVssServerDataProvider dataProvider = connection.ServerDataProvider; - - // If this provider is connected, then we should make sure the remote provider - // is also up-to-date - if (m_connection.ServerDataProvider.HasConnected) - { - await dataProvider.ConnectAsync(ConnectOptions.None, cancellationToken).ConfigureAwait(false); - } - - return dataProvider; - } - - /// - /// - /// - protected virtual ILocationDataProvider LocalDataProvider - { - get - { - return m_connection.ServerDataProvider; - } - } - - private VssConnection m_connection; - private ProviderCache m_providerLookup; - - private class ProviderCache - { - public Boolean TryGetValue(Guid locationAreaIdentfier, out ILocationDataProvider provider) - { - return m_guidCache.TryGetValue(locationAreaIdentfier, out provider); - } - - public Boolean TryGetValue(String locationUrl, out ILocationDataProvider provider) - { - return m_urlCache.TryGetValue(NormalizeUrl(locationUrl), out provider); - } - - public ILocationDataProvider GetOrAdd(String locationUrl, ILocationDataProvider provider) - { - return m_urlCache.GetOrAdd(NormalizeUrl(locationUrl), provider); - } - - public ILocationDataProvider this[Guid locationAreaIdentifier] - { - get { return m_guidCache[locationAreaIdentifier]; } - set { m_guidCache[locationAreaIdentifier] = value; } - } - - private static String NormalizeUrl(String locationUrl) - { - return UriUtility.AppendSlashToPathIfNeeded(locationUrl); - } - - private ConcurrentDictionary m_guidCache = new ConcurrentDictionary(); - private ConcurrentDictionary m_urlCache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Location/LocationXmlOperator.cs b/src/Sdk/WebApi/WebApi/Location/LocationXmlOperator.cs deleted file mode 100644 index 33f442ffe..000000000 --- a/src/Sdk/WebApi/WebApi/Location/LocationXmlOperator.cs +++ /dev/null @@ -1,601 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; -using GitHub.Services.Common; -using GitHub.Services.Location; -using GitHub.Services.Common.Internal; - -namespace GitHub.Services.WebApi.Location -{ - internal class LocationXmlOperator - { - /// - /// This is to be used for reading in an xml file that contains service definitions that - /// have to be loaded during install - /// - /// True if the parser is parsing xml from a client cache - public LocationXmlOperator(Boolean isClientCache) - { - m_isClientCache = isClientCache; - m_accessMappingLocationServiceUrls = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - /// - /// Reads the service definitions from the provided document. - /// For a specification of what the xml should look like, see the - /// corresponding Write method. - /// - /// The document to read from. - /// A list of service definitions. - public List ReadServices(XmlDocument document, Dictionary accessMappings) - { - List definitions = new List(); - - XmlNodeList servicesNodeList = document.SelectNodes("//" + s_services); - if (servicesNodeList == null) - { - return definitions; - } - - foreach (XmlNode servicesNode in servicesNodeList) - { - // Get all of the service definition nodes - foreach (XmlNode definitionNode in servicesNode.SelectNodes("./" + s_serviceDefinition)) - { - ServiceDefinition definition = new ServiceDefinition(); - - // Get the service type - it must exist - XmlNode serviceTypeNode = definitionNode.SelectSingleNode("./" + s_serviceType); - LocationXmlOperator.CheckXmlNodeNullOrEmpty(serviceTypeNode, s_serviceType, definitionNode); - definition.ServiceType = serviceTypeNode.InnerText; - - // Get the identifier if it exists - it must exist if this is the client cache - XmlNode identifierNode = definitionNode.SelectSingleNode("./" + s_identifier); - if (m_isClientCache) - { - LocationXmlOperator.CheckXmlNodeNullOrEmpty(identifierNode, s_identifier, definitionNode); - } - definition.Identifier = (identifierNode != null) ? XmlConvert.ToGuid(identifierNode.InnerText) : Guid.Empty; - - // Get the display name - it must exist - XmlNode displayNameNode = definitionNode.SelectSingleNode("./" + s_displayName); - LocationXmlOperator.CheckXmlNodeNullOrEmpty(displayNameNode, s_displayName, definitionNode); - definition.DisplayName = displayNameNode.InnerText; - - // Get the description if it exists - XmlNode descriptionNode = definitionNode.SelectSingleNode("./" + s_description); - definition.Description = (descriptionNode != null) ? descriptionNode.InnerText : String.Empty; - - // Get the relativePath and the relativeTo setting - XmlNode relativePathNode = definitionNode.SelectSingleNode("./" + s_relativePath); - LocationXmlOperator.CheckXmlNodeNull(relativePathNode, s_relativePath, definitionNode); - definition.RelativePath = relativePathNode.InnerText; - - // Get the relativeTo setting - XmlAttribute relativeToAttribute = relativePathNode.Attributes[s_relativeTo]; - CheckXmlAttributeNullOrEmpty(relativeToAttribute, s_relativeTo, relativePathNode); - RelativeToSetting setting; - if (!RelativeToEnumCache.GetRelativeToEnums().TryGetValue(relativeToAttribute.InnerText, out setting)) - { - throw new ConfigFileException(relativeToAttribute.InnerText); - } - definition.RelativeToSetting = setting; - - // If the relativeToSetting is FullyQualified and the path is empty, set it to null - // to make the framework happy. - if (definition.RelativeToSetting == RelativeToSetting.FullyQualified && definition.RelativePath == String.Empty) - { - definition.RelativePath = null; - } - - XmlNode parentServiceTypeNode = definitionNode.SelectSingleNode("./" + s_parentServiceType); - definition.ParentServiceType = (parentServiceTypeNode != null) ? parentServiceTypeNode.InnerText : null; - - XmlNode parentIdentifierNode = definitionNode.SelectSingleNode("./" + s_parentIdentifier); - definition.ParentIdentifier = (parentIdentifierNode != null) ? XmlConvert.ToGuid(parentIdentifierNode.InnerText) : Guid.Empty; - - // Get all of the location mappings - definition.LocationMappings = new List(); - if (definition.RelativeToSetting == RelativeToSetting.FullyQualified) - { - XmlNodeList mappings = definitionNode.SelectNodes(".//" + s_locationMapping); - - foreach (XmlNode mappingNode in mappings) - { - LocationMapping locationMapping = new LocationMapping(); - - // Get the accessMapping - XmlNode accessMappingNode = mappingNode.SelectSingleNode("./" + s_accessMapping); - LocationXmlOperator.CheckXmlNodeNullOrEmpty(accessMappingNode, s_accessMapping, mappingNode); - locationMapping.AccessMappingMoniker = accessMappingNode.InnerText; - - // Only process the location code if this is the client cache and there better - // not be a location node if this isn't a client cache. - XmlNode locationNode = mappingNode.SelectSingleNode("./" + s_location); - if (m_isClientCache) - { - CheckXmlNodeNullOrEmpty(locationNode, s_location, mappingNode); - } - - locationMapping.Location = (locationNode != null) ? locationNode.InnerText : null; - - // We will let the caller build the proper location from the proper service definitions - // instead of doing it here. - - definition.LocationMappings.Add(locationMapping); - } - } - - // Get the resourceVersion - XmlNode resourceVersionNode = definitionNode.SelectSingleNode("./" + s_resourceVersion); - definition.ResourceVersion = (resourceVersionNode != null) ? XmlConvert.ToInt32(resourceVersionNode.InnerText) : 0; - - // Get the minVersion - XmlNode minVersionNode = definitionNode.SelectSingleNode("./" + s_minVersion); - definition.MinVersionString = (minVersionNode != null) ? minVersionNode.InnerText : null; - - // Get the maxVersion - XmlNode maxVersionNode = definitionNode.SelectSingleNode("./" + s_maxVersion); - definition.MaxVersionString = (maxVersionNode != null) ? maxVersionNode.InnerText : null; - - // Get the releasedVersion - XmlNode releasedVersionNode = definitionNode.SelectSingleNode("./" + s_releasedVersion); - definition.ReleasedVersionString = (releasedVersionNode != null) ? releasedVersionNode.InnerText : null; - - definitions.Add(definition); - } - } - - return definitions; - } - - public List ReadCachedMisses(XmlDocument document) - { - List cachedMisses = new List(); - - XmlNodeList cachedMissesNodeList = document.SelectNodes("//" + s_cachedMisses); - if (cachedMissesNodeList == null) - { - return cachedMisses; - } - - foreach (XmlNode cachedMissesNode in cachedMissesNodeList) - { - // Get all of the service definition nodes - foreach (XmlNode cachedMissNode in cachedMissesNode.SelectNodes("./" + s_cachedMiss)) - { - cachedMisses.Add(cachedMissNode.InnerText); - } - } - - return cachedMisses; - } - - /// - /// Reads the access mappings from the provided document. - /// For a specification of what the xml should look like, see the - /// corresponding Write method. - /// - /// The document to read from. - /// A list of access mappings. - public List ReadAccessMappings(XmlDocument document) - { - List accessMappings = new List(); - - XmlNodeList accessMappingNodeList = document.SelectNodes("//" + s_accessMappings); - if (accessMappingNodeList == null) - { - return accessMappings; - } - - foreach (XmlNode accessMappingsNode in accessMappingNodeList) - { - foreach (XmlNode accessMappingNode in accessMappingsNode.SelectNodes("./" + s_accessMapping)) - { - AccessMapping accessMapping = new AccessMapping(); - - // Get the moniker - XmlNode monikerNode = accessMappingNode.SelectSingleNode("./" + s_moniker); - CheckXmlNodeNullOrEmpty(monikerNode, s_moniker, accessMappingNode); - accessMapping.Moniker = monikerNode.InnerText; - - // Get the enabled property - XmlNode accessPointNode = accessMappingNode.SelectSingleNode("./" + s_accessPoint); - CheckXmlNodeNullOrEmpty(accessPointNode, s_accessPoint, accessMappingNode); - accessMapping.AccessPoint = accessPointNode.InnerText; - - // Get the displayName property - XmlNode displayNameNode = accessMappingNode.SelectSingleNode("./" + s_displayName); - accessMapping.DisplayName = (displayNameNode != null) ? displayNameNode.InnerText : null; - - XmlNode virtualDirectoryNode = accessMappingNode.SelectSingleNode("./" + s_virtualDirectory); - accessMapping.VirtualDirectory = (virtualDirectoryNode != null) ? virtualDirectoryNode.InnerText : null; - - // If this isn't the client cache, load the location service url - if (!m_isClientCache) - { - XmlNode locationServiceUrlNode = accessMappingNode.SelectSingleNode("./" + s_locationServiceUrl); - String locationServiceUrl = (locationServiceUrlNode != null) ? locationServiceUrlNode.InnerText : String.Empty; - m_accessMappingLocationServiceUrls[accessMapping.Moniker] = locationServiceUrl; - } - - accessMappings.Add(accessMapping); - } - } - - return accessMappings; - } - - /// - /// Reads the last change id from the provided document. - /// For a specification of what the xml should look like, see the - /// corresponding Write method. - /// - /// The document to read from. - /// The last change id. - public Int32 ReadLastChangeId(XmlDocument document) - { - XmlNode lastChangeIdNode = document.SelectSingleNode("//" + s_lastChangeId); - return (lastChangeIdNode != null) ? XmlConvert.ToInt32(lastChangeIdNode.InnerText) : -1; - } - - public DateTime ReadCacheExpirationDate(XmlDocument document) - { - XmlNode cacheExpirationDateNode = document.SelectSingleNode("//" + s_cacheExpirationDate); - return (cacheExpirationDateNode != null) ? XmlConvert.ToDateTime(cacheExpirationDateNode.InnerText, XmlDateTimeSerializationMode.Utc) : DateTime.MinValue; - } - - public String ReadDefaultAccessMappingMoniker(XmlDocument document) - { - XmlNode defaultAccessMappingMonikerNode = document.SelectSingleNode("//" + s_defaultAccessMappingMoniker); - CheckXmlNodeNullOrEmpty(defaultAccessMappingMonikerNode, s_defaultAccessMappingMoniker, document); - return defaultAccessMappingMonikerNode.InnerText; - } - - public String ReadVirtualDirectory(XmlDocument document) - { - XmlNode virtualDirectoryNode = document.SelectSingleNode("//" + s_virtualDirectory); - CheckXmlNodeNull(virtualDirectoryNode, s_virtualDirectory, document); - return virtualDirectoryNode.InnerText; - } - - /// - /// Writes the lastChangeId to the provided document in the form - /// value - /// - /// The document to write to. - /// The value to write. - public void WriteLastChangeId(XmlNode documentNode, Int32 lastChangeId) - { - XmlNode lastChangeIdNode = documentNode.OwnerDocument.CreateNode(XmlNodeType.Element, s_lastChangeId, null); - documentNode.AppendChild(lastChangeIdNode); - lastChangeIdNode.InnerText = XmlConvert.ToString(lastChangeId); - } - - public void WriteCacheExpirationDate(XmlNode documentNode, DateTime cacheExpirationDate) - { - XmlNode cacheExpirationDateNode = documentNode.OwnerDocument.CreateNode(XmlNodeType.Element, s_cacheExpirationDate, null); - documentNode.AppendChild(cacheExpirationDateNode); - cacheExpirationDateNode.InnerText = XmlConvert.ToString(cacheExpirationDate, XmlDateTimeSerializationMode.Utc); - } - - public void WriteDefaultAccessMappingMoniker(XmlNode documentNode, String defaultAccessMappingMoniker) - { - XmlNode defaultAccessMappingMonikerNode = documentNode.OwnerDocument.CreateNode(XmlNodeType.Element, s_defaultAccessMappingMoniker, null); - documentNode.AppendChild(defaultAccessMappingMonikerNode); - defaultAccessMappingMonikerNode.InnerText = defaultAccessMappingMoniker; - } - - public void WriteVirtualDirectory(XmlNode documentNode, String virtualDirectory) - { - XmlNode virtualDirectoryNode = documentNode.OwnerDocument.CreateNode(XmlNodeType.Element, s_virtualDirectory, null); - documentNode.AppendChild(virtualDirectoryNode); - virtualDirectoryNode.InnerText = virtualDirectory; - } - - /// - /// Writes the access mapping information to the provided document in the form: - /// - /// - /// value - /// value - /// value - /// value - /// - /// - /// - /// The document to write to. - /// The values to write. - public void WriteAccessMappings(XmlNode documentNode, IEnumerable accessMappings) - { - XmlDocument document = documentNode.OwnerDocument; - - XmlNode accessMappingsNode = document.CreateNode(XmlNodeType.Element, s_accessMappings, null); - documentNode.AppendChild(accessMappingsNode); - - foreach (AccessMapping accessMapping in accessMappings) - { - XmlNode accessMappingNode = document.CreateNode(XmlNodeType.Element, s_accessMapping, null); - accessMappingsNode.AppendChild(accessMappingNode); - - XmlNode monikerNode = document.CreateNode(XmlNodeType.Element, s_moniker, null); - accessMappingNode.AppendChild(monikerNode); - monikerNode.InnerText = accessMapping.Moniker; - - XmlNode accessPointNode = document.CreateNode(XmlNodeType.Element, s_accessPoint, null); - accessMappingNode.AppendChild(accessPointNode); - accessPointNode.InnerText = accessMapping.AccessPoint; - - XmlNode displayNameNode = document.CreateNode(XmlNodeType.Element, s_displayName, null); - accessMappingNode.AppendChild(displayNameNode); - displayNameNode.InnerText = accessMapping.DisplayName; - - if (accessMapping.VirtualDirectory != null) - { - XmlNode virtualDirectoryNode = document.CreateNode(XmlNodeType.Element, s_virtualDirectory, null); - accessMappingNode.AppendChild(virtualDirectoryNode); - virtualDirectoryNode.InnerText = accessMapping.VirtualDirectory; - } - } - } - - /// - /// Writes service definition information to the provided document in the form: - /// - /// - /// value - /// value - /// value - /// value - /// value - /// - /// - /// value - /// value - /// - /// . - /// . - /// . - /// - /// - /// . - /// . - /// . - /// - /// - /// The document to write to. - /// The values to write - public void WriteServices(XmlNode documentNode, IEnumerable serviceDefinitions) - { - XmlDocument document = documentNode.OwnerDocument; - - XmlNode servicesNode = document.CreateNode(XmlNodeType.Element, s_services, null); - documentNode.AppendChild(servicesNode); - - foreach (ServiceDefinition definition in serviceDefinitions) - { - XmlNode serviceDefinitionNode = document.CreateNode(XmlNodeType.Element, s_serviceDefinition, null); - servicesNode.AppendChild(serviceDefinitionNode); - - XmlNode serviceTypeNode = document.CreateNode(XmlNodeType.Element, s_serviceType, null); - serviceDefinitionNode.AppendChild(serviceTypeNode); - serviceTypeNode.InnerText = definition.ServiceType; - - XmlNode identifierNode = document.CreateNode(XmlNodeType.Element, s_identifier, null); - serviceDefinitionNode.AppendChild(identifierNode); - identifierNode.InnerText = XmlConvert.ToString(definition.Identifier); - - if (definition.DisplayName != null) - { - XmlNode displayNameNode = document.CreateNode(XmlNodeType.Element, s_displayName, null); - serviceDefinitionNode.AppendChild(displayNameNode); - displayNameNode.InnerText = definition.DisplayName; - } - - if (definition.Description != null) - { - XmlNode descriptionNode = document.CreateNode(XmlNodeType.Element, s_description, null); - serviceDefinitionNode.AppendChild(descriptionNode); - descriptionNode.InnerText = definition.Description; - } - - XmlNode relativePathNode = document.CreateNode(XmlNodeType.Element, s_relativePath, null); - serviceDefinitionNode.AppendChild(relativePathNode); - relativePathNode.InnerText = definition.RelativePath; - - XmlUtility.AddXmlAttribute(relativePathNode, s_relativeTo, definition.RelativeToSetting.ToString()); - - XmlNode parentServiceTypeNode = document.CreateNode(XmlNodeType.Element, s_parentServiceType, null); - serviceDefinitionNode.AppendChild(parentServiceTypeNode); - parentServiceTypeNode.InnerText = definition.ParentServiceType; - - XmlNode parentIdentifierNode = document.CreateNode(XmlNodeType.Element, s_parentIdentifier, null); - serviceDefinitionNode.AppendChild(parentIdentifierNode); - parentIdentifierNode.InnerText = XmlConvert.ToString(definition.ParentIdentifier); - - if (definition.RelativeToSetting == RelativeToSetting.FullyQualified) - { - XmlNode locationMappingsNode = document.CreateNode(XmlNodeType.Element, s_locationMappings, null); - serviceDefinitionNode.AppendChild(locationMappingsNode); - - foreach (LocationMapping mapping in definition.LocationMappings) - { - XmlNode locationMappingNode = document.CreateNode(XmlNodeType.Element, s_locationMapping, null); - locationMappingsNode.AppendChild(locationMappingNode); - - XmlNode accessMappingNode = document.CreateNode(XmlNodeType.Element, s_accessMapping, null); - locationMappingNode.AppendChild(accessMappingNode); - accessMappingNode.InnerText = mapping.AccessMappingMoniker; - - XmlNode locationNode = document.CreateNode(XmlNodeType.Element, s_location, null); - locationMappingNode.AppendChild(locationNode); - locationNode.InnerText = mapping.Location; - } - } - - if (definition.ResourceVersion > 0) - { - XmlNode resourceVersionNode = document.CreateNode(XmlNodeType.Element, s_resourceVersion, null); - serviceDefinitionNode.AppendChild(resourceVersionNode); - resourceVersionNode.InnerText = XmlConvert.ToString(definition.ResourceVersion); - } - - if (definition.MinVersionString != null) - { - XmlNode minVersionNode = document.CreateNode(XmlNodeType.Element, s_minVersion, null); - serviceDefinitionNode.AppendChild(minVersionNode); - minVersionNode.InnerText = definition.MinVersionString; - } - - if (definition.MaxVersionString != null) - { - XmlNode maxVersionNode = document.CreateNode(XmlNodeType.Element, s_maxVersion, null); - serviceDefinitionNode.AppendChild(maxVersionNode); - maxVersionNode.InnerText = definition.MaxVersionString; - } - - if (definition.ReleasedVersionString != null) - { - XmlNode releasedVersionNode = document.CreateNode(XmlNodeType.Element, s_releasedVersion, null); - serviceDefinitionNode.AppendChild(releasedVersionNode); - releasedVersionNode.InnerText = definition.ReleasedVersionString; - } - } - } - - public void WriteCachedMisses(XmlNode documentNode, IEnumerable cachedMisses) - { - XmlDocument document = documentNode.OwnerDocument; - - XmlNode cacheMissesNode = document.CreateNode(XmlNodeType.Element, s_cachedMisses, null); - documentNode.AppendChild(cacheMissesNode); - - foreach (String cacheMiss in cachedMisses) - { - XmlNode cacheMissNode = document.CreateNode(XmlNodeType.Element, s_cachedMiss, null); - cacheMissNode.InnerText = cacheMiss; - cacheMissesNode.AppendChild(cacheMissNode); - } - } - - /// - /// Gets the location service url for the access mapping moniker provided. - /// This function should be used to retrieve location service urls for access - /// zones that were loaded by this LocationXmlController instance. - /// - /// The access mapping moniker. - /// The location service url for this access mapping moniker. - public String GetLocationServiceUrl(String moniker) - { - return m_accessMappingLocationServiceUrls[moniker]; - } - - /// - /// Throws and exception if the node provided is null. - /// - /// The node to check. - /// The name of the node to check. - /// The parent node of the node we are checking. - private static void CheckXmlNodeNull(XmlNode node, String nodeName, XmlNode parent) - { - if (node == null) - { - throw new ConfigFileException(CommonResources.XmlNodeMissing(nodeName, parent)); - } - } - - /// - /// Throws an exception if the xml node is null or empty. - /// - /// The node we are checking. - /// The name of the node we are checking. - /// The parent node of the node we are checking. - private static void CheckXmlNodeNullOrEmpty(XmlNode node, String nodeName, XmlNode parent) - { - CheckXmlNodeNull(node, nodeName, parent); - - if (node.InnerText.Equals(String.Empty)) - { - throw new ConfigFileException(CommonResources.XmlNodeEmpty(nodeName, parent.Name)); - } - } - - /// - /// Throws exception if the attribute provided is null or empty - /// - /// The attribute we are checking. - /// The name of the attribute we are checking. - /// The node that contains this attribute. - private static void CheckXmlAttributeNullOrEmpty(XmlAttribute attribute, String attributeName, XmlNode element) - { - if (attribute == null) - { - throw new ConfigFileException(CommonResources.XmlAttributeNull(attributeName, element.Name)); - } - - if (attribute.InnerText.Equals(String.Empty)) - { - throw new ConfigFileException(CommonResources.XmlAttributeEmpty(attributeName, element.Name)); - } - } - - /// - /// Maps access mapping monikers to location service urls - /// - private Dictionary m_accessMappingLocationServiceUrls; - - private Boolean m_isClientCache; - - private static readonly String s_lastChangeId = "LastChangeId"; - private static readonly String s_cacheExpirationDate = "CacheExpirationDate"; - private static readonly String s_defaultAccessMappingMoniker = "DefaultAccessMappingMoniker"; - private static readonly String s_virtualDirectory = "VirtualDirectory"; - - private static readonly String s_services = "Services"; - private static readonly String s_cachedMisses = "CachedMisses"; - private static readonly String s_serviceDefinition = "ServiceDefinition"; - private static readonly String s_cachedMiss = "CachedMiss"; - private static readonly String s_serviceType = "ServiceType"; - private static readonly String s_identifier = "Identifier"; - private static readonly String s_displayName = "DisplayName"; - private static readonly String s_locationServiceUrl = "LocationServiceUrl"; - private static readonly String s_description = "Description"; - private static readonly String s_relativePath = "RelativePath"; - private static readonly String s_relativeTo = "relativeTo"; - private static readonly String s_parentServiceType = "ParentServiceType"; - private static readonly String s_parentIdentifier = "ParentIdentifier"; - private static readonly String s_locationMappings = "LocationMappings"; - private static readonly String s_locationMapping = "LocationMapping"; - private static readonly String s_location = "Location"; - private static readonly String s_resourceVersion = "ResourceVersion"; - private static readonly String s_minVersion = "MinVersion"; - private static readonly String s_maxVersion = "MaxVersion"; - private static readonly String s_releasedVersion = "ReleasedVersion"; - - private static readonly String s_accessMappings = "AccessMappings"; - private static readonly String s_accessMapping = "AccessMapping"; - private static readonly String s_moniker = "Moniker"; - private static readonly String s_accessPoint = "AccessPoint"; - } - - internal static class RelativeToEnumCache - { - private static Dictionary s_relativeToEnums; - - static RelativeToEnumCache() - { - s_relativeToEnums = new Dictionary(StringComparer.OrdinalIgnoreCase); - s_relativeToEnums["Context"] = RelativeToSetting.Context; - s_relativeToEnums["FullyQualified"] = RelativeToSetting.FullyQualified; - s_relativeToEnums["WebApplication"] = RelativeToSetting.WebApplication; - } - - internal static Dictionary GetRelativeToEnums() - { - return s_relativeToEnums; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Location/ServerDataProvider.cs b/src/Sdk/WebApi/WebApi/Location/ServerDataProvider.cs deleted file mode 100644 index 7cbcd80c9..000000000 --- a/src/Sdk/WebApi/WebApi/Location/ServerDataProvider.cs +++ /dev/null @@ -1,816 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.Identity; -using GitHub.Services.Location; -using GitHub.Services.Location.Client; -using GitHub.Services.WebApi.Utilities; - -namespace GitHub.Services.WebApi.Location -{ - /// - /// - /// - public interface IVssServerDataProvider : ILocationDataProvider - { - /// - /// - /// - Boolean HasConnected { get; } - - /// - /// - /// - /// - /// - Task GetAuthorizedIdentityAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// - /// - /// - /// - Task GetAuthenticatedIdentityAsync(CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Performs all of the steps that are necessary for setting up a connection - /// with a TeamFoundationServer. Specify what information should be - /// returned in the connectOptions parameter. - /// - /// Each time this call is made the username for the current user - /// will be returned as well as the client zone that this client is making - /// requests from. - /// - /// Specifies what information that should be - /// returned from the server. - Task ConnectAsync(ConnectOptions connectOptions, CancellationToken cancellationToken = default(CancellationToken)); - - /// - /// Reset the connection state back to disconnect - /// The client must reconnect - /// - Task DisconnectAsync(CancellationToken cancellationToken = default(CancellationToken)); - } - - /// - /// This class provides data about the server via the LocationService. - /// - internal class VssServerDataProvider : IVssServerDataProvider - { - public VssServerDataProvider( - VssConnection connection, - HttpMessageHandler pipeline, - String fullyQualifiedUrl) - { - m_connection = connection; - m_baseUri = connection.Uri; - m_fullyQualifiedUrl = fullyQualifiedUrl; - m_locationClient = new LocationHttpClient(m_baseUri, pipeline, false); - - // Try to get the guid for this server - ServerMapData serverData = LocationServerMapCache.ReadServerData(m_fullyQualifiedUrl); - m_locationDataCacheManager = new LocationCacheManager(serverData.ServerId, serverData.ServiceOwner, m_baseUri); - } - - // Back-pointer to connection - internal VssConnection Connection - { - get { return m_connection; } - } - - /// - /// Returns true if this object has successfully authenticated. - /// - public bool HasConnected - { - get - { - return m_connectionMade == true; - } - } - - /// - /// Gets the authorized user. This function will authenticate with the server if it has - /// not done so already. Like any other regular method, it throws VssUnauthorizedException - /// if the server is contacted and authentication fails. - /// - /// The authenticated user. - public async Task GetAuthorizedIdentityAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - await EnsureConnectedAsync(ConnectOptions.None).ConfigureAwait(false); - - Debug.Assert(m_authorizedIdentity != null); - return m_authorizedIdentity; - } - - /// - /// Gets the authenticated user. This function will authenticate with the server if it has - /// not done so already. Like any other regular method, it throws VssUnauthorizedException - /// if the server is contacted and authentication fails. - /// - /// The authenticated user. - public async Task GetAuthenticatedIdentityAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - await EnsureConnectedAsync(ConnectOptions.None).ConfigureAwait(false); - - Debug.Assert(m_authenticatedIdentity != null); - return m_authenticatedIdentity; - } - - /// - /// - /// - public Guid InstanceId - { - get - { - return GetInstanceIdAsync().SyncResult(); - } - } - - /// - /// - /// - public Guid InstanceType - { - get - { - return GetInstanceTypeAsync().SyncResult(); - } - } - - /// - /// The unique identifier for this server. This method will attempt to return - /// a cached value, if possible. - /// - public async Task GetInstanceIdAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - if (!NeedToConnect(ConnectOptions.None)) - { - // We've already made a Connect call and have the authoritative instance ID. - return m_instanceId; - } - else - { - // Check the location server cache to see if we have the instance ID there. - ServerMapData serverData = LocationServerMapCache.ReadServerData(m_fullyQualifiedUrl); - Guid toReturn = serverData.ServerId; - - if (Guid.Empty != toReturn) - { - // We do. Return it. - return toReturn; - } - - // We do not. Make a Connect call and retrieve the instance ID. - await EnsureConnectedAsync(ConnectOptions.None, cancellationToken).ConfigureAwait(false); - return m_instanceId; - } - } - - /// - /// The unique identifier for the service owner. This property will attempt to return - /// a cached value, if possible. - /// - public async Task GetInstanceTypeAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - if (!NeedToConnect(ConnectOptions.None)) - { - // We've already made a Connect call and have the authoritative service owner ID. - return m_serviceOwner; - } - else - { - ServerMapData serverData = LocationServerMapCache.ReadServerData(m_fullyQualifiedUrl); - Guid toReturn = serverData.ServiceOwner; - - if (Guid.Empty != toReturn) - { - // We do. Return it. - return toReturn; - } - - // We do not. Make a Connect call and retrieve the service owner ID. - await EnsureConnectedAsync(ConnectOptions.None, cancellationToken).ConfigureAwait(false); - return m_serviceOwner; - } - } - - public AccessMapping DefaultAccessMapping - { - get - { - return GetDefaultAccessMappingAsync().SyncResult(); - } - } - - /// - /// - /// - /// - /// - public async Task GetDefaultAccessMappingAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - AccessMapping defaultAccessMapping = m_locationDataCacheManager.DefaultAccessMapping; - - // If defaultAccessMapping is null we may not have the cache information yet, go to the server to get the information. - if (defaultAccessMapping == null) - { - await EnsureConnectedAsync(ConnectOptions.IncludeServices, cancellationToken).ConfigureAwait(false); - defaultAccessMapping = m_locationDataCacheManager.DefaultAccessMapping; - - Debug.Assert(defaultAccessMapping != null, "defaultAccessMapping should never be null"); - } - - return defaultAccessMapping; - } - - public AccessMapping ClientAccessMapping - { - get - { - return GetClientAccessMappingAsync().SyncResult(); - } - } - - /// - /// - /// - /// - /// - public async Task GetClientAccessMappingAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - AccessMapping clientAccessMapping = m_locationDataCacheManager.ClientAccessMapping; - - // If definition is null we may not have the cache information yet, go to the server to get the information. - if (clientAccessMapping == null) - { - await EnsureConnectedAsync(ConnectOptions.IncludeServices, cancellationToken).ConfigureAwait(false); - clientAccessMapping = m_locationDataCacheManager.ClientAccessMapping; - - Debug.Assert(clientAccessMapping != null, "clientAccessMapping should never be null"); - } - - return clientAccessMapping; - } - - public IEnumerable ConfiguredAccessMappings - { - get - { - return GetConfiguredAccessMappingsAsync().SyncResult(); - } - } - - /// - /// - /// - /// - /// - public async Task> GetConfiguredAccessMappingsAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - await EnsureConnectedAsync(ConnectOptions.IncludeServices, cancellationToken).ConfigureAwait(false); - return m_locationDataCacheManager.AccessMappings; - } - - public AccessMapping GetAccessMapping(String moniker) - { - return GetAccessMappingAsync(moniker).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - public async Task GetAccessMappingAsync( - String moniker, - CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckForNull(moniker, "moniker"); - - await EnsureConnectedAsync(ConnectOptions.IncludeServices, cancellationToken).ConfigureAwait(false); - return m_locationDataCacheManager.GetAccessMapping(moniker); - } - - public String LocationForAccessMapping(String serviceType, Guid serviceIdentifier, AccessMapping accessMapping) - { - return LocationForAccessMappingAsync(serviceType, serviceIdentifier, accessMapping).SyncResult(); - } - - public async Task LocationForAccessMappingAsync( - String serviceType, - Guid serviceIdentifier, - AccessMapping accessMapping, - CancellationToken cancellationToken = default(CancellationToken)) - { - ServiceDefinition serviceDefinition = await FindServiceDefinitionAsync(serviceType, serviceIdentifier, cancellationToken).ConfigureAwait(false); - - if (serviceDefinition == null) - { - // This method is expected to return a location or fail so throw if we couldn't find - // the service definition. - throw new ServiceDefinitionDoesNotExistException(WebApiResources.ServiceDefinitionDoesNotExist(serviceType, serviceIdentifier)); - } - - return await LocationForAccessMappingAsync(serviceDefinition, accessMapping, cancellationToken).ConfigureAwait(false); - } - - public String LocationForAccessMapping( - ServiceDefinition serviceDefinition, - AccessMapping accessMapping) - { - return LocationForAccessMappingAsync(serviceDefinition, accessMapping).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - /// - public Task LocationForAccessMappingAsync( - ServiceDefinition serviceDefinition, - AccessMapping accessMapping, - CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckForNull(serviceDefinition, "serviceDefinition"); - ArgumentUtility.CheckForNull(accessMapping, "accessMapping"); - - // If this is FullyQualified then look through our location mappings - if (serviceDefinition.RelativeToSetting == RelativeToSetting.FullyQualified) - { - LocationMapping locationMapping = serviceDefinition.GetLocationMapping(accessMapping); - - if (locationMapping != null) - { - return Task.FromResult(locationMapping.Location); - } - - // We weren't able to find the location for the access mapping. Return null. - return Task.FromResult(null); - } - else - { - // Make sure the AccessMapping has a valid AccessPoint. - if (String.IsNullOrEmpty(accessMapping.AccessPoint)) - { - throw new InvalidAccessPointException(WebApiResources.InvalidAccessMappingLocationServiceUrl()); - } - - String webApplicationRelativeDirectory = m_locationDataCacheManager.WebApplicationRelativeDirectory; - - if (accessMapping.VirtualDirectory != null) - { - webApplicationRelativeDirectory = accessMapping.VirtualDirectory; - } - - Uri uri = new Uri(accessMapping.AccessPoint); - - String properRoot = String.Empty; - switch (serviceDefinition.RelativeToSetting) - { - case RelativeToSetting.Context: - properRoot = PathUtility.Combine(uri.AbsoluteUri, webApplicationRelativeDirectory); - break; - case RelativeToSetting.WebApplication: - properRoot = accessMapping.AccessPoint; - break; - default: - Debug.Assert(true, "Found an unknown RelativeToSetting"); - break; - } - - return Task.FromResult(PathUtility.Combine(properRoot, serviceDefinition.RelativePath)); - } - } - - public String LocationForCurrentConnection( - String serviceType, - Guid serviceIdentifier) - { - return LocationForCurrentConnectionAsync(serviceType, serviceIdentifier).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - /// - public async Task LocationForCurrentConnectionAsync( - String serviceType, - Guid serviceIdentifier, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (StringComparer.CurrentCultureIgnoreCase.Equals(serviceType, ServiceInterfaces.LocationService2) && - serviceIdentifier == LocationServiceConstants.SelfReferenceIdentifier) - { - // This is an edge case because the server may not have registered a self-reference pointer - // or the server is legacy and doesn't send back service owner yet. - return m_baseUri.AbsoluteUri; - } - - ServiceDefinition serviceDefinition = await FindServiceDefinitionAsync(serviceType, serviceIdentifier, cancellationToken).ConfigureAwait(false); - - if (serviceDefinition == null) - { - // This method should not throw if a ServiceDefinition could not be found. - return null; - } - - return await LocationForCurrentConnectionAsync(serviceDefinition, cancellationToken).ConfigureAwait(false); - } - - public String LocationForCurrentConnection(ServiceDefinition serviceDefinition) - { - return LocationForCurrentConnectionAsync(serviceDefinition).SyncResult(); - } - - public async Task LocationForCurrentConnectionAsync( - ServiceDefinition serviceDefinition, - CancellationToken cancellationToken = default(CancellationToken)) - { - AccessMapping clientAccessMapping = await GetClientAccessMappingAsync(cancellationToken).ConfigureAwait(false); - String location = await LocationForAccessMappingAsync(serviceDefinition, clientAccessMapping, cancellationToken).ConfigureAwait(false); - - if (location == null) - { - AccessMapping defaultAccessMapping = await GetDefaultAccessMappingAsync(cancellationToken).ConfigureAwait(false); - location = await LocationForAccessMappingAsync(serviceDefinition, defaultAccessMapping, cancellationToken).ConfigureAwait(false); - - if (location == null) - { - LocationMapping firstLocationMapping = serviceDefinition.LocationMappings.FirstOrDefault(); - - if (firstLocationMapping == null) - { - throw new InvalidServiceDefinitionException(WebApiResources.ServiceDefinitionWithNoLocations(serviceDefinition.ServiceType)); - } - - location = firstLocationMapping.Location; - } - } - - return location; - } - - public IEnumerable FindServiceDefinitions(String serviceType) - { - return FindServiceDefinitionsAsync(serviceType).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - public async Task> FindServiceDefinitionsAsync( - String serviceType, - CancellationToken cancellationToken = default(CancellationToken)) - { - // Look in the cache - IEnumerable definitions = null; - - if (m_locationDataCacheManager != null) - { - definitions = m_locationDataCacheManager.FindServices(serviceType); - } - - // If definitions is null, we had a potential cache miss, go to the server to see if our cache is up-to-date - if (definitions == null) - { - await CheckForServerUpdatesAsync(cancellationToken).ConfigureAwait(false); - - // Try again to see if we can find it now in case that something has updated. - return m_locationDataCacheManager.FindServices(serviceType); - } - - return definitions; - } - - public ServiceDefinition FindServiceDefinition(String serviceType, Guid serviceIdentifier) - { - return FindServiceDefinitionAsync(serviceType, serviceIdentifier).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - /// - public async Task FindServiceDefinitionAsync( - String serviceType, - Guid serviceIdentifier, - CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckForNull(serviceType, "serviceType"); - - int lastChangeId = m_locationDataCacheManager.GetLastChangeId(); - - ServiceDefinition definition; - if (m_locationDataCacheManager.TryFindService(serviceType, serviceIdentifier, out definition)) - { - // If we hit a cache entry return it whether it is null or not. - return definition; - } - - // If we got here that means that we have a first-time cache miss, go to the server to see if our cache is up-to-date - await CheckForServerUpdatesAsync(cancellationToken).ConfigureAwait(false); - - // Try again to see if we can find it now in case that something has updated. - if (!m_locationDataCacheManager.TryFindService(serviceType, serviceIdentifier, out definition)) - { - // If it is a LS2 then try to fault the definition in, otherwise add a cache miss - if (String.Equals(serviceType, ServiceInterfaces.LocationService2, StringComparison.OrdinalIgnoreCase) && - serviceIdentifier != LocationServiceConstants.RootIdentifier && - serviceIdentifier != LocationServiceConstants.ApplicationIdentifier && - await GetInstanceTypeAsync(cancellationToken).ConfigureAwait(false) == LocationServiceConstants.RootIdentifier) - { - // Force SPS to fault in the definition - definition = await m_locationClient.GetServiceDefinitionAsync(serviceType, serviceIdentifier, cancellationToken).ConfigureAwait(false); - } - else - { - m_locationDataCacheManager.AddCachedMiss(serviceType, serviceIdentifier, lastChangeId); - return null; - } - } - - return definition; - } - - public ApiResourceLocationCollection GetResourceLocations() - { - return GetResourceLocationsAsync().SyncResult(); - } - - /// - /// - /// - /// - /// - public async Task GetResourceLocationsAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - if (m_resourceLocations == null) - { - IEnumerable definitions = await FindServiceDefinitionsAsync(null).ConfigureAwait(false); - - if (definitions != null) - { - IEnumerable resourceLocationDefinitions = definitions.Where(x => x.ResourceVersion > 0); - - if (resourceLocationDefinitions.Any()) - { - ApiResourceLocationCollection resourceLocations = new ApiResourceLocationCollection(); - - foreach (ServiceDefinition definition in resourceLocationDefinitions) - { - resourceLocations.AddResourceLocation(ApiResourceLocation.FromServiceDefinition(definition)); - } - - m_resourceLocations = resourceLocations; - } - } - } - - return m_resourceLocations; - } - - /// - /// Consults the server to see if any services from the filter array have - /// changed. It updates the cache with the new values. - /// - /// - private async Task CheckForServerUpdatesAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - Boolean checkedForUpdates = await EnsureConnectedAsync(ConnectOptions.IncludeServices, cancellationToken).ConfigureAwait(false); - - if (!checkedForUpdates) - { - Int32 lastChangeId = m_locationDataCacheManager.GetLastChangeId(); - - // If the ServerDataProvider believes it is already connected (i.e. EnsureConnectedAsync returns false) but the location cache is in a bad state - // we need to make another Connect call to get back to a good state. - // This can happen if the disk cache is invalidated by another process (or another VssConnection object in the same process) writing to the shared file - // this will invalidate the memory cache (via FileSystemWatcher), but we could then subsequently fail to reload the disk cache (IOException) for some reason. - if (lastChangeId == -1) - { - await ConnectAsync(ConnectOptions.IncludeServices, cancellationToken).ConfigureAwait(false); - } - } - } - - /// - /// This function ensures that the connection data that is needed by the caller - /// has been retrieved from the server. This function does not use the - /// credentials provider if authentication fails. - /// - /// The options that designate the information the - /// caller needs from the server. - private async Task EnsureConnectedAsync( - ConnectOptions optionsNeeded, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (NeedToConnect(optionsNeeded)) - { - // We only want one thread to make the server call, so we will lock this section. - // It's **really** important that the locked contents (i.e. ConnectAsync) has no recursive path back into this code - // otherwise we will deadlock. - using (await m_connectionLock.LockAsync(cancellationToken).ConfigureAwait(false)) - { - if (NeedToConnect(optionsNeeded)) - { - await ConnectAsync(optionsNeeded, cancellationToken).ConfigureAwait(false); - return true; - } - } - } - - return false; - } - - /// - /// Returns true if we need to connect to the server. - /// - /// - /// - private Boolean NeedToConnect(ConnectOptions optionsNeeded) - { - // Make sure we refresh the information if the impersonated user has changed. - if (m_locationDataCacheManager.CacheDataExpired) - { - m_connectionMade = false; - m_validConnectionData = ConnectOptions.None; - } - - return !m_connectionMade || ((optionsNeeded & m_validConnectionData) != optionsNeeded); - } - - public async Task ConnectAsync(ConnectOptions connectOptions, CancellationToken cancellationToken = default(CancellationToken)) - { - // We want to force ourselves to includes services if our location service cache has no access mappings. - // This means that this is our first time connecting. - if (!m_locationDataCacheManager.AccessMappings.Any()) - { - connectOptions |= ConnectOptions.IncludeServices; - } - - Int32 lastChangeId = m_locationDataCacheManager.GetLastChangeId(); - - // If we have -1 then that means we have no disk cache yet or it means that we recently hit an exception trying to reload - // the the cache from disk (see Exception catch block in EnsureDiskCacheLoaded). - // Either way, we cannot make a call to the server with -1 and pass None. - // If we do, the resulting payload (which would have ClientCacheFresh=false but include no ServiceDefinitions) - // would leave the in-memory cache in an inconsistent state - if (lastChangeId == -1) - { - connectOptions |= ConnectOptions.IncludeServices; - } - - Boolean includeServices = (connectOptions & ConnectOptions.IncludeServices) == ConnectOptions.IncludeServices; - - // Perform the connection - ConnectionData connectionData = await GetConnectionDataAsync(connectOptions, lastChangeId, cancellationToken).ConfigureAwait(false); - LocationServiceData locationServiceData = connectionData.LocationServiceData; - - // If we were previously connected, make sure we cannot connect as a different user. - if (m_authenticatedIdentity != null) - { - if (!IdentityDescriptorComparer.Instance.Equals(m_authenticatedIdentity.Descriptor, connectionData.AuthenticatedUser.Descriptor)) - { - throw new VssAuthenticationException(WebApiResources.CannotAuthenticateAsAnotherUser(m_authenticatedIdentity.DisplayName, connectionData.AuthenticatedUser.DisplayName)); - } - } - - m_authenticatedIdentity = connectionData.AuthenticatedUser; - m_authorizedIdentity = connectionData.AuthorizedUser; - - m_instanceId = connectionData.InstanceId; - - if (locationServiceData != null) - { - Guid serviceOwner = connectionData.LocationServiceData.ServiceOwner; - - if (Guid.Empty == serviceOwner) - { - serviceOwner = ServiceInstanceTypes.TFSOnPremises; - } - - m_serviceOwner = serviceOwner; - } - - // Verify with our locationServerMap cache that we are storing the correct guid - // for this server. If we are, this is essentially a no-op. - Boolean wroteMapping = LocationServerMapCache.EnsureServerMappingExists(m_fullyQualifiedUrl, m_instanceId, m_serviceOwner); - - if (wroteMapping) - { - if (includeServices && - (connectionData.LocationServiceData.ServiceDefinitions == null || - connectionData.LocationServiceData.ServiceDefinitions.Count == 0)) - { - // This is the rare, rare case where a new server exists at the same url - // that an old server used to (guids are different) and both servers had the same - // location service last change id. In that case, Connect would not have - // brought down any services. To fix this we need to query the services back - // down with -1 as our last change id - ConnectionData updatedConnectionData = await GetConnectionDataAsync(ConnectOptions.IncludeServices, -1, cancellationToken).ConfigureAwait(false); - locationServiceData = updatedConnectionData.LocationServiceData; - } - - m_locationDataCacheManager = new LocationCacheManager(m_instanceId, m_serviceOwner, m_baseUri); - } - - // update the location service cache if we tried to retireve location service data - m_locationDataCacheManager.WebApplicationRelativeDirectory = connectionData.WebApplicationRelativeDirectory; - if (locationServiceData != null) - { - m_locationDataCacheManager.LoadServicesData(locationServiceData, includeServices); - } - - // Set the connection data that we have retrieved - m_validConnectionData |= connectOptions; - - m_connectionMade = true; - } - - /// - /// Reset the connected state of the provider - /// - public Task DisconnectAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - m_connectionMade = false; - m_authenticatedIdentity = null; - m_authorizedIdentity = null; - return Task.FromResult(null); - } - - /// - /// Passed in on construction. The Uris for the server we are connecting to. - /// - private VssConnection m_connection; - private Uri m_baseUri; - private String m_fullyQualifiedUrl; - - /// - /// These are the values we are responsible for determining - /// - private Identity.Identity m_authenticatedIdentity; - private Identity.Identity m_authorizedIdentity; - private Guid m_instanceId; - private Guid m_serviceOwner; - - /// - /// These handle talking to the web service and dealing with connection data - /// - private LocationHttpClient m_locationClient; - private ConnectOptions m_validConnectionData; - private Boolean m_connectionMade; - - /// - /// This object manages the location data cache - /// - private LocationCacheManager m_locationDataCacheManager; - - /// - /// Cache of the resource locations - /// - private ApiResourceLocationCollection m_resourceLocations; - - private readonly AsyncLock m_connectionLock = new AsyncLock(); - - private async Task GetConnectionDataAsync(ConnectOptions connectOptions, int lastChangeId, CancellationToken cancellationToken) - { - int timeoutRetries = 1; - - while (true) - { - try - { - return await m_locationClient.GetConnectionDataAsync(connectOptions, lastChangeId, cancellationToken).ConfigureAwait(false); - } - catch(TimeoutException) when (timeoutRetries-- > 0) { } // Catch TimeoutException when we have retries remaining; otherwise, let it go. - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/IVssOAuthTokenParameterProvider.cs b/src/Sdk/WebApi/WebApi/OAuth/IVssOAuthTokenParameterProvider.cs deleted file mode 100644 index eb013ecea..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/IVssOAuthTokenParameterProvider.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.OAuth -{ - /// - /// Represents an object which participates in setting parameters for an OAuth token request. - /// - public interface IVssOAuthTokenParameterProvider - { - /// - /// Sets applicable parameters on the provided parameters collection for a token request in which the provider - /// is a participant. - /// - /// The current set of parameters - void SetParameters(IDictionary parameters); - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthAccessToken.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthAccessToken.cs deleted file mode 100644 index 530d4c4d9..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthAccessToken.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides encapsulation for opaque access tokens in OAuth token exchanges. - /// - public sealed class VssOAuthAccessToken : IssuedToken - { - /// - /// Initializes a new VssOAuthAccessToken instance with the specified value. - /// - /// The value of the access token, encoded as a string - public VssOAuthAccessToken(String value) - : this(value, DateTime.MaxValue) - { - } - - /// - /// Initializes a new VssOAuthAccessToken instance with the specified value and expiration time. - /// - /// The value of the access token, encoded as a string - /// The date and time when this token is no longer valid - public VssOAuthAccessToken( - String value, - DateTime validTo) - { - ArgumentUtility.CheckStringForNullOrEmpty(value, nameof(value)); - m_value = value; - m_validTo = validTo; - } - - /// - /// Initializes a new VssOAuthAccessToken instance with the specified JWT. - /// - /// The value of the access token, encoded as a JsonWebToken - public VssOAuthAccessToken(JsonWebToken value) - { - ArgumentUtility.CheckForNull(value, nameof(value)); - m_value = value.EncodedToken; - m_validTo = value.ValidTo; - } - - /// - /// Gets the date and time at which this token expires. - /// - public DateTime ValidTo - { - get - { - return m_validTo; - } - } - - /// - /// Gets the value of the current token. - /// - public String Value - { - get - { - return m_value; - } - } - - protected internal override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.OAuth; - } - } - - internal override void ApplyTo(IHttpRequest request) - { - request.Headers.SetValue(Common.Internal.HttpHeaders.Authorization, $"Bearer {m_value}"); - } - - private readonly String m_value; - private readonly DateTime m_validTo; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthAccessTokenCredential.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthAccessTokenCredential.cs deleted file mode 100644 index 03cf0c012..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthAccessTokenCredential.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Net.Http; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides authentication for OAuth 2.0 access tokens issued without credentials. - /// - public class VssOAuthAccessTokenCredential : FederatedCredential - { - /// - /// Initializes a new VssOAuthAccessTokenCredential instance with the specified access token encoded as - /// a string. - /// - /// The access token value encoded as a string - public VssOAuthAccessTokenCredential(String accessToken) - : this(new VssOAuthAccessToken(accessToken)) - { - } - - /// - /// Initializes a new VssOAuthAccessTokenCredential instance with the specified access token encoded as - /// a JWT. - /// - /// The access token value encoded as a JWT - public VssOAuthAccessTokenCredential(JsonWebToken accessToken) - : this(new VssOAuthAccessToken(accessToken)) - { - } - - /// - /// Initializes a new VssOAuthAccessTokenCredential instance with the specified access token. - /// - /// The access token - public VssOAuthAccessTokenCredential(VssOAuthAccessToken accessToken) - : base(accessToken) - { - } - - /// - /// Gets the type of the current credentials. - /// - public override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.OAuth; - } - } - - /// - /// Returns a no-op token provider. This credential does not provide token acquisition functionality. - /// - /// The server URL from which the challenge originated - /// The authentication challenge response message - /// A no-op token provider for supplying the access token - protected override IssuedTokenProvider OnCreateTokenProvider( - Uri serverUrl, - IHttpResponse response) - { - return new VssOAuthAccessTokenProvider(this, serverUrl, null); - } - - private class VssOAuthAccessTokenProvider : IssuedTokenProvider - { - public VssOAuthAccessTokenProvider( - IssuedTokenCredential credential, - Uri serverUrl, - Uri signInUrl) - : base(credential, serverUrl, signInUrl) - { - } - - public override Boolean GetTokenIsInteractive - { - get - { - return false; - } - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredential.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredential.cs deleted file mode 100644 index c70754d8d..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredential.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Collections.Generic; -using GitHub.Services.Common; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides client credentials for proof of identity in OAuth 2.0 token exchanges. - /// - public abstract class VssOAuthClientCredential : IVssOAuthTokenParameterProvider, IDisposable - { - protected VssOAuthClientCredential( - VssOAuthClientCredentialType type, - String clientId) - { - ArgumentUtility.CheckStringForNullOrEmpty(clientId, nameof(clientId)); - - m_type = type; - m_clientId = clientId; - } - - /// - /// Gets the client identifier. - /// - public String ClientId - { - get - { - return m_clientId; - } - } - - /// - /// Gets the type of credentials for this instance. - /// - public VssOAuthClientCredentialType CredentialType - { - get - { - return m_type; - } - } - - /// - /// Disposes of managed resources referenced by the credentials. - /// - public void Dispose() - { - if (m_disposed) - { - return; - } - - m_disposed = true; - Dispose(true); - } - - protected virtual void Dispose(Boolean disposing) - { - } - - /// - /// When overridden in a derived class, the corresponding token request parameters should be set for the - /// credential type represented by the instance. - /// - /// The parameters to post to an authorization server - protected abstract void SetParameters(IDictionary parameters); - - void IVssOAuthTokenParameterProvider.SetParameters(IDictionary parameters) - { - SetParameters(parameters); - } - - private Boolean m_disposed; - private readonly String m_clientId; - private readonly VssOAuthClientCredentialType m_type; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredentialType.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredentialType.cs deleted file mode 100644 index 61837c2c7..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredentialType.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace GitHub.Services.OAuth -{ - /// - /// Lists the supported client credential types - /// - public enum VssOAuthClientCredentialType - { - /// - /// Client Password for OAuth 2.0 Client Authentication - /// - Password, - - /// - /// JWT Bearer Token Profile for OAuth 2.0 Client Authentication - /// - JwtBearer, - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredentialsGrant.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredentialsGrant.cs deleted file mode 100644 index ceb06d3a2..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthClientCredentialsGrant.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.OAuth -{ - /// - /// Represents the client credentials grant for OAuth 2.0 token exchanges. - /// - public sealed class VssOAuthClientCredentialsGrant : VssOAuthGrant - { - /// - /// Initializes a new VssOAuthClientCredentials grant. - /// - public VssOAuthClientCredentialsGrant() - : base(VssOAuthGrantType.ClientCredentials) - { - } - - protected override void SetParameters(IDictionary parameters) - { - parameters[VssOAuthConstants.GrantType] = VssOAuthConstants.ClientCredentialsGrantType; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthConstants.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthConstants.cs deleted file mode 100644 index dbff72776..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthConstants.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides constants used in token exhanges for OAuth 2.0 - /// - public static class VssOAuthConstants - { - /// - /// Assertion parameter for token requests. - /// - public const String Assertion = "assertion"; - - /// - /// Authorization Code Grant for OAuth 2.0 - /// - public const String AuthorizationCodeGrantType = "authorization_code"; - - /// - /// Client Credentials Grant for OAuth 2.0 - /// - public const String ClientCredentialsGrantType = "client_credentials"; - - /// - /// Client ID parameter for client authentication. - /// - public const String ClientId = "client_id"; - - /// - /// Client secret parameter for client authentication. - /// - // [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine")] -- The "Password" that follows is not valid anywhere - public const String ClientSecret = "client_secret"; - - /// - /// Client assertion parameter for client authentication. - /// - public const String ClientAssertion = "client_assertion"; - - /// - /// Client assertion type parameter for client authentication. - /// - public const String ClientAssertionType = "client_assertion_type"; - - /// - /// Code parameter for authorization code token requests. - /// - public const String Code = "code"; - - /// - /// Grant type parameter for token requests. - /// - public const String GrantType = "grant_type"; - - /// - /// JWT Bearer Token Grant Type Profile for OAuth 2.0 - /// - /// - /// See http://tools.ietf.org/html/rfc7523 - /// - public const String JwtBearerAuthorizationGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"; - - /// - /// JWT Bearer Token Profile for OAuth 2.0 Client Authentication - /// - /// - /// See http://tools.ietf.org/html/rfc7523 - /// - public const String JwtBearerClientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; - - /// - /// Refresh token parameter for token requests. - /// - public const String RefreshToken = "refresh_token"; - - /// - /// Refresh Token Grant for OAuth 2.0 - /// - public const String RefreshTokenGrantType = "refresh_token"; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthCredential.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthCredential.cs deleted file mode 100644 index b5c4ea5c1..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthCredential.cs +++ /dev/null @@ -1,133 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Net.Http; -using GitHub.Services.Common; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides authentication with a secure token service using the OAuth 2.0 protocol. - /// - public class VssOAuthCredential : FederatedCredential - { - /// - /// Initializes a new VssOAuthCredential instance with the specified authorization grant and client - /// credentials. - /// - /// The location of the token endpoint for the target authorization server - /// The grant to provide for the token exchange - /// The client credentials to provide for the token exchange - /// An optional set of token parameters which, if present, are sent in the request body of the token request - /// An optional access token which, if present, is used prior to requesting new tokens - public VssOAuthCredential( - Uri authorizationUrl, - VssOAuthGrant grant, - VssOAuthClientCredential clientCredential, - VssOAuthTokenParameters tokenParameters = null, - VssOAuthAccessToken accessToken = null) - : base(accessToken) - { - ArgumentUtility.CheckForNull(authorizationUrl, nameof(authorizationUrl)); - ArgumentUtility.CheckForNull(grant, nameof(grant)); - - m_authorizationUrl = authorizationUrl; - m_grant = grant; - m_tokenParameters = tokenParameters; - m_clientCredential = clientCredential; - } - - /// - /// Gets the type of issued token credential. - /// - public override VssCredentialsType CredentialType - { - get - { - return VssCredentialsType.OAuth; - } - } - - /// - /// Gets the authorization endpoint for this credential. - /// - public Uri AuthorizationUrl - { - get - { - return m_authorizationUrl; - } - } - - /// - /// Gets the grant for this credential. - /// - public VssOAuthGrant Grant - { - get - { - return m_grant; - } - } - - /// - /// Gets the client credentials for this credential. - /// - public VssOAuthClientCredential ClientCredential - { - get - { - return m_clientCredential; - } - } - - /// - /// Gets the set of additional token parameters configured for the credential. - /// - public VssOAuthTokenParameters TokenParameters - { - get - { - if (m_tokenParameters == null) - { - m_tokenParameters = new VssOAuthTokenParameters(); - } - return m_tokenParameters; - } - } - - /// - /// Determines whether or not the response reperesents an authentication challenge for the current credential. - /// - /// The response to analyze - /// True if the web response indicates an authorization challenge; otherwise, false - public override Boolean IsAuthenticationChallenge(IHttpResponse webResponse) - { - if (webResponse == null) - { - return false; - } - - if (webResponse.StatusCode == HttpStatusCode.Found || - webResponse.StatusCode == HttpStatusCode.Unauthorized) - { - return webResponse.Headers.GetValues(Common.Internal.HttpHeaders.WwwAuthenticate).Any(x => x.IndexOf("Bearer", StringComparison.OrdinalIgnoreCase) >= 0); - } - - return false; - } - - protected override IssuedTokenProvider OnCreateTokenProvider( - Uri serverUrl, - IHttpResponse response) - { - return new VssOAuthTokenProvider(this, serverUrl); - } - - private VssOAuthTokenParameters m_tokenParameters; - - private readonly Uri m_authorizationUrl; - private readonly VssOAuthGrant m_grant; - private readonly VssOAuthClientCredential m_clientCredential; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthExceptions.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthExceptions.cs deleted file mode 100644 index 5ebf86f9a..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthExceptions.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Runtime.Serialization; -using GitHub.Services.Common; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides a base class for all OAuth exceptions. - /// - [Serializable] - public class VssOAuthException : VssServiceException - { - /// - /// Initializes a new VssOAuthException instance with the specified message. - /// - /// The error message that explains the reason for the exception - public VssOAuthException(String message) - : base(message) - { - } - - /// - /// Initializes a new VssOAuthException instance with the specified message. - /// - /// The error message that explains the reason for the exception - /// An object that describes the error that caused the current exception - public VssOAuthException(String message, Exception innerException) - : base(message, innerException) - { - } - - /// - /// Initializes a new VssOAuthException instance with serialized data. - /// - /// The SerializationInfo that holds the serialized object data about the exception being thrown - /// The StreamingContext that contains contextual information about the source or destination - protected VssOAuthException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } - - /// - /// Thrown when an exception is encountered processing an OAuth 2.0 token request. - /// - [Serializable] - public class VssOAuthTokenRequestException : VssOAuthException - { - /// - /// Initializes a new VssOAuthTokenRequestException instance with the specified message. - /// - /// The error message that explains the reason for the exception - public VssOAuthTokenRequestException(String message) - : base(message) - { - } - - /// - /// Initializes a new VssOAuthTokenRequestException instance with the specified message. - /// - /// The error message that explains the reason for the exception - /// An object that describes the error that caused the current exception - public VssOAuthTokenRequestException(String message, Exception innerException) - : base(message, innerException) - { - } - - /// - /// Initializes a new VssOAuthException instance with serialized data. - /// - /// The SerializationInfo that holds the serialized object data about the exception being thrown - /// The StreamingContext that contains contextual information about the source or destination - protected VssOAuthTokenRequestException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - this.Error = info.GetString("m_error"); - } - - /// - /// Gets or sets the OAuth 2.0 error code. See for potential values. - /// - public String Error - { - get; - set; - } - - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - info.AddValue("m_error", this.Error); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthGrant.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthGrant.cs deleted file mode 100644 index f27435297..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthGrant.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace GitHub.Services.OAuth -{ - /// - /// Represents an authorization grant in an OAuth 2.0 token exchange. - /// - public abstract class VssOAuthGrant : IVssOAuthTokenParameterProvider - { - /// - /// Initializes a new VssOAuthGrant instance with the specified grant type. - /// - /// The type of authorization grant - protected VssOAuthGrant(VssOAuthGrantType grantType) - { - m_grantType = grantType; - } - - /// - /// Gets the type of authorization grant. - /// - public VssOAuthGrantType GrantType - { - get - { - return m_grantType; - } - } - - /// - /// Gets the client credentials authorization grant. - /// - public static VssOAuthClientCredentialsGrant ClientCredentials - { - get - { - return s_clientCredentialsGrant.Value; - } - } - - /// - /// When overridden in a derived class, the corresponding token request parameters should be set for the - /// grant type represented by the instance. - /// - /// The parameters to post to an authorization server - protected abstract void SetParameters(IDictionary parameters); - - void IVssOAuthTokenParameterProvider.SetParameters(IDictionary parameters) - { - SetParameters(parameters); - } - - private readonly VssOAuthGrantType m_grantType; - private static readonly Lazy s_clientCredentialsGrant = new Lazy(() => new VssOAuthClientCredentialsGrant()); - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthGrantType.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthGrantType.cs deleted file mode 100644 index 23834cb15..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthGrantType.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace GitHub.Services.OAuth -{ - /// - /// Lists the supported authorization grant types - /// - public enum VssOAuthGrantType - { - /// - /// Authorization Code Grant for OAuth 2.0 - /// - AuthorizationCode, - - /// - /// Client Credentials Grant for OAuth 2.0 - /// - ClientCredentials, - - /// - /// JWT Bearer Token Grant Type Profile for OAuth 2.0 - /// - JwtBearer, - - /// - /// Refresh Token Grant for OAuth 2.0 - /// - RefreshToken, - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthJwtBearerAssertion.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthJwtBearerAssertion.cs deleted file mode 100644 index 6e451beb2..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthJwtBearerAssertion.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Security.Claims; -using GitHub.Services.WebApi; -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.OAuth -{ - /// - /// Represents a bearer token assertion for either JWT Bearer Token Profile for OAuth 2.0 Client Authentication - /// or JWT Bearer Token Grant Type Profile for OAuth 2.0. - /// - public class VssOAuthJwtBearerAssertion - { - /// - /// Initializes a new VssOAuthJwtBearerAssertion with the specified token as the assertion value. - /// - /// The JsonWebToken instance representing the assertion - internal VssOAuthJwtBearerAssertion(JsonWebToken bearerToken) - { - m_bearerToken = bearerToken; - } - - /// - /// Initializes a new VssOAuthJwtBearerAssertion with the specified issuer, subject, audience, - /// and signing credentials for generating a bearer token. - /// - /// The iss claim for the bearer token - /// The sub claim for the bearer token - /// The aud claim for the bearer token - /// The credentials used to sign the bearer token - public VssOAuthJwtBearerAssertion( - String issuer, - String subject, - String audience, - VssSigningCredentials signingCredentials) - : this(issuer, subject, audience, null, signingCredentials) - { - } - - /// - /// Initializes a new VssOAuthJwtBearerAssertion with the specified issuer, subject, audience, - /// and signing credentials for generating a bearer token. - /// - /// The iss claim for the bearer token - /// The sub claim for the bearer token - /// The aud claim for the bearer token - /// An optional list of additional claims to provide with the bearer token - /// The credentials used to sign the bearer token - public VssOAuthJwtBearerAssertion( - String issuer, - String subject, - String audience, - IList additionalClaims, - VssSigningCredentials signingCredentials) - { - m_issuer = issuer; - m_subject = subject; - m_audience = audience; - m_signingCredentials = signingCredentials; - - if (additionalClaims != null) - { - this.additionalClaims = new List(additionalClaims); - } - } - - /// - /// Gets the issuer (iss claim) for the credentials. - /// - public String Issuer - { - get - { - return m_issuer; - } - } - - /// - /// Gets the subject (sub claim) for the credentials. - /// - public String Subject - { - get - { - return m_subject; - } - } - - /// - /// Gets the audience (aud claim) for the credentials. - /// - public String Audience - { - get - { - return m_audience; - } - } - - /// - /// Gets a list of additional claims provided with the credentials. - /// - public IList AdditionalClaims - { - get - { - if (additionalClaims == null) - { - additionalClaims = new List(); - } - return additionalClaims; - } - } - - /// - /// Gets a JsonWebToken instance based on the values provided to the assertion. - /// - /// A signed JsonWebToken instance for presentation as a bearer token - public JsonWebToken GetBearerToken() - { - if (m_bearerToken != null) - { - return m_bearerToken; - } - else - { - var additionalClaims = new List(this.AdditionalClaims ?? new Claim[0]); - if (!String.IsNullOrEmpty(m_subject)) - { - additionalClaims.Add(new Claim(JsonWebTokenClaims.Subject, m_subject)); - } - - additionalClaims.Add(new Claim(JsonWebTokenClaims.TokenId, Guid.NewGuid().ToString())); - - var nowUtc = DateTime.UtcNow; - return JsonWebToken.Create(m_issuer, m_audience, nowUtc, nowUtc.Add(BearerTokenLifetime), additionalClaims, m_signingCredentials); - } - } - - private List additionalClaims; - private readonly String m_issuer; - private readonly String m_subject; - private readonly String m_audience; - private readonly JsonWebToken m_bearerToken; - private readonly VssSigningCredentials m_signingCredentials; - private static readonly TimeSpan BearerTokenLifetime = TimeSpan.FromMinutes(5); - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthJwtBearerClientCredential.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthJwtBearerClientCredential.cs deleted file mode 100644 index 970fb72df..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthJwtBearerClientCredential.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using GitHub.Services.Common; -using GitHub.Services.WebApi; - -namespace GitHub.Services.OAuth -{ - /// - /// Implements the JWT Bearer Token Profile for OAuth 2.0 Client Authentication. - /// - public sealed class VssOAuthJwtBearerClientCredential : VssOAuthClientCredential - { - /// - /// Initializes a new VssOAuthJwtBearerClientCredential with the specified client identifier and audience. The - /// credential will be used for the JWT Bearer Token Profile for Client Authentication as a client assertion. - /// - /// The client identifier issued by the authorization server - /// The target audience for the bearer assertion. This is usually the authorization URL - /// The signing credentials for proof of client identity - public VssOAuthJwtBearerClientCredential( - String clientId, - String audience, - VssSigningCredentials signingCredentials) - : this(clientId, new VssOAuthJwtBearerAssertion(clientId, clientId, audience, signingCredentials)) - { - } - - /// - /// Initializes a new VssOAuthJwtBearerClientCredential with the specified JWT bearer assertion. - /// - /// The client identifier issued by the authorization server - /// The client assertion for proof of identity - public VssOAuthJwtBearerClientCredential( - String clientId, - VssOAuthJwtBearerAssertion assertion) - : base(VssOAuthClientCredentialType.JwtBearer, clientId) - { - ArgumentUtility.CheckForNull(assertion, nameof(assertion)); - - m_assertion = assertion; - } - - /// - /// Gets the jwt-bearer assertion for issuing tokens. - /// - public VssOAuthJwtBearerAssertion Assertion - { - get - { - return m_assertion; - } - } - - protected override void SetParameters(IDictionary parameters) - { - parameters[VssOAuthConstants.ClientAssertionType] = VssOAuthConstants.JwtBearerClientAssertionType; - parameters[VssOAuthConstants.ClientAssertion] = m_assertion.GetBearerToken().EncodedToken; - } - - private readonly VssOAuthJwtBearerAssertion m_assertion; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenHttpClient.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenHttpClient.cs deleted file mode 100644 index 8f0158f18..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenHttpClient.cs +++ /dev/null @@ -1,216 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Net.Http.Headers; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.Common.Diagnostics; -using GitHub.Services.WebApi; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides a method for exchanging tokens with a secure token service which supports OAuth 2.0. - /// - public class VssOAuthTokenHttpClient - { - /// - /// Initializes a new VssOAuthTokenHttpClient using the specified authorization URL as the token - /// exchange endpoint. Requests for tokens will be posted to the provided URL. - /// - /// The endpoint used to acquire new tokens from the secure token service - public VssOAuthTokenHttpClient(Uri authorizationUrl) - { - ArgumentUtility.CheckForNull(authorizationUrl, nameof(authorizationUrl)); - m_authorizationUrl = authorizationUrl; - m_formatter = new VssJsonMediaTypeFormatter(); - } - - /// - /// Gets the authorization URL for the secure token service. - /// - public Uri AuthorizationUrl - { - get - { - return m_authorizationUrl; - } - } - - /// - /// Performs a token exchange using the specified token request. - /// - /// The token request - /// A token for signalling cancellation - /// A Task<VssOAuthTokenResponse> which may be used to track progress of the token request - public Task GetTokenAsync( - VssOAuthTokenRequest request, - CancellationToken cancellationToken = default(CancellationToken)) - { - ArgumentUtility.CheckForNull(request, nameof(request)); - return GetTokenAsync(request.Grant, request.ClientCredential, request.Parameters, cancellationToken); - } - - /// - /// Performs a token exchange using the specified authorization grant and client credentials. - /// - /// The authorization grant for the token request - /// The credentials to present to the secure token service as proof of identity - /// An collection of additional parameters to provide for the token request - /// A token for signalling cancellation - /// A Task<VssOAuthTokenResponse> which may be used to track progress of the token request - public async Task GetTokenAsync( - VssOAuthGrant grant, - VssOAuthClientCredential credential, - VssOAuthTokenParameters tokenParameters = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - VssTraceActivity traceActivity = VssTraceActivity.Current; - using (HttpClient client = new HttpClient(CreateMessageHandler(this.AuthorizationUrl))) - { - var requestMessage = new HttpRequestMessage(HttpMethod.Post, this.AuthorizationUrl); - requestMessage.Content = CreateRequestContent(grant, credential, tokenParameters); - requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - -#if NETSTANDARD - if (VssClientHttpRequestSettings.Default.UseHttp11) - { - requestMessage.Version = HttpVersion.Version11; - } -#endif - - foreach (var headerVal in VssClientHttpRequestSettings.Default.UserAgent) - { - if (!requestMessage.Headers.UserAgent.Contains(headerVal)) - { - requestMessage.Headers.UserAgent.Add(headerVal); - } - } - - using (var response = await client.SendAsync(requestMessage, cancellationToken: cancellationToken).ConfigureAwait(false)) - { - string correlationId = "Unknown"; - if (response.Headers.TryGetValues("x-ms-request-id", out IEnumerable requestIds)) - { - correlationId = string.Join(",", requestIds); - } - VssHttpEventSource.Log.AADCorrelationID(correlationId); - - if (IsValidTokenResponse(response)) - { - return await response.Content.ReadAsAsync(new[] { m_formatter }, cancellationToken).ConfigureAwait(false); - } - else - { - var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new VssServiceResponseException(response.StatusCode, responseContent, null); - } - } - } - } - - private static Boolean IsValidTokenResponse(HttpResponseMessage response) - { - return response.StatusCode == HttpStatusCode.OK || (response.StatusCode == HttpStatusCode.BadRequest && IsJsonResponse(response)); - } - - private static HttpMessageHandler CreateMessageHandler(Uri requestUri) - { - var retryOptions = new VssHttpRetryOptions() - { - RetryableStatusCodes = - { - HttpStatusCode.InternalServerError, - VssNetworkHelper.TooManyRequests, - }, - }; - -#if !NETSTANDARD - WebRequestHandler messageHandler = new WebRequestHandler() - { - UseDefaultCredentials = false - }; -#else - HttpClientHandler messageHandler = new HttpClientHandler() - { - UseDefaultCredentials = false - }; -#endif - - // Inherit proxy setting from VssHttpMessageHandler - if (VssHttpMessageHandler.DefaultWebProxy != null) - { - messageHandler.Proxy = VssHttpMessageHandler.DefaultWebProxy; - messageHandler.UseProxy = true; - } - - if (requestUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) && - VssClientHttpRequestSettings.Default.ClientCertificateManager != null && - VssClientHttpRequestSettings.Default.ClientCertificateManager.ClientCertificates != null && - VssClientHttpRequestSettings.Default.ClientCertificateManager.ClientCertificates.Count > 0) - { - messageHandler.ClientCertificates.AddRange(VssClientHttpRequestSettings.Default.ClientCertificateManager.ClientCertificates); - } - - if (requestUri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase) && - VssClientHttpRequestSettings.Default.ServerCertificateValidationCallback != null) - { -#if !NETSTANDARD - messageHandler.ServerCertificateValidationCallback = VssClientHttpRequestSettings.Default.ServerCertificateValidationCallback; -#else - messageHandler.ServerCertificateCustomValidationCallback = VssClientHttpRequestSettings.Default.ServerCertificateValidationCallback; -#endif - } - - return new VssHttpRetryMessageHandler(retryOptions, messageHandler); - } - - private static HttpContent CreateRequestContent(params IVssOAuthTokenParameterProvider[] parameterProviders) - { - var parameters = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var parameterProvider in parameterProviders) - { - if (parameterProvider != null) - { - parameterProvider.SetParameters(parameters); - } - } - - return new FormUrlEncodedContent(parameters); - } - - private static Boolean HasContent(HttpResponseMessage response) - { - if (response != null && - response.StatusCode != HttpStatusCode.NoContent && - response.Content != null && - response.Content.Headers != null && - response.Content.Headers.ContentLength.HasValue && - response.Content.Headers.ContentLength != 0) - { - return true; - } - - return false; - } - - private static Boolean IsJsonResponse(HttpResponseMessage response) - { - if (HasContent(response) && - response.Content.Headers != null && - response.Content.Headers.ContentType != null && - !String.IsNullOrEmpty(response.Content.Headers.ContentType.MediaType)) - { - return String.Equals("application/json", response.Content.Headers.ContentType.MediaType, StringComparison.OrdinalIgnoreCase); - } - - return false; - } - - private readonly Uri m_authorizationUrl; - private readonly MediaTypeFormatter m_formatter; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenParameters.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenParameters.cs deleted file mode 100644 index e214121ec..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenParameters.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides additional parameters for OAuth 2.0 token requests. Existing values may be removed by setting the - /// property to null. Properties with no value should use an empty string. - /// - [JsonDictionary] - public class VssOAuthTokenParameters : Dictionary, IVssOAuthTokenParameterProvider - { - /// - /// Initializes a new VssOAuthTokenParameters instance with no additional parameters. - /// - public VssOAuthTokenParameters() - : base(StringComparer.OrdinalIgnoreCase) - { - } - - /// - /// Gets or sets the redirect_uri parameter, specifying the redirection endpoint for the user-agent after - /// the authorization server completes interaction with the resource owner. - /// - public String RedirectUri - { - get - { - return GetValueOrDefault("redirect_uri"); - } - set - { - RemoveOrSetValue("redirect_uri", value); - } - } - - /// - /// Gets or sets the resource parameter, indicating the target resource for the token request. - /// - /// - /// At the time of writing, the specification for this parameter may be found at the link below. - /// https://datatracker.ietf.org/doc/draft-campbell-oauth-resource-indicators/?include_text=1 - /// - public String Resource - { - get - { - return GetValueOrDefault("resource"); - } - set - { - RemoveOrSetValue("resource", value); - } - } - - /// - /// Gets or sets the scope parameter, indicating the scope of the access request. - /// - public String Scope - { - get - { - return GetValueOrDefault("scope"); - } - set - { - RemoveOrSetValue("scope", value); - } - } - - - /// - /// Gets a string representation of the additional parameters as a JSON string. - /// - /// A string representation of the parameters which are set - public override String ToString() - { - return JsonConvert.SerializeObject(this); - } - - void IVssOAuthTokenParameterProvider.SetParameters(IDictionary parameters) - { - foreach (var parameter in this) - { - parameters[parameter.Key] = parameter.Value; - } - } - - private String GetValueOrDefault(String key) - { - String value; - if (!TryGetValue(key, out value)) - { - value = null; - } - - return value; - } - - private void RemoveOrSetValue( - String key, - String value) - { - if (value == null) - { - this.Remove(key); - } - else - { - this[key] = value; - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs deleted file mode 100644 index e910b259f..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenProvider.cs +++ /dev/null @@ -1,214 +0,0 @@ -using System; -using System.Globalization; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.Common.Diagnostics; -using GitHub.Services.WebApi; -using Newtonsoft.Json; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides functionality to acquire access tokens for OAuth 2.0. - /// - public class VssOAuthTokenProvider : IssuedTokenProvider - { - /// - /// Initializes a new VssOAuthTokenProvider instance for the specified credential. - /// - /// The VssOAuthCredential instance which owns the token provider - /// The resource server which issued the authentication challenge - public VssOAuthTokenProvider( - VssOAuthCredential credential, - Uri serverUrl) - : this(credential, serverUrl, credential.AuthorizationUrl, credential.Grant, credential.ClientCredential, credential.TokenParameters) - { - m_credential = credential; - } - - /// - /// Initializes a new VssOAuthTokenProvider instance for the specified credential. - /// - /// The VssOAuthCredential instance which owns the token provider - /// The resource server which issued the authentication challenge - /// The authorization server token endpoint - /// The authorization grant to use for token requests - /// The client credentials to use for token requests - /// Additional parameters to include with token requests - protected VssOAuthTokenProvider( - IssuedTokenCredential credential, - Uri serverUrl, - Uri authorizationUrl, - VssOAuthGrant grant, - VssOAuthClientCredential clientCrential, - VssOAuthTokenParameters tokenParameters) - : base(credential, serverUrl, authorizationUrl) - { - m_grant = grant; - m_tokenParameters = tokenParameters; - m_clientCredential = clientCrential; - } - - /// - /// Gets the authorization grant for the token provider. - /// - public VssOAuthGrant Grant - { - get - { - return m_grant; - } - } - - /// - /// Gets the client credentials for the token provider. - /// - public VssOAuthClientCredential ClientCredential - { - get - { - return m_clientCredential; - } - } - - /// - /// Gets the additional parameters configured for the token provider. - /// - public VssOAuthTokenParameters TokenParameters - { - get - { - return m_tokenParameters; - } - } - - /// - /// Gets a value indicating whether or not this token provider requires interactivity. - /// - public override Boolean GetTokenIsInteractive - { - get - { - return false; - } - } - - protected override String AuthenticationParameter - { - get - { - if (this.ClientCredential == null) - { - return null; - } - else - { - return String.Format(CultureInfo.InvariantCulture, "client_id=\"{0}\" audience=\"{1}\"", this.ClientCredential.ClientId, this.SignInUrl.AbsoluteUri); - } - } - } - - protected override String AuthenticationScheme - { - get - { - return "Bearer"; - } - } - - /// - /// Issues a token request to the configured secure token service. On success, the access token issued by the - /// token service is returned to the caller - /// - /// If applicable, the previous token which is now considered invalid - /// A token used for signalling cancellation - /// A Task&lgt;IssuedToken> for tracking the progress of the token request - protected override async Task OnGetTokenAsync( - IssuedToken failedToken, - CancellationToken cancellationToken) - { - if (this.SignInUrl == null || - this.Grant == null || - this.ClientCredential == null) - { - return null; - } - - IssuedToken issuedToken = null; - var traceActivity = VssTraceActivity.Current; - try - { - var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl); - var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken).ConfigureAwait(false); - if (!String.IsNullOrEmpty(tokenResponse.AccessToken)) - { - // Construct a new access token based on the response, including the expiration time so we know - // when to refresh the token. - issuedToken = CreateIssuedToken(tokenResponse); - - if (!String.IsNullOrEmpty(tokenResponse.RefreshToken)) - { - // TODO: How should this flow be handled? Refresh Token is a credential change which is not - // the same thing as access token storage - } - } - else if (!String.IsNullOrEmpty(tokenResponse.Error)) - { - // Raise a new exception describing the underlying authentication error - throw new VssOAuthTokenRequestException(tokenResponse.ErrorDescription) - { - Error = tokenResponse.Error, - }; - } - else - { - // If the error property isn't set, but we didn't get an access token, then it's not - // clear what the issue is. In this case just trace the response and fall through with - // a null access token return value. - var sb = new StringBuilder(); - var serializer = JsonSerializer.Create(s_traceSettings.Value); - using (var sr = new StringWriter(sb)) - { - serializer.Serialize(sr, tokenResponse); - } - - VssHttpEventSource.Log.AuthenticationError(traceActivity, this, sb.ToString()); - } - } - catch (VssServiceResponseException ex) - { - VssHttpEventSource.Log.AuthenticationError(traceActivity, this, ex); - } - - return issuedToken; - } - - protected virtual IssuedToken CreateIssuedToken(VssOAuthTokenResponse tokenResponse) - { - if (tokenResponse.ExpiresIn > 0) - { - return new VssOAuthAccessToken(tokenResponse.AccessToken, DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn)); - } - else - { - return new VssOAuthAccessToken(tokenResponse.AccessToken); - } - } - - private static JsonSerializerSettings CreateTraceSettings() - { - var settings = new VssJsonMediaTypeFormatter().SerializerSettings; - settings.Formatting = Formatting.Indented; - return settings; - } - - private readonly VssOAuthGrant m_grant; - private readonly VssOAuthCredential m_credential; - private readonly VssOAuthTokenParameters m_tokenParameters; - private readonly VssOAuthClientCredential m_clientCredential; - private static readonly Lazy s_traceSettings = new Lazy(CreateTraceSettings); - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenRequest.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenRequest.cs deleted file mode 100644 index 3e21ab7e3..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenRequest.cs +++ /dev/null @@ -1,232 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net.Http.Formatting; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.OAuth -{ - /// - /// Encapsulates the data used in an OAuth 2.0 token request. - /// - public class VssOAuthTokenRequest - { - /// - /// Initializes a new VssOAuthTokenRequest instance with the specified grant and client credential. - /// - /// The authorization grant to use for the token request - /// The client credential to use for the token request - public VssOAuthTokenRequest( - VssOAuthGrant grant, - VssOAuthClientCredential clientCredential) - : this(grant, clientCredential, null) - { - } - - /// - /// Initializes a new VssOAuthTokenRequest instance with the specified grant and client credential. - /// Additional parameters specified by the token parameters will be provided in the token request. - /// - /// The authorization grant to use for the token request - /// The client credential to use for the token request - /// An optional set of additional parameters for the token request - public VssOAuthTokenRequest( - VssOAuthGrant grant, - VssOAuthClientCredential clientCredential, - VssOAuthTokenParameters tokenParameters) - { - ArgumentUtility.CheckForNull(grant, nameof(grant)); - - m_grant = grant; - m_clientCredential = clientCredential; - m_tokenParameters = tokenParameters; - } - - /// - /// Gets the authorization grant for this token request. - /// - public VssOAuthGrant Grant - { - get - { - return m_grant; - } - } - - /// - /// Gets the client credential for this token request. Depending on the grant ype used, this value may be null. - /// - public VssOAuthClientCredential ClientCredential - { - get - { - return m_clientCredential; - } - } - - /// - /// Gets the optional set of additional parameters for this token request. - /// - public VssOAuthTokenParameters Parameters - { - get - { - if (m_tokenParameters == null) - { - m_tokenParameters = new VssOAuthTokenParameters(); - } - return m_tokenParameters; - } - } - -#if !NETSTANDARD - /// - /// Initializes a new VssOAuthTokenRequest instance from the specified form input. - /// - /// The input which should be parsed into a token request - /// A new VssOAuthTokenRequest instance representative of the provided form input - public static VssOAuthTokenRequest FromFormInput(FormDataCollection form) - { - var parsedParameters = new HashSet(); - var grant = CreateGrantFromFormInput(form, parsedParameters); - var clientCredential = CreateClientCredentialFromFormInput(form, parsedParameters); - - var tokenParameters = new VssOAuthTokenParameters(); - foreach (var parameter in form) - { - // Only include parameters in the extended set if we didn't already read them in the grant and - // credentials parsing logic. - if (parsedParameters.Add(parameter.Key)) - { - tokenParameters.Add(parameter.Key, parameter.Value); - } - } - - return new VssOAuthTokenRequest(grant, clientCredential, tokenParameters); - } - - private static VssOAuthGrant CreateGrantFromFormInput( - FormDataCollection form, - ISet parsedParameters) - { - ArgumentUtility.CheckForNull(form, nameof(form)); - - var grantType = GetRequiredValue(form, VssOAuthConstants.GrantType, VssOAuthErrorCodes.InvalidRequest); - switch (grantType) - { - case VssOAuthConstants.AuthorizationCodeGrantType: - var codeValue = GetRequiredValue(form, VssOAuthConstants.Code, VssOAuthErrorCodes.InvalidRequest); - parsedParameters.Add(VssOAuthConstants.Code); - return new VssOAuthCodeGrant(codeValue); - - case VssOAuthConstants.ClientCredentialsGrantType: - return VssOAuthGrant.ClientCredentials; - - case VssOAuthConstants.JwtBearerAuthorizationGrantType: - var assertionValue = GetRequiredValue(form, VssOAuthConstants.Assertion, VssOAuthErrorCodes.InvalidRequest); - parsedParameters.Add(VssOAuthConstants.Assertion); - var assertion = JsonWebToken.Create(assertionValue); - return new VssOAuthJwtBearerGrant(new VssOAuthJwtBearerAssertion(assertion)); - - case VssOAuthConstants.RefreshTokenGrantType: - var refreshTokenValue = GetRequiredValue(form, VssOAuthConstants.RefreshToken, VssOAuthErrorCodes.InvalidRequest); - parsedParameters.Add(VssOAuthConstants.RefreshToken); - return new VssOAuthRefreshTokenGrant(refreshTokenValue); - - default: - // The OAuth 2.0 spec explicitly allows only ASCII characters in the error description - throw new VssOAuthTokenRequestException($"{VssOAuthConstants.GrantType} {grantType} is not supported") - { - Error = VssOAuthErrorCodes.UnsupportedGrantType, - }; - } - } - - private static VssOAuthClientCredential CreateClientCredentialFromFormInput( - FormDataCollection form, - ISet parsedParameters) - { - // https://tools.ietf.org/html/rfc7521#section-4.2 - // See the above document for rules on processing client assertions w.r.t other credential types. - var clientId = form[VssOAuthConstants.ClientId]; - var clientAssertionType = form[VssOAuthConstants.ClientAssertionType]; - if (clientAssertionType == VssOAuthConstants.JwtBearerClientAssertionType) - { - var clientAssertionValue = GetRequiredValue(form, VssOAuthConstants.ClientAssertion, VssOAuthErrorCodes.InvalidClient); - JsonWebToken clientAssertion = null; - try - { - clientAssertion = JsonWebToken.Create(clientAssertionValue); - } - catch (JsonWebTokenDeserializationException ex) - { - // The OAuth 2.0 spec explicitly allows only ASCII characters in the error description - throw new VssOAuthTokenRequestException($"{VssOAuthConstants.ClientAssertion} is not in the correct format", ex) - { - Error = VssOAuthErrorCodes.InvalidClient - }; - } - - // If the client id parameter is present when client assertions are used then it must match exactly - // the subject claim of the token. - if (!String.IsNullOrEmpty(clientId)) - { - if (clientId.Equals(clientAssertion.Subject, StringComparison.Ordinal)) - { - parsedParameters.Add(VssOAuthConstants.ClientId); - } - else - { - // The OAuth 2.0 spec explicitly allows only ASCII characters in the error description - throw new VssOAuthTokenRequestException($"{VssOAuthConstants.ClientId} {clientId} does not match {VssOAuthConstants.ClientAssertion} subject {clientAssertion.Subject}") - { - Error = VssOAuthErrorCodes.InvalidClient, - }; - } - } - else - { - clientId = clientAssertion.Subject; - } - - parsedParameters.Add(VssOAuthConstants.ClientAssertion); - parsedParameters.Add(VssOAuthConstants.ClientAssertionType); - return new VssOAuthJwtBearerClientCredential(clientId, new VssOAuthJwtBearerAssertion(clientAssertion)); - } - - if (!String.IsNullOrEmpty(clientId)) - { - parsedParameters.Add(VssOAuthConstants.ClientId); - - var clientSecret = form[VssOAuthConstants.ClientSecret]; - if (!String.IsNullOrEmpty(clientSecret)) - { - parsedParameters.Add(VssOAuthConstants.ClientSecret); - return new VssOAuthPasswordClientCredential(clientId, clientSecret); - } - } - - return null; - } - - private static String GetRequiredValue( - FormDataCollection form, - String parameterName, - String error) - { - var value = form[parameterName]; - if (String.IsNullOrEmpty(value)) - { - throw new VssOAuthTokenRequestException($"{parameterName} is required") { Error = error }; - } - - return value; - } -#endif - - private VssOAuthTokenParameters m_tokenParameters; - - private readonly VssOAuthGrant m_grant; - private readonly VssOAuthClientCredential m_clientCredential; - } -} diff --git a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs b/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs deleted file mode 100644 index fab331726..000000000 --- a/src/Sdk/WebApi/WebApi/OAuth/VssOAuthTokenResponse.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.OAuth -{ - /// - /// Provides the properties for the response of a token exchange in OAuth 2.0 - /// - [DataContract] - public class VssOAuthTokenResponse - { - /// - /// Initializes a new VssOAuthTokenResponse instance with empty values. - /// - public VssOAuthTokenResponse() - { - } - - /// - /// Gets or sets the access token for the response. - /// - [DataMember(Name = "access_token", EmitDefaultValue = false)] - public String AccessToken - { - get; - set; - } - - /// - /// Gets or sets the error for the response. - /// - [DataMember(Name = "error", EmitDefaultValue = false)] - public String Error - { - get; - set; - } - - /// - /// Gets or sets the error description for the response. - /// - [DataMember(Name = "errordescription", EmitDefaultValue = false)] - public String ErrorDescription - { - get; - set; - } - - /// - /// Gets or sets a value indicating the remaining duration, in seconds, of the access token. - /// - [DataMember(Name = "expires_in", EmitDefaultValue = false)] - public Int32 ExpiresIn - { - get; - set; - } - - /// - /// Gets or sets the refresh token for the response, if applicable. - /// - [DataMember(Name = "refresh_token", EmitDefaultValue = false)] - public String RefreshToken - { - get; - set; - } - - /// - /// Gets or sets the scope or scopes of access for the provided access token. - /// - [DataMember(Name = "scope", EmitDefaultValue = false)] - public String Scope - { - get; - set; - } - - /// - /// Gets or sets the type of token for the response. - /// - [DataMember(Name = "token_type", EmitDefaultValue = false)] - public String TokenType - { - get; - set; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Profile/ProfileArgumentValidation.cs b/src/Sdk/WebApi/WebApi/Profile/ProfileArgumentValidation.cs deleted file mode 100644 index ff27f4257..000000000 --- a/src/Sdk/WebApi/WebApi/Profile/ProfileArgumentValidation.cs +++ /dev/null @@ -1,40 +0,0 @@ -using GitHub.Services.Common; -using System; - -namespace GitHub.Services.Profile -{ - public static class ProfileArgumentValidation - { - public static void ValidateAttributeName(string attributeName) - { - ArgumentUtility.CheckStringForNullOrEmpty(attributeName, "attributeName", true); - ArgumentUtility.CheckStringForInvalidCharacters(attributeName, "attributeName"); - if (attributeName.Contains(Semicolon)) - { - throw new ArgumentException("Attribute name cannot contain the character ';'", attributeName); - } - } - - public static void ValidateContainerName(string containerName) - { - ArgumentUtility.CheckStringForNullOrEmpty(containerName, "containerName", true); - ArgumentUtility.CheckStringForInvalidCharacters(containerName, "containerName"); - if (containerName.Contains(Semicolon)) - { - throw new ArgumentException("Container name cannot contain the character ';'", containerName); - } - } - - public static void ValidateApplicationContainerName(string containerName) - { - ValidateContainerName(containerName); - if (VssStringComparer.AttributesDescriptor.Compare(containerName, Profile.CoreContainerName) == 0) - { - throw new ArgumentException( - string.Format("The container name '{0}' is reserved. Please specify a valid application container name", Profile.CoreContainerName), "containerName"); - } - } - - private const string Semicolon = ";"; - } -} diff --git a/src/Sdk/WebApi/WebApi/ProxyAuthenticationRequiredException.cs b/src/Sdk/WebApi/WebApi/ProxyAuthenticationRequiredException.cs deleted file mode 100644 index 8d5261719..000000000 --- a/src/Sdk/WebApi/WebApi/ProxyAuthenticationRequiredException.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi -{ - [ExceptionMapping("0.0", "3.0", "ProxyAuthenticationRequiredException", "GitHub.Services.WebApi.ProxyAuthenticationRequiredException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ProxyAuthenticationRequiredException : VssException - { - public ProxyAuthenticationRequiredException() - : base(WebApiResources.ProxyAuthenticationRequired()) - { - this.HelpLink = HelpLinkUrl; - } - - public ProxyAuthenticationRequiredException(string message, Exception innerException) - : base(message, innerException) - { - this.HelpLink = HelpLinkUrl; - } - - public ProxyAuthenticationRequiredException(string message) - : base(message) - { - this.HelpLink = HelpLinkUrl; - } - - private const string HelpLinkUrl = ""; - } -} diff --git a/src/Sdk/WebApi/WebApi/PublicAccessJsonConverter.cs b/src/Sdk/WebApi/WebApi/PublicAccessJsonConverter.cs deleted file mode 100644 index 9a39a06e5..000000000 --- a/src/Sdk/WebApi/WebApi/PublicAccessJsonConverter.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.ComponentModel; -using System.Reflection; -using Newtonsoft.Json; - -namespace GitHub.Services.WebApi -{ - /// - /// A JsonConverter that sets the value of a property or field to its type's default value if the value is not null - /// and the ShouldClearValueFunction property is set and the ShouldClearValueFunction function returns true. This - /// can only be used on properties and fields. The converter will fail if used on at the class level. - /// - /// The type of the property or field. - [EditorBrowsable(EditorBrowsableState.Never)] - public class DefaultValueOnPublicAccessJsonConverter : PublicAccessJsonConverter - { - public override object GetDefaultValue() - { - return default(T); - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public abstract class PublicAccessJsonConverter : PublicAccessJsonConverter - { - public PublicAccessJsonConverter() - { - if (typeof(T) == typeof(bool)) - { - // We are not supporting boolean types. This is because the converter does not get invoked in case of default values, - // therefore you can infer that a boolean type is false if the value does not exist in the json, and true if it does - // exist in the json even though the value would be set to false. - throw new ArgumentException($"The {nameof(PublicAccessJsonConverter)} does not support Boolean types, because the value can be inferred from the existance or non existance of the property in the json."); - } - } - - public override bool CanConvert(Type objectType) - { - return typeof(T).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public abstract class PublicAccessJsonConverter : JsonConverter - { - public abstract object GetDefaultValue(); - - public override bool CanRead => false; - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - if (value != null && ShouldClearValueFunction != null && ShouldClearValueFunction()) - { - serializer.Serialize(writer, GetDefaultValue()); - } - else - { - // this is the default serialization. This will fail if the converter is used at the class level rather than - // at the member level, because the default serialization will reinvoke this converter resulting in an exception. - serializer.Serialize(writer, value); - } - } - - internal static Func ShouldClearValueFunction { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/ResourceLocationIds.cs b/src/Sdk/WebApi/WebApi/ResourceLocationIds.cs deleted file mode 100644 index f4ccaa58b..000000000 --- a/src/Sdk/WebApi/WebApi/ResourceLocationIds.cs +++ /dev/null @@ -1,1511 +0,0 @@ -using System; -using GitHub.Services.Common; - -//each resource (aka "controller") needs its own guid -//for the location service. Defined here so we can use it on the client -//to look it up. -namespace GitHub.Services.Identity -{ - public static class IdentityResourceIds - { - public const string AreaId = "8A3D49B8-91F0-46EF-B33D-DDA338C25DB3"; - public const string AreaName = "IMS"; - public static readonly Guid Identity = new Guid("{28010C54-D0C0-4C89-A5B0-1C9E188B9FB7}"); - public const string IdentityResource = "Identities"; - public static readonly Guid IdentityBatch = new Guid("{299E50DF-FE45-4D3A-8B5B-A5836FAC74DC}"); - public const string IdentityBatchResource = "IdentityBatch"; - public static readonly Guid Group = new Guid("{5966283B-4196-4D57-9211-1B68F41EC1C2}"); - public const string GroupResource = "Groups"; - public static readonly Guid Scope = new Guid("{4E11E2BF-1E79-4EB5-8F34-A6337BD0DE38}"); - public const string ScopeResource = "Scopes"; - public const string MemberLocationIdString = "8BA35978-138E-41F8-8963-7B1EA2C5F775"; - public static readonly Guid Member = new Guid(MemberLocationIdString); - public const string MemberResource = "Members"; - public const string MemberOfLocationIdString = "22865B02-9E4A-479E-9E18-E35B8803B8A0"; - public static readonly Guid MemberOf = new Guid(MemberOfLocationIdString); - public const string MemberOfResource = "MembersOf"; - public static readonly Guid IdentityDebug = new Guid("{C6B859A5-248C-448A-B770-D373C6E165BD}"); - public const string IdentityDebugResource = "IdentitiesDebug"; - public static readonly Guid IdentitySnapshot = new Guid("{D56223DF-8CCD-45C9-89B4-EDDF692400D7}"); - public const string IdentitySnapshotResource = "IdentitySnapshot"; - public static readonly Guid IdentitySelf = new Guid("{4BB02B5B-C120-4BE2-B68E-21F7C50A4B82}"); - public const string IdentitySelfResource = "me"; - public static readonly Guid SignoutToken = new Guid("{BE39E83C-7529-45E9-9C67-0410885880DA}"); - public const string SignoutTokenResource = "SignoutToken"; - public static readonly Guid SignedInToken = new Guid("{6074FF18-AAAD-4ABB-A41E-5C75F6178057}"); - public const string SignedInTokenResource = "SignedInToken"; - public static readonly Guid IdentityTenant = new Guid("{5F0A1723-2E2C-4C31-8CAE-002D01BDD592}"); - public const string IdentityTenantResource = "tenant"; - public static readonly Guid FrameworkIdentity = new Guid("{DD55F0EB-6EA2-4FE4-9EBE-919E7DD1DFB4}"); - public const string FrameworkIdentityResource = "Identity"; - public static readonly Guid IdentityMaxSequenceId = new Guid("{E4A70778-CB2C-4E85-B7CC-3F3C7AE2D408}"); - public const string IdentityMaxSequenceIdResource = "MaxSequenceId"; - public static readonly Guid Claims = new Guid("{90ddfe71-171c-446c-bf3b-b597cd562afd}"); - public const string ClaimsResource = "Claims"; - public static readonly Guid Rights = new Guid("{05F0AD48-6AEF-42A8-9D9B-9AB650875A5D}"); - public const string RightsResource = "Rights"; - public static readonly Guid RightsBatch = new Guid("{908B4EDC-4C6A-41E8-88ED-07A1F01A9A59}"); - - public static readonly Guid DescriptorsResourceLocationId = new Guid("A230389A-94F2-496C-839F-C929787496DD"); - public const string DescriptorsResourceName = "descriptors"; - - public static readonly Guid SwapLocationId = new Guid("{7A2338C2-39D8-4906-9889-E8BC9C52CBB2}"); - public const string SwapResource = "Swap"; - } -} - -namespace GitHub.Services.Graph -{ - public class GraphResourceIds - { - public const string AreaName = "Graph"; - public const string AreaId = "BB1E7EC9-E901-4B68-999A-DE7012B920F8"; - public static readonly Guid AreaIdGuid = new Guid(AreaId); - - public class Groups - { - public const string GroupsResourceName = "Groups"; - public static readonly Guid GroupsResourceLocationId = new Guid("EBBE6AF8-0B91-4C13-8CF1-777C14858188"); - } - - public class Descriptors - { - public static readonly Guid DescriptorsResourceLocationId = new Guid("048AEE0A-7072-4CDE-AB73-7AF77B1E0B4E"); - public const string DescriptorsResourceName = "Descriptors"; - } - - public class Memberships - { - public static readonly Guid MembershipsResourceLocationId = new Guid("3FD2E6CA-FB30-443A-B579-95B19ED0934C"); - public const string MembershipsResourceName = "Memberships"; - - public static readonly Guid MembershipsBatchResourceLocationId = new Guid("E34B6394-6B30-4435-94A9-409A5EEF3E31"); - public const string MembershipsBatchResourceName = "MembershipsBatch"; - - public static readonly Guid MembershipStatesResourceLocationId = new Guid("1FFE5C94-1144-4191-907B-D0211CAD36A8"); - public const string MembershipStatesResourceName = "MembershipStates"; - } - - public class Scopes - { - public const string ScopesResourceName = "Scopes"; - public static readonly Guid ScopesResourceLocationId = new Guid("21B5FEA7-2513-41D0-AF78-B8CDB0F328BB"); - } - - public class SubjectLookup - { - public const string SubjectLookupResourceName = "SubjectLookup"; - public static readonly Guid SubjectLookupResourceLocationId = new Guid("4DD4D168-11F2-48C4-83E8-756FA0DE027C"); - } - - public class Users - { - public const string UsersResourceName = "Users"; - public static readonly Guid UsersResourceLocationId = new Guid("005E26EC-6B77-4E4F-A986-B3827BF241F5"); - - public class ProviderInfo - { - public const string ProviderInfoResourceName = "ProviderInfo"; - public static readonly Guid ProviderInfoResourceLocationId = new Guid("1E377995-6FA2-4588-BD64-930186ABDCFA"); - } - } - - public class Subjects - { - public const string SubjectsResourceName = "Subjects"; - public static readonly Guid SubjectsResourceLocationId = new Guid("1D44A2AC-4F8A-459E-83C2-1C92626FB9C6"); - - public class Avatars - { - public const string AvatarsResourceName = "Avatars"; - public static readonly Guid AvatarsResourceLocationId = new Guid("801EAF9C-0585-4BE8-9CDB-B0EFA074DE91"); - } - } - - public class Members - { - public const string MembersResourceName = "Members"; - - public const string MembersByDescriptorResourceLocationIdString = "B9AF63A7-5DB6-4AF8-AAE7-387F775EA9C6"; - public static readonly Guid MembersByDescriptorResourceLocationId = new Guid(MembersByDescriptorResourceLocationIdString); - - public const string MembersResourceLocationIdString = "8B9ECDB2-B752-485A-8418-CC15CF12EE07"; - public static readonly Guid MembersResourceLocationId = new Guid(MembersResourceLocationIdString); - } - - public class CachePolicies - { - public const string CachePoliciesResourceName = "CachePolicies"; - public static readonly Guid CachePoliciesResourceLocationId = new Guid("BEB83272-B415-48E8-AC1E-A9B805760739"); - } - - public class MemberLookup - { - public const string MemberLookupResourceName = "MemberLookup"; - public static readonly Guid MemberLookupResourceLocationId = new Guid("3D74D524-AE3D-4D24-A9A7-F8A5CF82347A"); - } - - public class StorageKeys - { - public const string StorageKeysResourceName = "StorageKeys"; - public static readonly Guid StorageKeysResourceLocationId = new Guid("EB85F8CC-F0F6-4264-A5B1-FFE2E4D4801F"); - } - - public class MembershipTraversals - { - public const string MembershipTraversalsResourceName = "MembershipTraversals"; - public static readonly Guid MembershipTraversalsLocationId = new Guid("5D59D874-746F-4F9B-9459-0E571F1DED8C"); - } - - public class FederatedProviderData - { - public static readonly Guid FederatedProviderDataResourceLocationId = new Guid("5DCD28D6-632D-477F-AC6B-398EA9FC2F71"); - public const string FederatedProviderDataResourceName = "FederatedProviderData"; - } - } -} - -namespace GitHub.GraphProfile.WebApi -{ - [GenerateAllConstants] - public static class GraphProfileResourceIds - { - public const String AreaId = "4E40F190-2E3F-4D9F-8331-C7788E833080"; - public const String AreaName = "GraphProfile"; - public static readonly Guid AreaIdGuid = new Guid(AreaId); - - public class MemberAvatars - { - public const String MemberAvatarsResourceName = "MemberAvatars"; - public static readonly Guid MemberAvatarsLocationId = new Guid("D443431F-B341-42E4-85CF-A5B0D639ED8F"); - } - } -} - -namespace GitHub.Services.OAuth -{ - public static class TokenOAuth2ResourceIds - { - public const string AreaName = "tokenoauth2"; - public const string AreaId = "01c5c153-8bc0-4f07-912a-ec4dc386076d"; - - public const string TokenResource = "token"; - public static readonly Guid Token = new Guid("{bbc63806-e448-4e88-8c57-0af77747a323}"); - } - - public static class OAuth2ResourceIds - { - public const string AreaName = "oauth2"; - public const string AreaId = "585028FE-17D8-49E2-9A1B-EFB4D8502156"; - - public const string TokenResource = "token"; - public static readonly Guid Token = new Guid("{CD12634C-1D0F-4A19-9FF3-17875B764932}"); - } -} - -namespace GitHub.Services.Tokens -{ - public static class TokenAuthResourceIds - { - public const string AreaName = "TokenAuth"; - public const string AreaId = "c5a2d98b-985c-432e-825e-3c6971edae87"; - - public const string AuthorizationResource = "Authorizations"; - public static readonly Guid Authorization = new Guid("7d7ddc0d-60bd-4978-a0b5-295cb099a400"); - - public const string HostAuthorizationResource = "HostAuthorization"; - public static readonly Guid HostAuthorizeId = new Guid("{817d2b46-1507-4efe-be2b-adccf17ffd3b}"); - - public const string RegistrationResource = "Registration"; - public static readonly Guid Registration = new Guid("{522ad1a0-389d-4c6f-90da-b145fd2d3ad8}"); - - public const string RegistrationSecretResource = "RegistrationSecret"; - public static readonly Guid RegistrationSecret = new Guid("{74896548-9cdd-4315-8aeb-9ecd88fceb21}"); - } - - public static class TokenIssueResourceIds - { - public const string AreaName = "TokenIssue"; - public const string AreaId = "6b10046c-829d-44d2-8a1d-02f88f4ff032"; - - public const string AccessTokenResource = "AccessTokens"; - public static readonly Guid AccessToken = new Guid("{24691e90-c8bd-42c0-8aae-71b7511a797a}"); - - public const string SessionTokenResource = "SessionTokens"; - public static readonly Guid SessionToken = new Guid("{98e25729-952a-4b1f-ac89-7ca8b9803261}"); - - public const string AadUserTokenResource = "AadUserTokens"; - public static readonly Guid AadUserToken = new Guid("{4cbff9ec-7f69-4d40-a82e-cca1e8545d01}"); - - public const string AadAppTokenResource = "AadAppTokens"; - public static readonly Guid AadAppToken = new Guid("{f15de83d-4b1d-4387-90aa-e72c0ce10b3e}"); - - public const string AppSessionTokenResource = "AppSessionTokens"; - public static readonly Guid AppSessionToken = new Guid("{325f73ea-e978-4ad1-8f3a-c30b39000a17}"); - - public const string AppTokenPairResource = "AppTokenPairs"; - public static readonly Guid AppTokenPair = new Guid("{9030cb81-c1fd-4f3b-9910-c90eb559b830}"); - } - - public static class TokenTokenExpirationResourceIds - { - public const string AreaName = "TokenExpiration"; - public const string AreaId = "339c63b0-d305-4fd3-958a-22b8e0eb6fc2"; - - public const string TokenExpirationResource = "Token"; - public static readonly Guid TokenExpiration = new Guid("{e04f61f2-a03d-4aec-8b0f-6e8511fe5adc}"); - } - - public static class DelegatedAuthResourceIds - { - public const string AreaName = "DelegatedAuth"; - public const string AreaId = "A0848FA1-3593-4AEC-949C-694C73F4C4CE"; - - public const string AuthorizationResource = "Authorizations"; - public static readonly Guid Authorization = new Guid("EFBF6E0C-1150-43FD-B869-7E2B04FC0D09"); - - public const string HostAuthorizationResource = "HostAuthorization"; - public static readonly Guid HostAuthorizeId = new Guid("{7372FDD9-238C-467C-B0F2-995F4BFE0D94}"); - - public const string RegistrationResource = "Registration"; - public static readonly Guid Registration = new Guid("{909CD090-3005-480D-A1B4-220B76CB0AFE}"); - - public const string RegistrationSecretResource = "RegistrationSecret"; - public static readonly Guid RegistrationSecret = new Guid("{F37E5023-DFBE-490E-9E40-7B7FB6B67887}"); - } - - public static class TokenResourceIds - { - public const string AreaName = "Token"; - public const string AreaId = "0AD75E84-88AE-4325-84B5-EBB30910283C"; - - public const string AccessTokenResource = "AccessTokens"; - public static readonly Guid AccessToken = new Guid("{94C2BCFB-BF10-4B41-AC01-738122D6B5E0}"); - - public const string SessionTokenResource = "SessionTokens"; - public static readonly Guid SessionToken = new Guid("{ADA996BC-8C18-4193-B20C-CD41B13F5B4D}"); - - public const string AadUserTokenResource = "AadUserTokens"; - public static readonly Guid AadUserToken = new Guid("{6A8B6E50-FDA9-4AC1-9536-678C28BE2F7D}"); - - public const string AadAppTokenResource = "AadAppTokens"; - public static readonly Guid AadAppToken = new Guid("{11B3E525-35D3-4373-8985-EA72887427DB}"); - - public const string AppSessionTokenResource = "AppSessionTokens"; - public static readonly Guid AppSessionToken = new Guid("{B743B207-6DC5-457B-B1DF-B9B63D640F0B}"); - - public const string AppTokenPairResource = "AppTokenPairs"; - public static readonly Guid AppTokenPair = new Guid("{9CE3C96A-34A2-41AF-807D-205DA73F227B}"); - } - - public static class PropertyCacheResourceIds - { - public const string AreaName = "Cache"; - public const string AreaId = "0B808CEB-EF49-4C5E-9483-600A4ECF1224"; - - public const string PropertyCacheResource = "Properties"; - public static readonly Guid PropertyCache = new Guid("{656342EB-AE7D-4FF2-802F-19C6E35B0FE6}"); - } -} - -namespace GitHub.Services.TokenAdmin.Client -{ - public static class TokenAdminResourceIds - { - public const string AreaName = "TokenAdmin"; - public const string AreaId = "af68438b-ed04-4407-9eb6-f1dbae3f922e"; - - public const string PersonalAccessTokensResource = "PersonalAccessTokens"; - public static readonly Guid PersonalAccessTokensLocationId = new Guid("{af68438b-ed04-4407-9eb6-f1dbae3f922e}"); - - public const string RevocationsResource = "Revocations"; - public static readonly Guid RevocationsLocationId = new Guid("{a9c08b2c-5466-4e22-8626-1ff304ffdf0f}"); - - public const string RevocationRulesResource = "RevocationRules"; - public static readonly Guid RevocationRulesLocationId = new Guid("{ee4afb16-e7ab-4ed8-9d4b-4ef3e78f97e4}"); - } -} - -namespace GitHub.Services.Tokens.TokenAdmin.Client -{ - public static class TokenAdministrationResourceIds - { - public const string TokenAreaName = "TokenAdministration"; - public const string TokenAreaId = "95935461-9E54-44BD-B9FB-04F4DD05D640"; - - public const string TokenPersonalAccessTokensResource = "TokenPersonalAccessTokens"; - public static readonly Guid TokenPersonalAccessTokensLocationId = new Guid("{1BB7DB14-87C5-4762-BF77-A70AD34A9AB3}"); - - public const string TokenRevocationsResource = "TokenRevocations"; - public static readonly Guid TokenRevocationsLocationId = new Guid("{A2E4520B-1CC8-4526-871E-F3A8F865F221}"); - - public const string TokenListGlobalIdentities = "TokenListGlobalIdentities"; - public static readonly Guid TokenListGlobalIdentitiesId = new Guid("{30D3A12B-66C3-4669-B016-ECB0706C8D0F}"); - } -} - -namespace GitHub.Services.Identity.Client -{ - public static class PropertyCacheResourceIds - { - public const string AreaName = "Cache"; - public const string AreaId = "0B808CEB-EF49-4C5E-9483-600A4ECF1224"; - - public const string PropertyCacheResource = "Properties"; - public static readonly Guid PropertyCache = new Guid("{656342EB-AE7D-4FF2-802F-19C6E35B0FE6}"); - } -} - -namespace GitHub.Services.Security -{ - public static class LocationResourceIds - { - public const string SecurityBackingStoreArea = "SBS"; - - public const string SecurityBackingStoreNamespaceResource = "SBSNamespace"; - public static readonly Guid SecurityBackingStoreNamespace = new Guid("049929B0-79E1-4AD5-A548-9E192D5C049E"); - - public const string SecurityBackingStoreAclStoreResource = "SBSAclStore"; - public static readonly Guid SecurityBackingStoreAclStore = new Guid("D9DA18E4-274B-4DD4-B09D-B8B931AF3826"); - - public const string SecurityBackingStoreAclsResource = "SBSAcls"; - public static readonly Guid SecurityBackingStoreAcls = new Guid("3F95720D-2EF6-47CC-B5D7-733561D13EB9"); - - public const string SecurityBackingStoreAcesResource = "SBSAces"; - public static readonly Guid SecurityBackingStoreAces = new Guid("AB821A2B-F383-4C72-8274-8425ED30835D"); - - public const string SecurityBackingStoreInheritResource = "SBSInherit"; - public static readonly Guid SecurityBackingStoreInherit = new Guid("25DCFFD2-9F2A-4109-B4CC-000F8472107D"); - - public const string SecurityBackingStoreTokensResource = "SBSTokens"; - public static readonly Guid SecurityBackingStoreTokens = new Guid("466ECEAD-D7F1-447C-8BC1-52C22592B98E"); - - public const string SecurityServiceArea = "Security"; - - public const string SecurityPermissionsResource = "Permissions"; - public static readonly Guid SecurityPermissions = new Guid("DD3B8BD6-C7FC-4CBD-929A-933D9C011C9D"); - - public const string SecurityPermissionEvaluationBatchResource = "PermissionEvaluationBatch"; - public static readonly Guid SecurityPermissionEvaluationBatch = new Guid("CF1FAA59-1B63-4448-BF04-13D981A46F5D"); - - public const string SecurityAccessControlEntriesResource = "AccessControlEntries"; - public static readonly Guid SecurityAccessControlEntries = new Guid("AC08C8FF-4323-4B08-AF90-BCD018D380CE"); - - public const string SecurityAccessControlListsResource = "AccessControlLists"; - public static readonly Guid SecurityAccessControlLists = new Guid("18A2AD18-7571-46AE-BEC7-0C7DA1495885"); - - public const string SecurityNamespacesResource = "SecurityNamespaces"; - public static readonly Guid SecurityNamespaces = new Guid("CE7B9F95-FDE9-4BE8-A86D-83B366F0B87A"); - } -} - -namespace GitHub.Services.Account -{ - public static class AccountResourceIds - { - public const string RegionArea = "Region"; - - public const string AreaId = "0D55247A-1C47-4462-9B1F-5E2125590EE6"; - - public const string AccountServiceArea = "Account"; - public static readonly Guid Account = new Guid("{229A6A53-B428-4FFB-A835-E8F36B5B4B1E}"); - public const string AccountResource = "Accounts"; - - public static readonly Guid AccountUserId = new Guid("{DFA3B963-C8BB-4CAF-BCAC-5C066B3B5793}"); - public const string AccountUserResource = "Users"; - - public const string HostMappingsResource = "HostMappings"; - public static readonly Guid HostsLocationid = new Guid("{DC2B7A91-2350-487B-9192-8099F28D6576}"); - - public static readonly Guid AccountTenantId = new Guid("{C58B3989-1E17-4A18-9925-67186FE66833}"); - public const string AccountTenantResource = "Tenant"; - - public static readonly Guid AccountRegionLocationId = new Guid("642A93C7-8385-4D63-A5A5-20D044FE504F"); - public const string AccountRegionResource = "Regions"; - - public static readonly Guid AccountNameAvailabilityid = new Guid("65DD1DC5-53FE-4C67-9B4E-0EC3E2539998"); - public const string AccountNameAvailabilityResource = "Availability"; - - public static readonly Guid AccountSettingsid = new Guid("4E012DD4-F8E1-485D-9BB3-C50D83C5B71B"); - public const string AccountSettingsResource = "Settings"; - } -} - -namespace GitHub.Services.ClientNotification -{ - public static class ClientNotificationResourceIds - { - public const string AreaId = "C2845FF0-342A-4059-A831-AA7A5BF00FF0"; - public const string AreaName = "ClientNotification"; - - public const string SubscriptionsResource = "Subscriptions"; - public static readonly Guid SubscriptionsLocationid = new Guid("E037C69C-5AD1-4B26-B340-51C18035516F"); - - public const string NotificationsResource = "Notifications"; - public static readonly Guid NotificationsLocationid = new Guid("7F325780-EAD9-4C90-ACD1-2ECF621CE348"); - } -} - -namespace GitHub.Services.Licensing -{ - public static class LicensingResourceIds - { - public const string AreaId = "C73A23A1-59BB-458C-8CE3-02C83215E015"; - public const string AreaName = "Licensing"; - - public const string CertificateResource = "Certificate"; - public static readonly Guid CertificateLocationid = new Guid("2E0DBCE7-A327-4BC0-A291-056139393F6D"); - - public const string ClientRightsResource = "ClientRights"; - public static readonly Guid ClientRightsLocationid = new Guid("643C72DA-EAEE-4163-9F07-D748EF5C2A0C"); - - public const string MsdnResource = "Msdn"; - public const string MsdnPresenceLocationIdString = "69522C3F-EECC-48D0-B333-F69FFB8FA6CC"; - public static readonly Guid MsdnPresenceLocationId = new Guid(MsdnPresenceLocationIdString); - public const string MsdnEntitlementsLocationIdString = "1cc6137e-12d5-4d44-a4f2-765006c9e85d"; - public static readonly Guid MsdnEntitlementsLocationId = new Guid(MsdnEntitlementsLocationIdString); - - public const string ExtensionRightsResource = "ExtensionRights"; - public static readonly Guid ExtensionRightsLocationId = new Guid("5F1DBE21-F748-47C7-B5FD-3770C8BC2C08"); - - public const string ExtensionLicenseResource = "ExtensionRegistration"; - public static readonly Guid ExtensionLicenseLocationId = new Guid("004A420A-7BEF-4B7F-8A50-22975D2067CC"); - - public const string UsageRightsResource = "UsageRights"; - public static readonly Guid UsageRightsLocationid = new Guid("D09AC573-58FE-4948-AF97-793DB40A7E16"); - - public const string ServiceRightsResource = "ServiceRights"; - public static readonly Guid ServiceRightsLocationid = new Guid("78ED2F48-D449-412D-8772-E4E97317B7BE"); - - public const string UsageResource = "Usage"; - public static readonly Guid UsageLocationid = new Guid("D3266B87-D395-4E91-97A5-0215B81A0B7D"); - - public const string EntitlementsResource = "Entitlements"; - public const string EntitlementsBatchResource = "EntitlementsBatch"; - public const string ExtensionsAssignedToAccountResource = "AccountAssignedExtensions"; - public const string ExtensionsAssignedToAccountLocationIdString = "01BCE8D3-C130-480F-A332-474AE3F6662E"; - public static readonly Guid ExtensionsAssignedToAccountLocationId = new Guid(ExtensionsAssignedToAccountLocationIdString); - - public const string EntitlementsLocationIdString = "EA37BE6F-8CD7-48DD-983D-2B72D6E3DA0F"; - public static readonly Guid EntitlementsLocationid = new Guid(EntitlementsLocationIdString); - public const string UserEntitlementsLocationIdString = "6490E566-B299-49A7-A4E4-28749752581F"; - public static readonly Guid UserEntitlementsLocationId = new Guid(UserEntitlementsLocationIdString); - - public const string UserEntitlementsBatchLocationIdString = "CC3A0130-78AD-4A00-B1CA-49BEF42F4656"; - public static readonly Guid UserEntitlementsBatchLocationId = new Guid(UserEntitlementsBatchLocationIdString); - - public const string CurrentUserEntitlementsLocationIdString = "C01E9FD5-0D8C-4D5E-9A68-734BD8DA6A38"; - public static readonly Guid CurrentUserEntitlementsLocationId = new Guid(CurrentUserEntitlementsLocationIdString); - public const string AssignAvailableEntitlementsLocationIdString = "C01E9FD5-0D8C-4D5E-9A68-734BD8DA6A38"; - public static readonly Guid AssignAvailableEntitlementsLocationId = new Guid(AssignAvailableEntitlementsLocationIdString); - - public const string ExtensionEntitlementsResource = "ExtensionEntitlements"; - public const string UserExtensionEntitlementsLocationIdString = "8CEC75EA-044F-4245-AB0D-A82DAFCC85EA"; - public static readonly Guid UserExtensionEntitlementsLocationId = new Guid(UserExtensionEntitlementsLocationIdString); - public const string ExtensionEntitlementsLocationIdString = "5434F182-7F32-4135-8326-9340D887C08A"; - public static readonly Guid ExtensionEntitlementsLocationId = new Guid(ExtensionEntitlementsLocationIdString); - - public const string TransferIdentitiesExtensionsResource = "TransferIdentitiesExtensions"; - public const string TransferIdentitiesExtensionsLocationIdString = "DA46FE26-DBB6-41D9-9D6B-86BF47E4E444"; - public static readonly Guid TransferIdentitiesExtensionsLocationId = - new Guid(TransferIdentitiesExtensionsLocationIdString); - - public const string ExtensionEntitlementsBatchResource = "ExtensionEntitlementsBatch"; - public const string UsersBatchExtensionEntitlementsLocationIdString = "1D42DDC2-3E7D-4DAA-A0EB-E12C1DBD7C72"; - public static readonly Guid UsersBatchExtensionEntitlementsLocationId = new Guid(UsersBatchExtensionEntitlementsLocationIdString); - - public const string LicensingRightsResource = "LicensingRights"; - public const string LicensingRightsLocationIdString = "8671B016-FA74-4C88-B693-83BBB88C2264"; - public static readonly Guid LicensingRightsLocationId = new Guid(LicensingRightsLocationIdString); - - public const string LicensingSettingsResource = "Settings"; - public const string LicensingSettingsLocationIdString = "6BA7740F-A387-4D74-B71A-969A9F2B49FB"; - public static readonly Guid LicensingSettingsLocationId = new Guid(LicensingSettingsLocationIdString); - } - - public static class LicensingResourceVersions - { - public const int AccountRightsResourcePreviewVersion = 1; - public const int CertificateResourcePreviewVersion = 1; - public const int ClientRightsResourcePreviewVersion = 1; - public const int UsageRightsResourcePreviewVersion = 1; - public const int ServiceRightsResourceRtmVersion = 1; - public const int AccountUsageResourceRtmVersion = 1; - public const int EntitlementResourceRtmVersion = 1; - public const int EntitlementsBatchResourcePreviewVersion = 1; - public const int LicensingRightsResourceRtmVersion = 1; - public const int MsdnResourceRtmVersion = 1; - public const int ExtensionRightsResourceRtmVersion = 1; - public const int ExtensionLicenseResourceRtmVersion = 1; - public const int ExtensionEntitlementsResourceRtmVersion = 1; - public const int ExtensionEntitlementsBatchResourceRtmVersion = 1; - public const int ExtensionEntitlementsBatch2ResourceRtmVersion = 2; - public const int TransferExtensionsForIdentitiesRtmVersion = 1; - public const int LicensingSettingsResourceRtmVersion = 1; - } -} - -namespace GitHub.Services.GroupLicensingRule -{ - public static class LicensingRuleResourceIds - { - public const string AreaId = "4F9A6C65-A750-4DE3-96D3-E4BCCF3A39B0"; - public const string AreaName = "LicensingRule"; - - public static class GroupLicensingRules - { - public const string GroupLicensingRulesResourceName = "GroupLicensingRules"; - public const string GroupLicensingRuleLocationIdString = "1DAE9AF4-C85D-411B-B0C1-A46AFAEA1986"; - public static readonly Guid GroupLicensingRuleLocationId = new Guid(GroupLicensingRuleLocationIdString); - } - - public static class GroupLicensingRulesLookup - { - public const string GroupLicensingRulesLookupResourceName = "GroupLicensingRulesLookup"; - public const string GroupLicensingRulesLookupResourceLocationIdString = "6282B958-792B-4F26-B5C8-6D035E02289F"; - public static readonly Guid GroupLicensingRulesLookupResourceLocationId = new Guid(GroupLicensingRulesLookupResourceLocationIdString); - } - - public static class GroupLicensingRulesUserApplication - { - public const string GroupLicensingRulesUserApplicationResourceName = "GroupLicensingRulesUserApplication"; - public const string GroupLicensingRulesUserApplicationResourceLocationIdString = "74A9DE62-9AFC-4A60-A6D9-F7C65E028619"; - public static readonly Guid GroupLicensingRulesUserApplicationResourceLocationId = new Guid(GroupLicensingRulesUserApplicationResourceLocationIdString); - } - - public static class GroupLicensingRulesApplication - { - public const string GroupLicensingRulesApplicationResourceName = "GroupLicensingRulesApplication"; - public const string GroupLicensingRulesApplicationResourceLocationIdString = "14602853-288e-4711-a613-c3f27ffce285"; - public static readonly Guid GroupLicensingRulesApplicationResourceLocationId = new Guid(GroupLicensingRulesApplicationResourceLocationIdString); - } - public static class GroupLicensingRulesApplicationStatus - { - public const string GroupLicensingRulesApplicationStatusResourceName = "GroupLicensingRulesApplicationStatus"; - public const string GroupLicensingRulesApplicationStatusResourceLocationIdString = "8953c613-d07f-43d3-a7bd-e9b66f960839"; - public static readonly Guid GroupLicensingRulesApplicationStatusResourceLocationId = new Guid(GroupLicensingRulesApplicationStatusResourceLocationIdString); - } - - public static class GroupLicensingRulesEvaluationLog - { - public const string GroupLicensingRulesEvaluationLogResourceName = "GroupLicensingRulesEvaluationLog"; - public const string GroupLicensingRulesEvaluationLogResourceLocationIdString = "C3C87024-5143-4631-94CE-CB2338B04BBC"; - public static readonly Guid GroupLicensingRulesEvaluationLogResourceLocationId = new Guid(GroupLicensingRulesEvaluationLogResourceLocationIdString); - } - } - - public static class GroupLicensingResourceVersions - { - public const int GroupLicensingRulesResourceVersion = 1; - public const int GroupLicensingRulesLookupResourceVersion = 1; - } -} - -namespace GitHub.Services.Invitation -{ - public static class InvitationResourceVersions - { - public const int InvitationAPIVersion = 1; - } - - public static class InvitationResourceIds - { - public const string AreaId = "287A6D53-7DC8-4618-8D57-6945B848A4AD"; - public const string AreaName = "Invitation"; - - public const string InvitationsResourceName = "Invitations"; - public const string InvitationsLocationIdString = "BC7CA053-E204-435B-A143-6240BA8A93BF"; - public static readonly Guid InvitationsLocationId = new Guid(InvitationsLocationIdString); - } -} - -namespace GitHub.Services.Compliance -{ - public static class ComplianceResourceVersions - { - public const int AccountRightsResourceVersion = 1; - public const int ConfigurationResourceVersion = 1; - public const int ValidationResourceVersion = 1; - } - - public static class ComplianceResourceIds - { - public const string AreaId = "7E7BAADD-B7D6-46A0-9CE5-A6F95DDA0E62"; - public const string AreaName = "Compliance"; - - public const string AccountRightsResource = "AccountRights"; - public static readonly Guid AccountRightsLocationId = new Guid("5FCEC4F4-491A-473D-B2F9-205977E66F01"); - - public const string ConfigurationResource = "Configuration"; - public static readonly Guid ConfigurationLocationId = new Guid("64076419-AC67-4F85-B709-B8C28D5B4F1D"); - - public const string ValidationResource = "Validation"; - public static readonly Guid ValidationLocationId = new Guid("A9994840-76C7-4C5B-97CF-2B353AD0E01C"); - } -} - -namespace GitHub.Services.Profile -{ - public static class ProfileResourceIds - { - public const string AreaId = "8CCFEF3D-2B87-4E99-8CCB-66E343D2DAA8"; - public const string AreaName = "Profile"; - public static readonly Guid AreaIdGuid = new Guid(AreaId); - - public const string ProfileHttpClientV2AreaId = "31C4AD39-B95A-4AC2-87FE-D8CE878D32A8"; - - public const string ProfileResource = "Profiles"; - public static readonly Guid ProfileLocationid = new Guid("F83735DC-483F-4238-A291-D45F6080A9AF"); - - public const string UserDefaultsResource = "UserDefaults"; - public static readonly Guid UserDefaultsLocationId = new Guid("B583A356-1DA7-4237-9F4C-1DEB2EDBC7E8"); - - public const string AttributeResource = "Attributes"; - public static readonly Guid AttributeLocationid = new Guid("EF743E8C-9A94-4E55-9392-CCFE55CFAE55"); - public static readonly Guid AttributeLocationId2 = new Guid("1392B6AC-D511-492E-AF5B-2263E5545A5D"); - - public const string AvatarResource = "Avatar"; - public static readonly Guid AvatarLocationid = new Guid("855C48A5-ED0C-4762-A640-3D212B2244B8"); - public static readonly Guid Avatar2LocationId = new Guid("67436615-B382-462A-B659-5367A492FB3C"); - - public const string DisplayNameResource = "DisplayName"; - public static readonly Guid DisplayNameLocationid = new Guid("5D969C0D-9A4A-45AB-A4EA-0C902AF8D39C"); - - public const string PublicAliasResource = "PublicAlias"; - public static readonly Guid PublicAliasLocationid = new Guid("B63E58B3-B830-40EA-A382-C198E6E9BB2C"); - - public const string EmailAddressResource = "EmailAddress"; - public static readonly Guid EmailAddressLocationid = new Guid("F47E1E09-08B3-436F-A541-495B3088635A"); - - public const string CountryResource = "Country"; - public static readonly Guid CountryLocationid = new Guid("C96428D6-5805-48A4-B4FD-DC6F1C39BE92"); - - public const string TermsOfServiceResource = "TermsOfService"; - public static readonly Guid TermsOfServiceLocationid = new Guid("E3411396-DA5F-4757-AA9E-521B48EEF625"); - - public const string PreferredEmailConfirmationResource = "PreferredEmailConfirmation"; - public static readonly Guid PreferredEmailConfirmationLocationid = new Guid("238437E4-73B9-4BB9-B467-DE4E5DC0FC78"); - - public const string CountriesResource = "Countries"; - public static readonly Guid CountriesLocationid = new Guid("775F46ED-26B3-4A6F-B7B1-01CF195ACDD0"); - - public const string SupportedLcidsResource = "SupportedLcids"; - public static readonly Guid SupportedLcidsLocationId = new Guid("D5BD1AA6-C269-4BCD-AD32-75FA17475584"); - - public const string RegionsResource = "Regions"; - public static readonly Guid RegionsLocationId = new Guid("92D8D1C9-26B8-4774-A929-D640A73DA524"); - - public const string LocationsResource = "Locations"; - public static readonly Guid LocationsLocationid = new Guid("EEA7DE6F-00A4-42F3-8A29-1BA615691880"); - - public const string LatestTosResource = "LatestTermsofService"; - public static readonly Guid LatestTosLocationid = new Guid("A4A9FB9D-FD32-4F9A-95A8-4B05FAF8C661"); - - public const string SettingsResource = "Settings"; - public static readonly Guid SettingsLocationid = new Guid("5081DFF5-947B-4CE6-9BBE-6C7C094DDCE0"); - - public const string GeoRegionResource = "GeoRegion"; - public static readonly Guid GeoRegionLocationid = new Guid("3BCDA9C0-3078-48A5-A1E0-83BD05931AD0"); - - public const string MigratingProfilesResource = "MigratingProfiles"; - public static readonly Guid MigratingProfilesLocationid = new Guid("397E8E6D-00BB-405F-90F4-02B38B2AC8F6"); - } - - public static class ProfileResourceVersions - { - public const int GenericResourcePreviewVersion = 1; - - public const int ProfileResourcePreviewVersion = 1; - public const int ProfileResourceRcVersion = 2; - public const int ProfileResourceRtmVersion = 3; - - public const int AttributeResourcePreviewVersion = 1; - public const int AttributeResourceRcVersion = 2; - } -} - -namespace GitHub.Services.FileContainer -{ - public static class FileContainerResourceIds - { - public const string FileContainerServiceArea = "Container"; - public const string FileContainerIdString = "E4F5C81E-E250-447B-9FEF-BD48471BEA5E"; - public const string BrowseFileContainerIdString = "E71A64AC-B2B5-4230-A4C0-DAD657CF97E2"; - - public static readonly Guid FileContainer = new Guid(FileContainerIdString); - public static readonly Guid BrowseFileContainer = new Guid(BrowseFileContainerIdString); - - public const string FileContainerResource = "Containers"; - } -} - -namespace GitHub.Services.WebApi -{ - public static class CvsFileDownloadResourceIds - { - public const string AreaName = "CvsFileDownload"; - - public const string LocationIdString = "0CF03C5A-D16D-4297-BFEB-F38A56D86670"; - public static readonly Guid LocationId = new Guid(LocationIdString); - - public const string Resource = "CvsFileDownload"; - } -} - -namespace GitHub.Services.Commerce -{ - public static class CommerceResourceIds - { - public const string AreaId = "365D9DCD-4492-4AE3-B5BA-AD0FF4AB74B3"; - public const string AreaName = "Commerce"; - - public const string MeterResource = "Meters"; - public static readonly Guid MeterLocationid = new Guid("AFB09D56-7740-4EB0-867F-792021FAB7C9"); - - public const string CommercePackageResource = "CommercePackage"; - public static readonly Guid CommercePackageLocationId = new Guid("E8135F49-A1DC-4135-80F4-120BBFC2ACF0"); - - public const string UsageEventResource = "UsageEvents"; - public static readonly Guid UsageEventLocationid = new Guid("EED7D28A-12A9-47ED-9A85-91A76C63E74B"); - - public const string ReportingEventResource = "ReportingEvents"; - public static readonly Guid ReportingEventLocationId = new Guid("E3296A33-647F-4A09-85C6-64B9259DADB8"); - - public const string SubscriptionResource = "Subscription"; - public static readonly Guid SubscriptionLocationId = new Guid("64485509-D692-4B70-B440-D02B3B809820"); - - public const string RegionsResource = "Regions"; - public static readonly Guid RegionsLocationId = new Guid("9527c79d-9f3e-465d-8178-069106c39457"); - - public const string OfferSubscriptionResource = "OfferSubscription"; - public static readonly Guid OfferSubscriptionResourceId = new Guid("E8950CE5-80BC-421F-B093-033C18FD3D79"); - - public const string OfferMeterResource = "OfferMeter"; - public static readonly Guid OfferMeterLocationId = new Guid("8B79E1FB-777B-4D0A-9D2E-6A4B2B8761B9"); - - public const string OfferMeterPriceResource = "OfferMeterPrice"; - public static readonly Guid OfferMeterPriceLocationId = new Guid("1C67C343-2269-4608-BC53-FE62DAA8E32B"); - - public const string ConnectedServerResource = "ConnectedServer"; - public static readonly Guid ConnectedServerLocationId = new Guid("C9928A7A-8102-4061-BDCE-B090068C0D2B"); - - public const string PurchaseRequestResource = "PurchaseRequest"; - public static readonly Guid PurchaseRequestLocationId = new Guid("A349B796-BDDB-459E-8921-E1967672BE86"); - - public const string ResourceMigrationResource = "ResourceMigration"; - public static readonly Guid ResourceMigrationLocationId = new Guid("2F11E604-83B2-4596-B3C6-242BAB102DA3"); - - public const string CommerceHostHelperResource = "CommerceHostHelperResource"; - public static readonly Guid CommerceHostHelperLocationId = new Guid("8B4C702A-7449-4FEB-9B23-ADD4288DDA1A"); - } - - public static class CommerceResourceVersions - { - public const int MeterV1Resources = 1; - - public const int MeterV2Resources = 2; - - public const int BillingV1Resources = 1; - - public const int OfferMeterV1Resources = 1; - - public const int OfferMeterPriceV1Resources = 1; - - public const int CommercePackageV1Resources = 1; - - public const int ReportingV1Resources = 1; - - public const int PurchaseRequestV1Resources = 1; - - public const int ResourceMigrationV1Resources = 1; - - public const int InfrastructureOrganizationV1Resources = 1; - } - - public static class CsmResourceIds - { - public const string AreaId = "B3705FD5-DC18-47FC-BB2F-7B0F19A70822"; - public const string AreaName = "Csm"; - - public const string ExtensionResourceResource = "ExtensionResource"; - public static readonly Guid ExtensionResourceLocationId = new Guid("9cb405cb-4a72-4a50-ab6d-be1da1726c33"); - - public const string ExtensionResourceGroupResource = "ExtensionResourceGroup"; - public static readonly Guid ExtensionResourceGroupLocationId = new Guid("a509d9a8-d23f-4e0f-a69f-ad52b248943b"); - - public const string AccountResourceResource = "AccountResource"; - public static readonly Guid AccountResourceResourceLocationId = new Guid("5745408e-6e9e-49c7-92bf-62932c8df69d"); - - public const string AccountResourceGroupResource = "AccountResourceGroup"; - public static readonly Guid AccountResourceGroupLocationId = new Guid("73d8b171-a2a0-4ac6-ba0b-ef762098e5ec"); - - public const string SubscriptionResourceGroupResource = "SubscriptionResourceGroup"; - public static readonly Guid SubscriptionResourceGroupLocationId = new Guid("f34be62f-f215-4bda-8b57-9e8a7a5fd66a"); - - public const string AccountResourceOperationsResource = "AccountResourceOperations"; - public static readonly Guid AccountResourceOperationsLocationId = new Guid("454d976b-812e-4947-bc4e-c2c23160317e"); - - public const string NameAvailabilityResource = "NameAvailability"; - public static readonly Guid NameAvailabilityResourceLocationId = new Guid("031d6b9b-a0d4-4b46-97c5-9ddaca1aa5cd"); - - public const string SubscriptionEventsResource = "SubscriptionEvents"; - public static readonly Guid SubscriptionEventsLocationId = new Guid("97bc4c4d-ce2e-4ca3-87cc-2bd07aeee500"); - - public const string ResourceGroupsResourceName = "ResourceGroups"; - public static readonly Guid ResourceGroupsResourceLocationId = new Guid("9e0fa51b-9d61-4899-a5a1-e1f0f5e75bc0"); - } - - public static class CommerceServiceResourceIds - { - // Offer Meter Area - public const string OfferMeterAreaId = "000080C1-AA68-4FCE-BBC5-C68D94BFF8BE"; - public const string OfferMeterAreaName = "OfferMeter"; - - public const string OfferMeterLocationString = "81E37548-A9E0-49F9-8905-650A7260A440"; - public static readonly Guid OfferMeterLocationId = new Guid(OfferMeterLocationString); - public const string OfferMeterResource = "OfferMeter"; - - public const string OfferMeterPriceResource = "OfferMeterPrice"; - public const string OfferMeterPriceLocationString = "D7197E00-DDDF-4029-9F9B-21B935A6CF9F"; - public static readonly Guid OfferMeterPriceLocationId = new Guid(OfferMeterPriceLocationString); - - // Meters Area - public const string MeterAreaId = "4C19F9C8-67BD-4C18-800B-55DC62C3017F"; - public const string MetersAreaName = "Meters"; - - public const string MeterResource = "Meters"; - public const string MeterLocationString = "4BD6E06B-1EDF-41A6-9BAF-D15B874DC539"; - public static readonly Guid MeterLocationid = new Guid(MeterLocationString); - - // Commerce Package Area - public const string CommercePackageAreaName = "Package"; - public const string CommercePackageAreaId = "45FB9450-A28D-476D-9B0F-FB4AEDDDFF73"; - - public const string CommercePackageResource = "CommercePackage"; - public const string CommercePackageLocationString = "A5E80D85-9718-44E0-BBED-461109268DBC"; - public static readonly Guid CommercePackageLocationId = new Guid(CommercePackageLocationString); - - // Usage Events Area - public const string UsageEventsAreaName = "UsageEvents"; - public const string UsageEventsAreaId = "3B16A4DB-B853-4C64-AA16-72138F5BB750"; - - public const string UsageEventsResource = "UsageEvents"; - public const string UsageEventsLocationString = "78741F74-E4F0-41B2-BB93-28C886443027"; - public static readonly Guid UsageEventLocationid = new Guid(UsageEventsLocationString); - - // Reporting Event Area - public const string ReportingEventsAreaName = "ReportingEvents"; - public const string ReportingEventsAreaId = "C890B7C4-5CF6-4280-91AC-331E439B8119"; - - public const string ReportingEventsResource = "ReportingEvents"; - public const string ReportingEventsLocationString = "D0BA838F-9253-46C5-ABB2-0ACF551C23D7"; - public static readonly Guid ReportingEventsLocationId = new Guid(ReportingEventsLocationString); - - // Subscription Area - public const string SubscriptionAreaId = "AC02550F-721A-4913-8EA5-CADAE535B03F"; - public const string SubscriptionAreaName = "Subscription"; - - public const string SubscriptionResource = "Subscription"; - public const string SubscriptionLocationString = "94DE86A2-03E3-42DB-A2E8-1A82BF13A262"; - public static readonly Guid SubscriptionLocationId = new Guid(SubscriptionLocationString); - - public const string AccountDetailsResource = "AccountDetails"; - public const string AccountDetailsLocationString = "0288F4E6-21D3-4529-AC5F-1719F99A4396"; - public static readonly Guid AccountDetailsLocationId = new Guid(AccountDetailsLocationString); - - // Region Area - public const string RegionsAreaName = "Regions"; - public const string RegionsAreaId = "A6ACEE79-C91A-47BA-87DF-AF36581833B6"; - - public const string RegionsResource = "Regions"; - public const string RegionsLocationString = "AAE8A531-9968-456F-9EF1-FE0ECF4724E8"; - public static readonly Guid RegionsLocationId = new Guid(RegionsLocationString); - - // Offer Subscription Area - public const string OfferSubscriptionAreaName = "OfferSubscription"; - public const string OfferSubscriptionAreaId = "5D4A2F52-5A08-41FB-8CCA-768ADD070E18"; - - public const string OfferSubscriptionResource = "OfferSubscription"; - public const string OfferSubscriptionLocationString = "7C13D166-01C5-4CCD-8A75-E5AD6AB3B0A6"; - public static readonly Guid OfferSubscriptionResourceId = new Guid(OfferSubscriptionLocationString); - - // Connected Server Area - public const string ConnectedServerAreaName = "ConnectedServer"; - public const string ConnectedServerAreaId = "05A2B228-317C-4886-9FE9-828F9EA3815A"; - - public const string ConnectedServerResource = "ConnectedServer"; - public const string ConnectedServerLocationString = "AB6E0E2F-A3CA-4478-BAFC-8E7AD022BE01"; - public static readonly Guid ConnectedServerLocationId = new Guid(ConnectedServerLocationString); - - // Purchase Request Area - public const string PurchaseRequestAreaName = "PurchaseRequest"; - public const string PurchaseRequestAreaId = "9D439667-F8CF-4991-89A9-95CA6A763327"; - - public const string PurchaseRequestResource = "PurchaseRequest"; - public const string PurchaseRequestLocationString = "6F905B2D-292A-4D30-B38A-2D254EAB06B7"; - public static readonly Guid PurchaseRequestLocationId = new Guid(PurchaseRequestLocationString); - - // Resource Migration Area - public const string ResourceMigrationAreaName = "ResourceMigration"; - public const string ResourceMigrationAreaId = "FFCFC36A-0BE8-412A-A2BB-93C2ABD4048B"; - - public const string ResourceMigrationResource = "ResourceMigration"; - public const string ResourceMigrationLocationString = "00432895-B3F6-488C-BA71-792FA5E07383"; - public static readonly Guid ResourceMigrationLocationId = new Guid(ResourceMigrationLocationString); - } - - public static class CsmResourceProviderResourceIds - { - public const string AreaId = "2900E97E-7BBD-4D87-95EE-BE54611B6184"; - public const string AreaName = "CsmResourceProvider"; - - public const string ExtensionResourceResource = "VssExtensionResource"; - public static readonly Guid ExtensionResourceLocationId = new Guid("8DF1CB68-197E-4BAF-8CE2-C96021879971"); - - public const string ExtensionResourceGroupResource = "VssExtensionResourceGroup"; - public static readonly Guid ExtensionResourceGroupLocationId = new Guid("E14787AB-FBD5-4064-A75D-0603C9ED66A8"); - - public const string AccountResourceResource = "VssAccountResource"; - public static readonly Guid AccountResourceResourceLocationId = new Guid("58FA3A85-AF20-408D-B46D-6D369408E3DA"); - - public const string AccountResourceGroupResource = "VssAccountResourceGroup"; - public static readonly Guid AccountResourceGroupLocationId = new Guid("955956A7-FBEB-48E6-9D78-C60F3F84BAE9"); - - public const string SubscriptionResourceGroupResource = "VssSubscriptionResourceGroup"; - public static readonly Guid SubscriptionResourceGroupLocationId = new Guid("8A066194-3817-4E76-9BBC-2A1446FA0FC5"); - - public const string AccountResourceOperationsResource = "VssAccountResourceOperations"; - public static readonly Guid AccountResourceOperationsLocationId = new Guid("14917175-ECBE-453B-B436-50430219EBA9"); - - public const string NameAvailabilityResource = "VssNameAvailability"; - public static readonly Guid NameAvailabilityResourceLocationId = new Guid("7DBAE6E1-993E-4AC9-B20D-6A39EEE4028B"); - - public const string SubscriptionEventsResource = "VssSubscriptionEvents"; - public static readonly Guid SubscriptionEventsLocationId = new Guid("A7F5BE2F-9AF8-4CC2-863F-D07377B2C079"); - - public const string ResourceGroupsResource = "VssResourceGroups"; - public static readonly Guid ResourceGroupsResourceLocationId = new Guid("8D9245EE-19A2-45B2-BE3E-03234122298E"); - } -} - -namespace GitHub.Services.Health -{ - public static class HealthResourceIds - { - public const string HealthArea = "Health"; - public const string HealthResource = "Health"; - public static readonly Guid HealthLocationId = new Guid("30964BA7-2A11-4792-B7BA-DF191DBCC3BB"); - } -} - -namespace GitHub.Services.ActivityStatistic -{ - public static class ActivityStatisticIds - { - public const string ActivityStatisticArea = "Stats"; - public const string ActivityStatisticResource = "Activities"; - public static readonly Guid ActivityStatisticId = new Guid("5F4C431A-4D8F-442D-96E7-1E7522E6EABD"); - } -} - -namespace GitHub.Services.ContentSecurityPolicy -{ - public static class ContentSecurityPolicyResourceIds - { - public const string CspReportArea = "CspReport"; - public const string CspReportResource = "CspReport"; - public static readonly Guid CspLocationId = new Guid("FA48A6B6-C4A9-42B4-AFE7-2640F68F99B6"); - } -} - -namespace GitHub.Services.Location -{ - [GenerateAllConstants] - public static class LocationResourceIds - { - public const string LocationServiceArea = "Location"; - - public const string ConnectionDataResource = "ConnectionData"; - public static readonly Guid ConnectionData = new Guid("{00D9565F-ED9C-4A06-9A50-00E7896CCAB4}"); - - public const string ServiceDefinitionsResource = "ServiceDefinitions"; - public static readonly Guid ServiceDefinitions = new Guid("{D810A47D-F4F4-4A62-A03F-FA1860585C4C}"); - - public const string AccessMappingsResource = "AccessMappings"; - public static readonly Guid AccessMappings = new Guid("{A52F2F69-B171-4E88-9DFE-34B44CF7E386}"); - - public const string ResourceAreasResource = "ResourceAreas"; - public static readonly Guid ResourceAreas = new Guid("E81700F7-3BE2-46DE-8624-2EB35882FCAA"); - - // Used for updating the SPS locations in account migrations. - public const string SpsServiceDefintionResource = "SpsServiceDefinition"; - - public static readonly Guid SpsServiceDefinition = new Guid("{DF5F298A-4E06-4815-A13E-6CE90A37EFA4}"); - } -} - -namespace GitHub.Services.Notification -{ - public static class PersistedNotificationResourceIds - { - public const string AreaId = "BA8495F8-E9EE-4A9E-9CBE-142897543FE9"; - public const string AreaName = "PersistedNotification"; - - public static readonly Guid NotificationsId = new Guid("E889FFCE-9F0A-4C6C-B749-7FB1ECFA6950"); - public const string NotificationsResource = "Notifications"; - - public static readonly Guid RecipientMetadataId = new Guid("1AAFF2D2-E2F9-4784-9F93-412A9F2EFD86"); - public const string RecipientMetadataResource = "RecipientMetadata"; - } - - public static class PersistedNotificationResourceVersions - { - public const int NotificationsResourcePreviewVersion = 1; - public const int RecipientMetadataPreviewVersion = 1; - } -} - -namespace GitHub.Services.Operations -{ - [GenerateAllConstants] - public static class OperationsResourceIds - { - public const string AreaName = "operations"; - public const string OperationsResource = "operations"; - public const string OperationsRouteName = "Operations"; - public const string OperationsPluginRouteName = "OperationsPlugin"; - public const string OperationsApi = "OperationsApi"; - public const string TagOperationsLocationId = "9A1B74B4-2CA8-4A9F-8470-C2F2E6FDC949"; - public static readonly Guid OperationsLocationId = new Guid(TagOperationsLocationId); - public const string TagOperationsPluginLocationId = "7F82DF6D-7D09-46C1-A015-643B556B3A1E"; - public static readonly Guid OperationsPluginLocationId = new Guid(TagOperationsPluginLocationId); - } -} - -namespace GitHub.Services.Directories.DirectoryService -{ - public static class DirectoryResourceIds - { - public const string DirectoryServiceArea = "Directory"; - public const string DirectoryService = "2B98ABE4-FAE0-4B7F-8562-7141C309B9EE"; - - public const string MembersResource = "Members"; - public static readonly Guid Members = Guid.Parse("{89526A2C-E9E3-1F40-A3FB-54D16BDA15B0}"); - public static readonly Guid MemberStatusLocationId = Guid.Parse("{714914b2-ad3f-4933-bf2e-fc3cabb37696}"); - } -} - -namespace GitHub.Services.FeatureAvailability -{ - [GenerateAllConstants] - public static class FeatureAvailabilityResourceIds - { - public const string AreaId = "C8E5AF97-4B95-4E73-9E7F-69A06507967C"; - public const string FeatureAvailabilityAreaName = "FeatureAvailability"; - public static readonly Guid FeatureFlagsLocationId = Guid.Parse("{3E2B80F8-9E6F-441E-8393-005610692D9C}"); - } -} - -namespace GitHub.Services.IdentityPicker -{ - //Common identity picker in the framework - [GenerateAllConstants] - public static class CommonIdentityPickerResourceIds - { - public const string ServiceArea = "IdentityPicker"; - - public const string IdentitiesResource = "Identities"; - - public static readonly Guid IdentitiesLocationId = new Guid("4102F006-0B23-4B26-BB1B-B661605E6B33"); - public static readonly Guid IdentityAvatarLocationId = new Guid("4D9B6936-E96A-4A42-8C3B-81E8337CD010"); - public static readonly Guid IdentityFeatureMruLocationId = new Guid("839E4258-F559-421B-A38E-B6E691967AB3"); - public static readonly Guid IdentityConnectionsLocationId = new Guid("C01AF8FD-2A61-4811-A7A3-B85BCEC080AF"); - } -} - -namespace GitHub.Services.Settings -{ - [GenerateAllConstants] - public static class SettingsApiResourceIds - { - public const string SettingsAreaName = "Settings"; - - public const string SettingEntriesResource = "Entries"; - public const string SettingEntriesLocationIdString = "CD006711-163D-4CD4-A597-B05BAD2556FF"; - public static readonly Guid SettingEntriesLocationId = new Guid(SettingEntriesLocationIdString); - public const string NamedScopeSettingEntriesLocationIdString = "4CBAAFAF-E8AF-4570-98D1-79EE99C56327"; - public static readonly Guid NamedScopeSettingEntriesLocationId = new Guid(NamedScopeSettingEntriesLocationIdString); - } -} - -namespace GitHub.Services.WebPlatform -{ - [GenerateAllConstants] - public static class AuthenticationResourceIds - { - public const string AreaId = "A084B81B-0F23-4136-BAEA-98E07F3C7446"; - public const string AuthenticationAreaName = "WebPlatformAuth"; - public static readonly Guid AuthenticationLocationId = Guid.Parse("{11420B6B-3324-490A-848D-B8AAFDB906BA}"); - public const string SessionTokenResource = "SessionToken"; - } - - [GenerateAllConstants] - public static class CustomerIntelligenceResourceIds - { - public const string AreaId = "40132BEE-F5F3-4F39-847F-80CC44AD9ADD"; - public const string CustomerIntelligenceAreaName = "CustomerIntelligence"; - public static readonly Guid EventsLocationId = Guid.Parse("{B5CC35C2-FF2B-491D-A085-24B6E9F396FD}"); - } - - public static class ContributionResourceIds - { - public const string AreaId = "39675476-C858-48A1-A5CD-80ED65E86532"; - public const string AreaName = "Contribution"; - public const string HierarchyLocationIdString = "8EC9F10C-AB9F-4618-8817-48F3125DDE6A"; - public static readonly Guid HierarchyLocationId = Guid.Parse(HierarchyLocationIdString); - public const string HierarchyResource = "Hierarchy"; - public const string HierarchyQueryLocationIdString = "3353E165-A11E-43AA-9D88-14F2BB09B6D9"; - public static readonly Guid HierarchyQueryLocationId = Guid.Parse(HierarchyQueryLocationIdString); - public const string HierarchyQueryResource = "HierarchyQuery"; - } - - [GenerateAllConstants] - public static class ClientTraceResourceIds - { - public const string AreaId = "054EEB0E-108E-47DC-848A-7074B14774A9"; - public const string ClientTraceAreaName = "ClientTrace"; - public static readonly Guid EventsLocationId = Guid.Parse("{06BCC74A-1491-4EB8-A0EB-704778F9D041}"); - public const string ClientTraceEventsResource = "Events"; - } -} - -namespace GitHub.Services.Zeus -{ - [GenerateAllConstants] - public static class BlobCopyLocationIds - { - public const string ResourceString = "{8907fe1c-346a-455b-9ab9-dde883687231}"; - public static readonly Guid ResourceId = new Guid(ResourceString); - public const string ResouceName = "BlobCopyRequest"; - public const string AreaName = "BlobCopyRequest"; - } - - [GenerateAllConstants] - public static class DatabaseMigrationLocationIds - { - public const string ResourceString = "{D56223DF-8CCD-45C9-89B4-EDDF69240000}"; - public static readonly Guid ResourceId = new Guid(ResourceString); - public const string ResouceName = "DatabaseMigration"; - public const string AreaName = "DatabaseMigration"; - } -} - -namespace GitHub.Services.Identity.Mru -{ - [GenerateAllConstants] - public static class IdentityMruResourceIds - { - public const string AreaId = "FC3682BE-3D6C-427A-87C8-E527B16A1D05"; - public const string AreaName = "Identity"; - - public static readonly Guid MruIdentitiesLocationId = new Guid("15D952A1-BB4E-436C-88CA-CFE1E9FF3331"); - public const string MruIdentitiesResource = "MruIdentities"; - } -} - -namespace GitHub.Services.Servicing -{ - public static class ServicingResourceIds - { - public const string AreaName = "Servicing"; - - public static readonly Guid JobsLocationId = new Guid("807F536E-0C6D-46D9-B856-4D5F3C27BEF5"); - public static readonly Guid LogsLocationId = new Guid("B46254F3-9523-4EF8-B69E-FD6EED5D0BB8"); - public static readonly Guid ServiceLevelLocationId = new Guid("3C4BFE05-AEB6-45F8-93A6-929468401657"); - - public const string JobsResourceName = "Jobs"; - public const string LogsResourceName = "Logs"; - public const string ServiceLevelResource = "ServiceLevel"; - } -} - -namespace GitHub.Services.Auditing -{ - public static class AuditingResourceIds - { - public const string AreaName = "Auditing"; - - public static readonly Guid EndpointsLocationId = new Guid("D4AB3CD0-66BE-4551-844E-CC2C32FA64C5"); - public const string EndpointResourceName = "Endpoints"; - } -} - -namespace GitHub.Services.ServicePrincipal -{ - public static class ServicePrincipalResourceIds - { - public const string AreaName = "ServicePrincipal"; - public const string ServicePrincipalsResourceName = "ServicePrincipals"; - public static readonly Guid ServicePrincipalsLocationId = new Guid("992CB93B-847E-4683-88C9-848CD450FDF6"); - } -} - -namespace GitHub.Services.TokenSigningKeyLifecycle -{ - public static class TokenSigningKeyLifecycleResourceIds - { - public const string AreaName = "TokenSigning"; - public const string AreaId = "{f189ca86-04a2-413c-81a0-abdbd7c472da}"; - - public const string SigningKeysResourceName = "SigningKeys"; - public static readonly Guid SigningKeysLocationId = new Guid("62361140-9bb7-4d57-8223-12e6155ce354"); - - public const string NamespaceResourceName = "SigningNamespace"; - public static readonly Guid NamespaceLocationId = new Guid("29f94429-6088-4394-afd9-0435df55f079"); - } -} - -namespace GitHub.Services.GitHubConnector -{ - public static class GitHubConnectorResourceIds - { - public const string AreaId = "85738938-9FAE-4EB4-B4F0-871502E6B549"; - public const string AreaName = "GitHubConnector"; - - public static readonly Guid ResourceAreaId = new Guid(AreaId); - - public static readonly Guid ConnectionsResourceLocationId = new Guid("EBE1CF27-8F19-4955-A47B-09F125F06518"); - public const string ConnectionsResourceName = "Connections"; - - public static readonly Guid InstallationTokensResourceLocationId = new Guid("05188D9F-DD80-4C9E-BA91-4B0B3A8A67D7"); - public const string InstallationTokensResourceName = "InstallationTokens"; - - public static readonly Guid WebhookEventsResourceLocationId = new Guid("063EC204-5C0D-402F-86CF-36B1703E187F"); - public const string WebhookEventsResourceName = "WebhookEvents"; - - public static readonly Guid UserOAuthUrlsResourceLocationId = new Guid("9EA35039-A91F-4E02-A81D-573623FF7235"); - public const string UserOAuthUrlsResourceName = "UserOAuthUrls"; - - public const string DefaultResourceId = "default"; - } -} - -namespace GitHub.Services.Organization -{ - public static class OrganizationResourceIds - { - public const string AreaId = "0D55247A-1C47-4462-9B1F-5E2125590EE6"; - - public static readonly Guid ResourceAreaId = new Guid(AreaId); - - public const string OrganizationArea = "Organization"; - - public const string PropertiesResourceName = "Properties"; - - public const string LogoResourceName = "Logo"; - - // organization resources - public static readonly Guid OrganizationsResourceLocationId = new Guid("95F49097-6CDC-4AFE-A039-48B4D4C4CBF7"); - - public const string OrganizationsResourceName = "Organizations"; - - // organization properties resources - public static readonly Guid OrganizationPropertiesResourceLocationId = new Guid("103707C6-236D-4434-A0A2-9031FBB65FA6"); - - public const string OrganizationPropertiesResourceName = "OrganizationProperties"; - - // organization logo resources - public static readonly Guid OrganizationLogoResourceLocationId = new Guid("A9EEEC19-85B4-40AE-8A52-B4F697260AC4"); - - public const string OrganizationLogoResourceName = "OrganizationLogo"; - - // organization migration blobs resources - public static readonly Guid OrganizationMigrationBlobsResourceLocationId = new Guid("93F69239-28BA-497E-B4D4-33E51E6303C3"); - - public const string OrganizationMigrationBlobsResourceName = "OrganizationMigrationBlobs"; - - // collection resources - public static readonly Guid CollectionsResourceLocationId = new Guid("668B5607-0DB2-49BB-83F8-5F46F1094250"); - - public const string CollectionsResourceName = "Collections"; - - // collection properties resources - public static readonly Guid CollectionPropertiesResourceLocationId = new Guid("A0F9C508-A3C4-456B-A812-3FB0C4743521"); - - public const string CollectionPropertiesResourceName = "CollectionProperties"; - - // region resources - public static readonly Guid RegionsResourceLocationId = new Guid("6F84936F-1801-46F6-94FA-1817545D366D"); - - public const string RegionsResourceName = "Regions"; - } - - public static class OrganizationPolicyResourceIds - { - public const string OrganizationPolicyArea = "OrganizationPolicy"; - - // policy - public static readonly Guid PoliciesLocationId = new Guid("D0AB077B-1B97-4F78-984C-CFE2D248FC79"); - - public const string PoliciesResourceName = "Policies"; - - // policies batch - public static readonly Guid PoliciesBatchLocationId = new Guid("7EF423E0-59D8-4C00-B951-7143B18BD97B"); - - public const string PoliciesBatchResourceName = "PoliciesBatch"; - - // policy metadata - public static readonly Guid PolicyInformationLocationId = new Guid("222AF71B-7280-4A95-80E4-DCB0DEEAC834"); - - public const string PolicyInformationResourceName = "PolicyInformation"; - } -} - -namespace GitHub.Services.UserMapping -{ - public static class UserMappingResourceIds - { - public const string AreaId = "C8C8FFD0-2ECF-484A-B7E8-A226955EE7C8"; - public const string UserMappingArea = "UserMapping"; - - public static readonly Guid UserAccountMappingsResourceLocationId = new Guid("0DBF02CC-5EC3-4250-A145-5BEB580E0086"); - public const string UserAccountMappingsResourceName = "UserAccountMappings"; - } -} - -namespace GitHub.Services.TokenRevocation -{ - public static class TokenRevocationResourceIds - { - public const string AreaName = "TokenRevocation"; - public const string AreaId = "{3C25A612-6355-4A43-80FE-75AEBE07E981}"; - - public const string RulesResourceName = "Rules"; - public static readonly Guid RulesLocationId = new Guid("03923358-D412-40BA-A63F-36A1836C7706"); - } -} - -namespace GitHub.Services.MarketingPreferences -{ - public static class MarketingPreferencesResourceIds - { - public const string AreaId = "F4AA2205-FF00-4EEE-8216-C7A73CEE155C"; - public const string AreaName = "MarketingPreferences"; - - public const string ContactWithOffersResource = "ContactWithOffers"; - public static readonly Guid ContactWithOffersLocationid = new Guid("6E529270-1F14-4E92-A11D-B496BBBA4ED7"); - - public const string MarketingPreferencesResource = "MarketingPreferences"; - public static readonly Guid MarketingPreferencesLocationId = new Guid("0e2ebf6e-1b6c-423d-b207-06b1afdfe332"); - } - - public static class MarketingPreferencesResourceVersions - { - public const int GenericResourcePreviewVersion = 1; - } -} - -namespace GitHub.Services.HostAcquisition -{ - public static class HostAcquisitionResourceIds - { - public const string AreaName = "HostAcquisition"; - public const string AreaId = "8E128563-B59C-4A70-964C-A3BD7412183D"; - - public static readonly Guid ResourceAreaId = new Guid(AreaId); - - public const string HostAcquisitionArea = "HostAcquisition"; - - // collection resources - public static readonly Guid CollectionsResourceLocationId = new Guid("2BBEAD06-CA34-4DD7-9FE2-148735723A0A"); - - public const string CollectionsResourceName = "Collections"; - - // NameAvailability resources - public static readonly Guid NameAvailabilityResourceLocationId = new Guid("01A4CDA4-66D1-4F35-918A-212111EDC9A4"); - - public const string NameAvailabilityResourceName = "NameAvailability"; - - // region resources - public static readonly Guid RegionsResourceLocationId = new Guid("776EF918-0DAD-4EB1-A614-04988CA3A072"); - - public const string RegionsResourceName = "Regions"; - } -} - -namespace GitHub.Services.OAuthWhitelist -{ - public static class OAuthWhitelistResourceIds - { - public const string AreaId = "BED1E9DD-AE97-4D73-9E01-4797F66ED0D3"; - public const string AreaName = "OAuthWhitelist"; - - public const string OAuthWhitelistEntriesResource = "OAuthWhitelistEntries"; - public static readonly Guid OAuthWhitelistEntriesLocationId = new Guid("3AFD5B3F-12B1-4551-B6D7-B33E0E2D45D6"); - } -} - -namespace GitHub.Services.CentralizedFeature -{ - public class CentralizedFeatureResourceIds - { - public const string AreaName = "CentralizedFeature"; - public const string AreaId = "86BF2186-3092-4F5E-86A6-13997CE0924A"; - public static readonly Guid AreaIdGuid = new Guid(AreaId); - - public class Availability - { - public static readonly Guid LocationId = new Guid("EB8B51A6-1BE5-4337-B4C1-BAE7BCB587C2"); - public const string Resource = "Availability"; - } - } -} - -namespace GitHub.Services.AzureFrontDoor -{ - public static class AfdResourceIds - { - public const string AreaName = "AzureFrontDoor"; - - public const string AfdEndpointLookupResource = "AfdEndpointLookup"; - public static readonly Guid EndpointLookupLocationId = new Guid("39738637-F7C6-439A-82D7-83EFAA3A7DB4"); - } -} - -namespace GitHub.Services.WebApi -{ - public static class BasicAuthBatchResourceIds - { - public const string AreaName = "BasicAuthBatch"; - public const string AreaId = "31D56A90-A194-4567-AACF-EFE0007E3309"; - - public const string BasicAuthBatchResource = "BasicAuthBatch"; - public static readonly Guid BasicAuthBatch = new Guid("{8214680a-5c4a-4333-9b3c-228030c136f6}"); - } -} - -namespace GitHub.Services.PermissionLevel -{ - public static class PermissionLevelDefinitionResourceIds - { - public const string AreaName = "PermissionLevel"; - public const string AreaId = "E97D4D3C-C339-4745-A987-BD6F6C496788"; - - public static readonly Guid ResourceAreaId = new Guid(AreaId); - - public static readonly Guid PermissionLevelDefinitionsResourceLocationId = new Guid("D9247EA2-4E01-47C1-8662-980818AAE5D3"); - - public const string PermissionLevelDefinitionsResourceName = "PermissionLevelDefinitions"; - } - - public static class PermissionLevelAssignmentResourceIds - { - public const string AreaName = "PermissionLevel"; - public const string AreaId = "E97D4D3C-C339-4745-A987-BD6F6C496788"; - - public static readonly Guid ResourceAreaId = new Guid(AreaId); - public static readonly Guid PermissionLevelAssignmentsResourceLocationId = new Guid("005E0302-7988-4066-9AC0-1D93A42A9F0B"); - - public const string PermissionLevelAssignmentsResourceName = "PermissionLevelAssignments"; - } -} diff --git a/src/Sdk/WebApi/WebApi/ServiceEvent.cs b/src/Sdk/WebApi/WebApi/ServiceEvent.cs deleted file mode 100644 index b1813c1a6..000000000 --- a/src/Sdk/WebApi/WebApi/ServiceEvent.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - // This is the event that shall be published on the service bus by different services for other first party services. - [DataContract] - public class ServiceEvent - { - private Object m_resource; - - /// - /// This is the id of the type. - /// Constants that will be used by subscribers to identify/filter events being published on a topic. - /// - [DataMember] - public String EventType { get; set; } - - /// - /// This is the service that published this event. - /// - [DataMember] - public Publisher Publisher { get; set; } - - /// - /// The resource object that carries specific information about the event. The object must have - /// the ServiceEventObject applied for serialization/deserialization to work. - /// - [DataMember] - public Object Resource - { - get - { - return m_resource; - } - set - { - Type type = value.GetType(); - if (!type.GetTypeInfo().GetCustomAttributes(true).Any()) - { - throw new InvalidOperationException($"Resource of type {type.FullName} must have ServiceEventObject attribute"); - } - m_resource = value; - } - } - - /// - /// This is the version of the resource. - /// - [DataMember] - public String ResourceVersion { get; set; } - - /// - /// This dictionary carries the context descriptors along with their ids. - /// - [DataMember] - public Dictionary ResourceContainers { get; set; } - } - - [DataContract] - public class Publisher - { - /// - /// Name of the publishing service. - /// - [DataMember] - public String Name { get; set; } - - /// - /// Service Owner Guid - /// Eg. Tfs : 00025394-6065-48CA-87D9-7F5672854EF7 - /// - [DataMember] - public Guid ServiceOwnerId { get; set; } - } - - public class ResourceContainerTypes - { - public const String Account = "Account"; - public const String Collection = "Collection"; - } - - [System.AttributeUsage(System.AttributeTargets.Class, Inherited = true)] - public class ServiceEventObjectAttribute : Attribute - { - public ServiceEventObjectAttribute() { } - } -} diff --git a/src/Sdk/WebApi/WebApi/TaskExtensions.cs b/src/Sdk/WebApi/WebApi/TaskExtensions.cs deleted file mode 100644 index 01cef55a5..000000000 --- a/src/Sdk/WebApi/WebApi/TaskExtensions.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.ComponentModel; -using System.Net.Http; -using System.Threading.Tasks; - -namespace GitHub.Services.WebApi -{ - //This class should be used by callers of derivatives of HttpClientBase to deal with - //getting a proper exception from a task, when you want to get a synchronous result - [EditorBrowsable(EditorBrowsableState.Never)] - public static class TaskExtensions - { - /// - /// Blocks until the task has completed, throwing the remote exception if one was raised. - /// - /// The task to await - [AsyncFixer.BlockCaller] - public static void SyncResult(this Task task) - { - // NOTE: GetResult() on TaskAwaiter uses ExceptionDispatchInfo.Throw if there - // is an exception, which preserves the original call stack and does not use - // AggregateException (unless explicitly thrown by the caller). - task.GetAwaiter().GetResult(); - } - - /// - /// Blocks until the task has completed, returning the result or throwing the remote exception if one was raised. - /// - /// The type for the result - /// The task to await - /// The result of the task - [AsyncFixer.BlockCaller] - public static T SyncResult(this Task task) - { - // NOTE: GetResult() on TaskAwaiter uses ExceptionDispatchInfo.Throw if there - // is an exception, which preserves the original call stack and does not use - // AggregateException (unless explicitly thrown by the caller). - return task.GetAwaiter().GetResult(); - } - - /// - /// Blocks until the task has completed, returning the result or throwing the remote exception if one was raised. - /// - /// The task to await - /// The result of the task - [AsyncFixer.BlockCaller] - public static HttpResponseMessage SyncResult(this Task task) - { - // NOTE: This is effectively the same as , - // but currently remains to support binary compatibility. - - // NOTE: GetResult() on TaskAwaiter uses ExceptionDispatchInfo.Throw if there - // is an exception, which preserves the original call stack and does not use - // AggregateException (unless explicitly thrown by the caller). - return task.GetAwaiter().GetResult(); - } - } -} - -namespace AsyncFixer -{ - [System.AttributeUsage(System.AttributeTargets.Method)] - public class BlockCaller : System.Attribute - { } -} - diff --git a/src/Sdk/WebApi/WebApi/Utilities/AsyncLock.cs b/src/Sdk/WebApi/WebApi/Utilities/AsyncLock.cs deleted file mode 100644 index 2b5bd9d60..000000000 --- a/src/Sdk/WebApi/WebApi/Utilities/AsyncLock.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace GitHub.Services.WebApi.Utilities -{ - /// - /// From: http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266988.aspx - /// - internal sealed class AsyncLock - { - public AsyncLock() - { - m_releaser = Task.FromResult((IDisposable)new Releaser(this)); - } - - public Task LockAsync(CancellationToken cancellationToken = default(CancellationToken)) - { - // Don't pass cancellationToken to the semaphore. If we can't acquire the semaphore immediately - // we'll still get the waitTask returned immediately (with IsCompleted = false) - // and then we'll end up in the else block where we add a continuation to the waitTask which will honor the cancellationToken - Task waitTask = m_semaphore.WaitAsync(); - - if (waitTask.IsCompleted) - { - return m_releaser; - } - else - { - return waitTask.ContinueWith( - (task, state) => (IDisposable)state, - m_releaser.Result, - cancellationToken, - TaskContinuationOptions.ExecuteSynchronously, - TaskScheduler.Default); - } - } - - private readonly SemaphoreSlim m_semaphore = new SemaphoreSlim(1, 1); - private readonly Task m_releaser; - - private sealed class Releaser : IDisposable - { - internal Releaser(AsyncLock toRelease) - { - m_toRelease = toRelease; - } - - public void Dispose() - { - m_toRelease.m_semaphore.Release(); - } - - private readonly AsyncLock m_toRelease; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Utilities/BaseSecuredObject.cs b/src/Sdk/WebApi/WebApi/Utilities/BaseSecuredObject.cs deleted file mode 100644 index c36135f48..000000000 --- a/src/Sdk/WebApi/WebApi/Utilities/BaseSecuredObject.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - [DataContract] - public abstract class BaseSecuredObject : ISecuredObject - { - protected BaseSecuredObject() - { - } - - protected BaseSecuredObject(ISecuredObject securedObject) - { - if (securedObject != null) - { - this.m_namespaceId = securedObject.NamespaceId; - this.m_requiredPermissions = securedObject.RequiredPermissions; - this.m_token = securedObject.GetToken(); - } - } - - Guid ISecuredObject.NamespaceId - { - get - { - return m_namespaceId; - } - } - - int ISecuredObject.RequiredPermissions - { - get - { - return m_requiredPermissions; - } - } - - string ISecuredObject.GetToken() - { - return m_token; - } - - internal Guid m_namespaceId; - internal int m_requiredPermissions; - internal string m_token; - } -} diff --git a/src/Sdk/WebApi/WebApi/Utilities/ClientGeneratorAttributes.cs b/src/Sdk/WebApi/WebApi/Utilities/ClientGeneratorAttributes.cs deleted file mode 100644 index 134a9e5e0..000000000 --- a/src/Sdk/WebApi/WebApi/Utilities/ClientGeneratorAttributes.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; - -namespace GitHub.Services.WebApi.Internal -{ - /// - /// GenClient (SwaggerGenerator) will ignore controller methods, parameters, and classes that have this attribute. - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Class | AttributeTargets.Enum, AllowMultiple = false)] - public sealed class ClientIgnoreAttribute : Attribute - { - public ClientIgnoreAttribute() - { - } - } - - /// - /// When a method or class has this attribute, we will only generate client methods for the specified languages. - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false)] - public sealed class ClientIncludeAttribute : Attribute - { - /// - /// - /// - /// A list of languages to generate methods for. - public ClientIncludeAttribute(RestClientLanguages languages) - { - Languages = languages; - } - - public RestClientLanguages Languages { get; private set; } - } - - [Flags] - public enum RestClientLanguages - { - All = ~0, - CSharp = 1, - Java = 2, - TypeScript = 4, - Nodejs = 8, - [Obsolete("DocMD has been replaced by Swagger generated REST Documentation.")] - DocMD = 16, - Swagger2 = 32, - Python = 64, - TypeScriptWebPlatform = 128 - } - - /// - /// Suppresses the default constant enum generation behavior in typescriptwebplatform clientgen. When using this attribute, and affected code generation will product a .ts file instead of a .d.ts file (non-constant enumerations should not be generated into .d.ts files). - /// - [AttributeUsage(AttributeTargets.Enum)] - public class ClientDontGenerateTypeScriptEnumAsConst : Attribute - { - public ClientDontGenerateTypeScriptEnumAsConst() - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/Utilities/ISecuredObject.cs b/src/Sdk/WebApi/WebApi/Utilities/ISecuredObject.cs deleted file mode 100644 index 977542d61..000000000 --- a/src/Sdk/WebApi/WebApi/Utilities/ISecuredObject.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.ComponentModel; - -namespace GitHub.Services.WebApi -{ - /// - /// Any responses from public APIs must implement this interface. It is used to enforce that - /// the data being returned has been security checked. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public interface ISecuredObject - { - /// - /// The id of the namespace which secures this resource. - /// - Guid NamespaceId - { - get; - } - - /// - /// The security bit to demand. - /// - Int32 RequiredPermissions - { - get; - } - - /// - /// The token to secure this resource. - /// - String GetToken(); - } - - /// - /// Containers of ISecuredObjects should implement this interface. If you implement this interface, all - /// serializable properties must be of type ISecuredObject or IEnumerable of ISecuredObject. This will - /// be enforced using a roslyn analyzer. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public interface ISecuredObjectContainer { } -} diff --git a/src/Sdk/WebApi/WebApi/Utilities/UserAgentUtility.cs b/src/Sdk/WebApi/WebApi/Utilities/UserAgentUtility.cs deleted file mode 100644 index b5fbec3d6..000000000 --- a/src/Sdk/WebApi/WebApi/Utilities/UserAgentUtility.cs +++ /dev/null @@ -1,217 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Net.Http.Headers; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using GitHub.Services.Common; -using GitHub.Services.Common.Internal; -using Microsoft.Win32; - -namespace GitHub.Services.WebApi.Utilities.Internal -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public static class UserAgentUtility - { - private static Lazy> s_defaultRestUserAgent - = new Lazy>(ConstructDefaultRestUserAgent); - - public static List GetDefaultRestUserAgent() - { - return s_defaultRestUserAgent.Value; - } - - private static List ConstructDefaultRestUserAgent() - { -#if !NETSTANDARD - // Get just the exe file name without the path. - String exe; - try - { - exe = Path.GetFileName(NativeMethods.GetModuleFileName()); - } - catch (Exception e) - { - Trace.WriteLine("DefaultUserAgent: Unable to get exe. " + e.ToString()); - - // We weren't allowed to get the exe file name, so we go on. - exe = "unavailable"; - } - - Tuple skuInfo = null; - if (String.Equals(exe, "devenv.exe", StringComparison.OrdinalIgnoreCase)) - { - skuInfo = GetCurrentSkuInfo(); - } - - String app = String.Empty; - if (AppDomain.CurrentDomain != null) - { - app = (String)AppDomain.CurrentDomain.GetData(AdminConstants.ApplicationName); - } - - if (!String.IsNullOrEmpty(app)) - { - exe = String.Concat(exe, "[", app, "]"); - } -#endif - // Pick up the assembly version from this dll - String fileVersion = "unavailable"; - try - { - AssemblyFileVersionAttribute attr = typeof(UserAgentUtility).GetTypeInfo().Assembly.GetCustomAttribute(); - if (attr != null) - { - fileVersion = attr.Version; - } - } - catch (Exception e) - { - Trace.WriteLine("DefaultUserAgent: Unable to get fileVersion: " + e.ToString()); - } - - -#if !NETSTANDARD - - Debug.Assert(fileVersion.StartsWith("16", StringComparison.OrdinalIgnoreCase), - "The SKU numbers here are only meant to work with Dev16. For later versions the SKU numbers mapped in the GetSkuNumber method need to be updated."); - StringBuilder builder = new StringBuilder(); - builder.Append("("); - builder.Append(exe); - if (skuInfo != null) - { - builder.Append(", "); - builder.Append(skuInfo.Item1); - builder.Append(", SKU:"); - builder.Append(skuInfo.Item2.ToString(CultureInfo.InvariantCulture)); - } - builder.Append(")"); - - String commentValue = builder.ToString(); -#else - String commentValue = string.Format("(NetStandard; {0})", RuntimeInformation.OSDescription.Replace('(', '[').Replace(')', ']').Trim()); -#endif - return new List { - new ProductInfoHeaderValue("VSServices", fileVersion), - new ProductInfoHeaderValue(commentValue) }; - } - - -#if !NETSTANDARD - private static Lazy s_defaultSoapUserAgent = new Lazy(ConstructDefaultSoapUserAgent); - - public static String GetDefaultSoapUserAgent() - { - return s_defaultSoapUserAgent.Value; - } - - private static string ConstructDefaultSoapUserAgent() - { - // Get just the exe file name without the path. - String exe; - try - { - exe = Path.GetFileName(NativeMethods.GetModuleFileName()); - } - catch (Exception e) - { - Trace.WriteLine("DefaultUserAgent: Unable to get exe: " + e.ToString()); - - // We weren't allowed to get the exe file name, so we go on. - exe = "unavailable"; - } - - Tuple skuInfo = null; - if (String.Equals(exe, "devenv.exe", StringComparison.OrdinalIgnoreCase)) - { - skuInfo = GetCurrentSkuInfo(); - } - - String app = String.Empty; - if (AppDomain.CurrentDomain != null) - { - app = (String)AppDomain.CurrentDomain.GetData("ApplicationName"); - } - - if (!String.IsNullOrEmpty(app)) - { - exe = String.Concat(exe, "[", app, "]"); - } - - // Pick up the assembly version from the current dll. - String fileVersion = String.Empty; - try - { - Object[] attrs = typeof(UserAgentUtility).Assembly.GetCustomAttributes(false); - foreach (Object attr in attrs) - { - if (attr is AssemblyFileVersionAttribute) - { - fileVersion = ((AssemblyFileVersionAttribute)attr).Version; - break; - } - } - } - catch (Exception e) - { - Trace.WriteLine("DefaultUserAgent: Unable to get fileVersion: " + e.ToString()); - - // We weren't allowed to get the version info, so we go on. - fileVersion = "unavailable"; - } - - StringBuilder userAgent = new StringBuilder(); - userAgent.Append("Team Foundation ("); - userAgent.Append(exe); - userAgent.Append(", "); - userAgent.Append(fileVersion); - if (skuInfo != null) - { - userAgent.Append(", "); - userAgent.Append(skuInfo.Item1); - userAgent.Append(", SKU:"); - userAgent.Append(skuInfo.Item2.ToString(CultureInfo.InvariantCulture)); - } - userAgent.Append(")"); - return userAgent.ToString(); - } - - - private static Tuple GetCurrentSkuInfo() - { - string vsSkuEdition = Environment.GetEnvironmentVariable("VSSKUEDITION"); - if (!string.IsNullOrEmpty(vsSkuEdition)) - { - Tuple skuInfo; - if (s_dev16SkuToAgentStringMap.TryGetValue(vsSkuEdition, out skuInfo)) - { - return skuInfo; - } - else - { - Debug.Fail("Unrecognized value for VSSKUEDITION: '{0}'. This value needs to be added to the s_dev16SkuToAgentStringMap.", vsSkuEdition); - } - } - - return new Tuple(ClientSkuNames.Dev16.Other, ClientSkuNumbers.Dev16Other); - } - - /// - /// The key is the SKU name provided by VSSKUEDITION env variable. The value is a tuple. Item1 is a string for the SKU Name to put in the User Agent string, and Item2 is an int for the SkuCode. - /// - private static readonly Dictionary> s_dev16SkuToAgentStringMap = new Dictionary>(StringComparer.OrdinalIgnoreCase) - { - { "Enterprise", new Tuple(ClientSkuNames.Dev16.Enterprise, ClientSkuNumbers.Dev16Enterprise) }, - { "Professional", new Tuple(ClientSkuNames.Dev16.Pro, ClientSkuNumbers.Dev16Pro) }, - { "Community", new Tuple(ClientSkuNames.Dev16.Community, ClientSkuNumbers.Dev16Community) }, - { "V3|UNKNOWN", new Tuple(ClientSkuNames.Dev16.TE, ClientSkuNumbers.Dev16TeamExplorer) }, - { "V4|UNKNOWN", new Tuple(ClientSkuNames.Dev16.Sql, ClientSkuNumbers.Dev16Sql) }, // future release as of 4/25/2017. - { "IntShell", new Tuple(ClientSkuNames.Dev16.IntShell, ClientSkuNumbers.Dev16IntShell) } // future release as of 4/25/2017. This key may change. - }; -#endif - } -} diff --git a/src/Sdk/WebApi/WebApi/Utilities/XmlSerializableDataContractExtensions.cs b/src/Sdk/WebApi/WebApi/Utilities/XmlSerializableDataContractExtensions.cs deleted file mode 100644 index 06cea3ca9..000000000 --- a/src/Sdk/WebApi/WebApi/Utilities/XmlSerializableDataContractExtensions.cs +++ /dev/null @@ -1,355 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reflection; -using System.Runtime.Serialization; -using System.Xml; -using System.Xml.Serialization; -using GitHub.Services.Common; -using GitHub.Services.Graph.Client; - -namespace GitHub.Services.WebApi.Xml -{ - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, Inherited = true, AllowMultiple = false)] - public class XmlSerializableDataContractAttribute : Attribute - { - public XmlSerializableDataContractAttribute() { } - - public bool EnableCamelCaseNameCompat { get; set; } - } - - /// - /// These extensions are intended to be used alongside the interface - /// to allow classes to leverage some of the functionality of DataContractSerializer, - /// such as serialization of publicly immutable properties, while also supporting the conventional . - /// - public static class XmlSerializableDataContractExtensions - { - // This method has a class constraint because we can't use reflection to mutate the properties of a struct without boxing - public static void ReadDataMemberXml(this XmlReader reader, T destination) where T : class - { - ArgumentUtility.CheckForNull(reader, nameof(reader)); - - var isEmptyElement = reader.IsEmptyElement; - - reader.ReadStartElement(); - - if (isEmptyElement) - { - return; - } - - var serializableProperties = GetSerializableProperties(destination.GetType().GetTypeInfo()).MappedByName; - - while (reader.IsStartElement()) - { - if (!serializableProperties.TryGetValue(reader.LocalName, out var property)) - { - reader.ReadOuterXml(); - continue; - } - - isEmptyElement = reader.IsEmptyElement; - - object propertyValue; - - if (destination is GraphSubjectBase && property.SerializedName == nameof(GraphSubjectBase.Descriptor)) - { - var propertySerializer = GetSerializer(reader.NamespaceURI, reader.LocalName, typeof(SubjectDescriptor)); - propertyValue = propertySerializer.Deserialize(reader.ReadSubtree()).ToString(); - } - else - { - var propertySerializer = GetSerializer(reader.NamespaceURI, reader.LocalName, property.SerializedType); - propertyValue = propertySerializer.Deserialize(reader.ReadSubtree()); - } - - property.SetValue(destination, propertyValue); - - if (isEmptyElement) - { - reader.ReadOuterXml(); - } - else - { - reader.ReadEndElement(); - } - } - - reader.ReadEndElement(); - } - - public static void WriteDataMemberXml(this XmlWriter writer, object source) - { - ArgumentUtility.CheckForNull(writer, nameof(writer)); - - var type = source.GetType().GetTypeInfo(); - var shouldWriteNamespace = writer.Settings == null; - var rootNamespace = shouldWriteNamespace ? GetNamespace(type) : null; - var serializableProperties = GetSerializableProperties(type).EnumeratedInOrder; - foreach (var property in serializableProperties) - { - if (!property.ShouldSerialize(source)) - { - continue; - } - - var propertyValue = property.GetValue(source); - if (property.IsIgnorableDefaultValue(propertyValue)) - { - continue; - } - - var propertySerializer = GetSerializer(rootNamespace, property.SerializedName, property.SerializedType); - propertySerializer.Serialize(writer, propertyValue); - - if (!string.IsNullOrEmpty(property.SerializedNameForCamelCaseCompat)) - { - propertySerializer = GetSerializer(rootNamespace, property.SerializedNameForCamelCaseCompat, property.SerializedType); - propertySerializer.Serialize(writer, propertyValue); - } - } - } - - private static string GetNamespace(TypeInfo type) - { - if (!NamespacesByType.TryGetValue(type, out string outputNamespace)) - { - outputNamespace = $"http://schemas.datacontract.org/2004/07/{type.Namespace}"; - NamespacesByType.TryAdd(type, outputNamespace); - } - - return outputNamespace; - } - - private static SerializableProperties GetSerializableProperties(TypeInfo type) - { - if (SerializablePropertiesByType.TryGetValue(type, out var properties)) - { - return properties; - } - - var dataContract = type.GetCustomAttribute(typeof(XmlSerializableDataContractAttribute)) as XmlSerializableDataContractAttribute; - var enableCamelCaseNameCompat = dataContract == null ? false : dataContract.EnableCamelCaseNameCompat; - - var declaredProperties = new List(); - - foreach (var declaredProperty in type.DeclaredProperties) - { - if (declaredProperty.GetCustomAttribute(typeof(XmlIgnoreAttribute)) != null) - { - continue; - } - - if (declaredProperty.SetMethod == null) - { - continue; - } - - var dataMember = declaredProperty.GetCustomAttribute(typeof(DataMemberAttribute)) as DataMemberAttribute; - if (dataMember == null) - { - continue; - } - - var shouldSerializeMethodName = string.Concat("ShouldSerialize", declaredProperty.Name); - var shouldSerializeMethod = type.GetDeclaredMethod(shouldSerializeMethodName); - - declaredProperties.Add(new SerializableProperty(declaredProperty, dataMember, shouldSerializeMethod, enableCamelCaseNameCompat)); - } - - var inheritedProperties = Enumerable.Empty(); - if (type.BaseType != typeof(object)) - { - inheritedProperties = GetSerializableProperties(type.BaseType.GetTypeInfo()).EnumeratedInOrder; - } - - var serializableProperties = new SerializableProperties(declaredProperties, inheritedProperties); - - return SerializablePropertiesByType.GetOrAdd(type, serializableProperties); - } - - private static XmlSerializer GetSerializer(string rootNamespace, string elementName, Type elementType) - { - var serializerKey = new SerializerKey(rootNamespace, elementName, elementType); - return Serializers.GetOrAdd(serializerKey, _ => - { - var rootAttribute = new XmlRootAttribute(elementName) { Namespace = rootNamespace }; - return new XmlSerializer(elementType, rootAttribute); - }); - } - - private static ConcurrentDictionary SerializablePropertiesByType - = new ConcurrentDictionary(); - - private static ConcurrentDictionary NamespacesByType - = new ConcurrentDictionary(); - - private static ConcurrentDictionary Serializers - = new ConcurrentDictionary(); - - /// - /// Creates a HashSet based on the elements in , using transformation - /// function . - /// - private static HashSet ToHashSet( - this IEnumerable source, - Func selector) - { - return new HashSet(source.Select(selector)); - } - - private class SerializableProperties - { - public IReadOnlyDictionary MappedByName { get; } - - public IReadOnlyList EnumeratedInOrder { get; } - - public SerializableProperties(IEnumerable declaredProperties, IEnumerable inheritedProperties) - { - var declaredPropertyNames = declaredProperties.ToHashSet(property => property.SerializedName); - - // To maintain consistency with the DataContractSerializer, property ordering is determined according to the following rules: - // 1. If a data contract type is a part of an inheritance hierarchy, data members of its base types are always first in the order. - // 2. Next in order are the current type’s data members that do not have the Order property of the DataMemberAttribute attribute set, in alphabetical order. - // https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/data-member-order - EnumeratedInOrder = inheritedProperties - // Subclass properties should hide inherited properties with the same name - .Where(inheritedProperty => !declaredPropertyNames.Contains(inheritedProperty.SerializedName)) - .Concat(declaredProperties.OrderBy(property => property.SerializedName)) - .ToList(); - - var propertiesMappedByName = new Dictionary(); - foreach (var property in EnumeratedInOrder) - { - propertiesMappedByName.Add(property.SerializedName, property); - if (property.SerializedNameForCamelCaseCompat != null) - { - propertiesMappedByName.TryAdd(property.SerializedNameForCamelCaseCompat, property); - } - } - MappedByName = propertiesMappedByName; - } - - private Dictionary PropertiesDictionary { get; } - } - - [DebuggerDisplay("Name={SerializedName} Type={SerializedType}")] - private class SerializableProperty - { - public Type SerializedType => Property.PropertyType; - - public string SerializedName { get; } - - public string SerializedNameForCamelCaseCompat { get; } - - public SerializableProperty(PropertyInfo property, DataMemberAttribute dataMember, MethodInfo shouldSerializeMethod, bool enableCamelCaseNameCompat) - { - Property = property; - DataMember = dataMember; - ShouldSerializeMethod = shouldSerializeMethod; - - SerializedName = DataMember?.Name ?? Property.Name; - SerializedNameForCamelCaseCompat = ComputeSerializedNameForCameCaseCompat(enableCamelCaseNameCompat); - } - - public object GetValue(object @object) => Property.GetValue(@object); - - public void SetValue(object @object, object value) => Property.SetValue(@object, value); - - public bool ShouldSerialize(object @object) - => ShouldSerializeMethod == null ? true : (bool)ShouldSerializeMethod.Invoke(@object, new object[] { }); - - public bool IsIgnorableDefaultValue(object value) - { - if (DataMember.EmitDefaultValue) - { - return false; - } - - var serializedType = SerializedType; - if (serializedType.GetTypeInfo().IsValueType) - { - var defaultValue = DefaultValuesByType.GetOrAdd(serializedType, key => Activator.CreateInstance(key)); - return Equals(value, defaultValue); - } - - return value == null; - } - - private string ComputeSerializedNameForCameCaseCompat(bool enableCamelCaseNameCompat) - { - if (!enableCamelCaseNameCompat) - { - return null; - } - - var upperCamelCaseName = ConvertToUpperCamelCase(SerializedName); - - if (string.Equals(upperCamelCaseName, SerializedName)) - { - return null; - } - - return upperCamelCaseName; - } - - private static string ConvertToUpperCamelCase(string input) - { - return string.Concat(char.ToUpperInvariant(input[0]), input.Substring(1)); - } - - private PropertyInfo Property { get; } - private DataMemberAttribute DataMember { get; } - private MethodInfo ShouldSerializeMethod { get; } - private static ConcurrentDictionary DefaultValuesByType = new ConcurrentDictionary(); - } - - private struct SerializerKey - { - public string RootNamespace { get; } - - public string ElementName { get; } - - public Type ElementType { get; } - - public SerializerKey(string rootNamespace, string elementName, Type elementType) - { - // root namespace can be null, but element name and type must be nonnull - ArgumentUtility.CheckForNull(elementName, nameof(elementName)); - ArgumentUtility.CheckForNull(elementType, nameof(elementType)); - RootNamespace = rootNamespace; - ElementName = elementName; - ElementType = elementType; - } - - public override bool Equals(object other) - { - if (other is SerializerKey) - { - var otherKey = (SerializerKey)other; - return RootNamespace == otherKey.RootNamespace - && ElementName == otherKey.ElementName - && ElementType == otherKey.ElementType; - } - - return false; - } - - public override int GetHashCode() - { - int hashCode = 7443; // "large" prime to start the seed - - // Bitshifting and subtracting once is an efficient way to multiply by our second "large" prime, 0x7ffff = 524287 - hashCode = (hashCode << 19) - hashCode + (RootNamespace?.GetHashCode() ?? 0); - hashCode = (hashCode << 19) - hashCode + ElementName.GetHashCode(); - hashCode = (hashCode << 19) - hashCode + ElementType.GetHashCode(); - - return hashCode; - } - } - - } -} diff --git a/src/Sdk/WebApi/WebApi/VssApiResourceLocation.cs b/src/Sdk/WebApi/WebApi/VssApiResourceLocation.cs deleted file mode 100644 index 3a3628675..000000000 --- a/src/Sdk/WebApi/WebApi/VssApiResourceLocation.cs +++ /dev/null @@ -1,197 +0,0 @@ -using System; -using System.Runtime.Serialization; -using System.ComponentModel; -using GitHub.Services.Location; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi -{ - /// - /// Information about the location of a REST API resource - /// - [DataContract] - public class ApiResourceLocation : IEquatable, ISecuredObject - { - /// - /// Unique Identifier for this location - /// - [DataMember] - public Guid Id { get; set; } - - /// - /// Area name for this resource - /// - [DataMember] - public String Area { get; set; } - - /// - /// Resource name - /// - [DataMember] - public String ResourceName { get; set; } - - /// - /// This location's route template (templated relative path) - /// - [DataMember] - public String RouteTemplate { get; set; } - - /// - /// The name of the route (not serialized to the client) - /// - public String RouteName { get; set; } - - /// - /// The current resource version supported by this resource location - /// - [DataMember] - public Int32 ResourceVersion { get; set; } - - /// - /// Minimum api version that this resource supports - /// - public Version MinVersion { get; set; } - - /// - /// Minimum api version that this resource supports - /// - [DataMember(Name = "MinVersion")] - public String MinVersionString - { - get - { - return MinVersion.ToString(2); - } - private set - { - if (String.IsNullOrEmpty(value)) - { - MinVersion = new Version(1, 0); - } - else - { - MinVersion = new Version(value); - } - } - } - - /// - /// Maximum api version that this resource supports (current server version for this resource) - /// - public Version MaxVersion { get; set; } - - /// - /// Maximum api version that this resource supports (current server version for this resource) - /// - [DataMember(Name = "MaxVersion")] - public String MaxVersionString - { - get - { - return MaxVersion.ToString(2); - } - private set - { - if (String.IsNullOrEmpty(value)) - { - MaxVersion = new Version(1, 0); - } - else - { - MaxVersion = new Version(value); - } - } - } - - /// - /// The latest version of this resource location that is in "Release" (non-preview) mode - /// - public Version ReleasedVersion { get; set; } - - /// - /// The latest version of this resource location that is in "Release" (non-preview) mode - /// - [DataMember(Name = "ReleasedVersion")] - public String ReleasedVersionString - { - get - { - return ReleasedVersion.ToString(2); - } - private set - { - if (String.IsNullOrEmpty(value)) - { - ReleasedVersion = new Version(1, 0); - } - else - { - ReleasedVersion = new Version(value); - } - } - } - - /// - /// - /// - /// - public ServiceDefinition ToServiceDefinition(InheritLevel level = InheritLevel.None) - { - return new ServiceDefinition() - { - Identifier = this.Id, - ServiceType = this.Area, - DisplayName = this.ResourceName, - Description = "Resource Location", - RelativePath = this.RouteTemplate, - ResourceVersion = this.ResourceVersion, - MinVersion = this.MinVersion, - MaxVersion = this.MaxVersion, - ReleasedVersion = this.ReleasedVersion, - ToolId = "Framework", // needed for back compat for old soap clients - InheritLevel = level - }; - } - - /// - /// - /// - /// - /// - public static ApiResourceLocation FromServiceDefinition(ServiceDefinition definition) - { - return new ApiResourceLocation() - { - Id = definition.Identifier, - Area = definition.ServiceType, - ResourceName = definition.DisplayName, - RouteTemplate = definition.RelativePath, - ResourceVersion = definition.ResourceVersion, - MinVersion = definition.MinVersion, - MaxVersion = definition.MaxVersion, - ReleasedVersion = definition.ReleasedVersion, - }; - } - - public bool Equals(ApiResourceLocation other) - { - return (Guid.Equals(Id, other.Id) && - string.Equals(Area, other.Area) && - string.Equals(ResourceName, other.ResourceName) && - string.Equals(RouteTemplate, other.RouteTemplate) && - string.Equals(RouteName, other.RouteName) && - Version.Equals(ResourceVersion, other.ResourceVersion) && - Version.Equals(MinVersion, other.MinVersion) && - Version.Equals(MaxVersion, other.MaxVersion) && - Version.Equals(ReleasedVersion, other.ReleasedVersion)); - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => LocationSecurityConstants.NamespaceId; - - int ISecuredObject.RequiredPermissions => LocationSecurityConstants.Read; - - string ISecuredObject.GetToken() => LocationSecurityConstants.NamespaceRootToken; - #endregion - } -} diff --git a/src/Sdk/WebApi/WebApi/VssApiResourceLocationCollection.cs b/src/Sdk/WebApi/WebApi/VssApiResourceLocationCollection.cs deleted file mode 100644 index 9f4439c7d..000000000 --- a/src/Sdk/WebApi/WebApi/VssApiResourceLocationCollection.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace GitHub.Services.WebApi -{ - /// - /// Container for API resource locations - /// - public class ApiResourceLocationCollection - { - private Dictionary m_locationsById = new Dictionary(); - private Dictionary> m_locationsByKey = new Dictionary>(); - - /// - /// Add a new API resource location - /// - /// API resource location to add - public void AddResourceLocation(ApiResourceLocation location) - { - ApiResourceLocation existingLocation; - if (m_locationsById.TryGetValue(location.Id, out existingLocation)) - { - if (!location.Equals(existingLocation)) // unit tests will register same resources multiple times, so only throw if the ApiResourceLocation doesn't match what is already cached. - { - throw new VssApiResourceDuplicateIdException(location.Id); - } - } - - m_locationsById[location.Id] = location; - - List locationsByKey; - String locationCacheKey = GetLocationCacheKey(location.Area, location.ResourceName); - if (!m_locationsByKey.TryGetValue(locationCacheKey, out locationsByKey)) - { - locationsByKey = new List(); - m_locationsByKey.Add(locationCacheKey, locationsByKey); - } - - if (!locationsByKey.Any(x => x.Id.Equals(location.Id))) - { - locationsByKey.Add(location); - } - } - - /// - /// Add new API resource locations - /// - /// API resource locations to add - public void AddResourceLocations(IEnumerable locations) - { - if (locations != null) - { - foreach (ApiResourceLocation location in locations) - { - AddResourceLocation(location); - } - } - } - - private String GetLocationCacheKey(String area, String resourceName) - { - if (area == null) - { - area = String.Empty; - } - if (resourceName == null) - { - resourceName = String.Empty; - } - - return String.Format("{0}:{1}", area.ToLower(), resourceName.ToLower()); - } - - /// - /// Get an API resource location by location id. Returns null if not found. - /// - /// Id of the registered resource location - /// ApiResourceLocation or null if not found - public ApiResourceLocation TryGetLocationById(Guid locationId) - { - ApiResourceLocation location; - m_locationsById.TryGetValue(locationId, out location); - return location; - } - - /// - /// Get an API resource location by location id. Throws if not found. - /// - /// Id of the registered resource location - /// ApiResourceLocation or null if not found - public ApiResourceLocation GetLocationById(Guid locationId) - { - ApiResourceLocation location = TryGetLocationById(locationId); - if (location == null) - { - throw new VssResourceNotFoundException(locationId); - } - return location; - } - - /// - /// Get all API resource locations - /// - /// - public IEnumerable GetAllLocations() - { - return m_locationsById.Values; - } - - /// - /// Get all API resource locations under a given area - /// - /// Resource area name - /// - public IEnumerable GetAreaLocations(String area) - { - return m_locationsById.Values.Where(l => String.Equals(area, l.Area, StringComparison.OrdinalIgnoreCase)); - } - - /// - /// Get all API resource locations for a given resource. - /// - /// Note: There are multiple locations for a given resource when multiple routes are registered for that resource - /// Resource area name - /// Resource name - /// - public IEnumerable GetResourceLocations(String area, String resourceName) - { - List locationsByKey; - String locationCacheKey = GetLocationCacheKey(area, resourceName); - - if (m_locationsByKey.TryGetValue(locationCacheKey, out locationsByKey)) - { - return locationsByKey; - } - else - { - return Enumerable.Empty(); - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssApiResourceVersion.cs b/src/Sdk/WebApi/WebApi/VssApiResourceVersion.cs deleted file mode 100644 index b23236f78..000000000 --- a/src/Sdk/WebApi/WebApi/VssApiResourceVersion.cs +++ /dev/null @@ -1,196 +0,0 @@ -using System; -using System.Globalization; -using System.Runtime.Serialization; -using System.Text; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi -{ - /// - /// Represents version information for a REST Api resource - /// - [DataContract] - public class ApiResourceVersion - { - private const String c_PreviewStageName = "preview"; - - /// - /// Construct a new API Version info - /// - /// Public API version - /// Resource version - public ApiResourceVersion(double apiVersion, int resourceVersion = 0) - : this(new Version(apiVersion.ToString("0.0", CultureInfo.InvariantCulture)), resourceVersion) - { - } - - /// - /// Construct a new API resource Version - /// - public ApiResourceVersion() - : this(1.0) - { - } - - /// - /// Construct a new API Version info - /// - /// Public API version - /// Resource version - public ApiResourceVersion(Version apiVersion, int resourceVersion = 0) - { - ArgumentUtility.CheckForNull(apiVersion, "apiVersion"); - - ApiVersion = apiVersion; - ResourceVersion = resourceVersion; - - if (resourceVersion > 0) - { - IsPreview = true; - } - } - - /// - /// Construct a new API Version info from the given version string - /// - /// Version string in the form: - /// {ApiMajor}.{ApiMinor}[-{stage}[.{resourceVersion}]] - /// - /// For example: 1.0 or 2.0-preview or 2.0-preview.3 - public ApiResourceVersion(String apiResourceVersionString) - { - this.FromVersionString(apiResourceVersionString); - } - - /// - /// Public API version. This is the version that the public sees and is used for a large - /// group of services (e.g. the TFS 1.0 API) - /// - public Version ApiVersion { get; private set; } - - /// - /// String representation of the Public API version. This is the version that the public sees and is used - /// for a large group of services (e.g. the TFS 1.0 API) - /// - [DataMember(Name = "ApiVersion")] - public String ApiVersionString - { - get - { - return ApiVersion.ToString(2); - } - private set - { - if (String.IsNullOrEmpty(value)) - { - ApiVersion = new Version(1, 0); - } - else - { - ApiVersion = new Version(value); - } - } - } - - /// - /// Internal resource version. This is defined per-resource and is used to support - /// build-to-build compatibility of API changes within a given (in-preview) public api version. - /// For example, within the TFS 1.0 API release cycle, while it is still in preview, a resource's - /// data structure may be changed. This resource can be versioned such that older clients will - /// still work (requests will be sent to the older version) and new/upgraded clients will - /// talk to the new version of the resource. - /// - [DataMember] - public int ResourceVersion { get; set; } - - /// - /// Is the public API version in preview - /// - [DataMember(EmitDefaultValue = false)] - public bool IsPreview { get; set; } - - /// - /// Returns the version string in the form: - /// {ApiMajor}.{ApiMinor}[-{stage}[.{resourceVersion}]] - /// - /// - public override string ToString() - { - StringBuilder sbVersion = new StringBuilder(ApiVersion.ToString(2)); - if (IsPreview) - { - sbVersion.Append('-'); - sbVersion.Append(c_PreviewStageName); - - if (ResourceVersion > 0) - { - sbVersion.Append('.'); - sbVersion.Append(ResourceVersion); - } - } - return sbVersion.ToString(); - } - - private void FromVersionString(String apiVersionString) - { - if (String.IsNullOrEmpty(apiVersionString)) - { - throw new VssInvalidApiResourceVersionException(apiVersionString); - } - - // Check for a stage/resourceVersion string - int dashIndex = apiVersionString.IndexOf('-'); - if (dashIndex >= 0) - { - String stageName; - - // Check for a '.' which separate stage from resource version - int dotIndex = apiVersionString.IndexOf('.', dashIndex); - if (dotIndex > 0) - { - stageName = apiVersionString.Substring(dashIndex + 1, dotIndex - dashIndex - 1); - - int resourceVersion; - String resourceVersionString = apiVersionString.Substring(dotIndex + 1); - if (!int.TryParse(resourceVersionString, out resourceVersion)) - { - throw new VssInvalidApiResourceVersionException(apiVersionString); - } - else - { - this.ResourceVersion = resourceVersion; - } - } - else - { - stageName = apiVersionString.Substring(dashIndex + 1); - } - - // Check for supported stage names - if (String.Equals(stageName, c_PreviewStageName, StringComparison.OrdinalIgnoreCase)) - { - IsPreview = true; - } - else - { - throw new VssInvalidApiResourceVersionException(apiVersionString); - } - - // Api version is the string before the dash - apiVersionString = apiVersionString.Substring(0, dashIndex); - } - - // Trim a leading "v" for version - apiVersionString = apiVersionString.TrimStart('v'); - - double apiVersionValue; - if (!double.TryParse(apiVersionString, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out apiVersionValue)) - { - throw new VssInvalidApiResourceVersionException(apiVersionString); - } - - // Store the api version - this.ApiVersion = new Version(apiVersionValue.ToString("0.0", CultureInfo.InvariantCulture)); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssApiResourceVersionExtensions.cs b/src/Sdk/WebApi/WebApi/VssApiResourceVersionExtensions.cs deleted file mode 100644 index 92a9777a4..000000000 --- a/src/Sdk/WebApi/WebApi/VssApiResourceVersionExtensions.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Net.Http.Headers; - -namespace GitHub.Services.WebApi -{ - /// - /// Extension methods for getting/setting API resource version information from requests and to responses - /// - public static class ApiResourceVersionExtensions - { - public const String c_apiVersionHeaderKey = "api-version"; - internal const String c_legacyResourceVersionHeaderKey = "res-version"; - - /// - /// Generate version key/value pairs to use in the header, replacing any existing api-version value. - /// - /// Header values to populate - /// Version to supply in the header - public static void AddApiResourceVersionValues(this ICollection headerValues, ApiResourceVersion version) - { - AddApiResourceVersionValues(headerValues, version, replaceExisting: true, useLegacyFormat: false); - } - - /// - /// Generate version key/value pairs to use in the header - /// - /// Header values to populate - /// Version to supply in the header - /// If true, replace an existing header with the specified version. Otherwise no-op in that case - public static void AddApiResourceVersionValues(this ICollection headerValues, ApiResourceVersion version, Boolean replaceExisting) - { - AddApiResourceVersionValues(headerValues, version, replaceExisting, useLegacyFormat: false); - } - - /// - /// Generate version key/value pairs to use in the header - /// - /// Header values to populate - /// Version to supply in the header - /// If true, replace an existing header with the specified version. Otherwise no-op in that case - /// If true, use the legacy format of api-version combined with res-version - internal static void AddApiResourceVersionValues(this ICollection headerValues, ApiResourceVersion version, Boolean replaceExisting, Boolean useLegacyFormat) - { - String apiVersionHeaderValue = null; - String resVersionHeaderValue = null; - - if (useLegacyFormat) - { - apiVersionHeaderValue = version.ApiVersionString; - if (version.ResourceVersion > 0) - { - resVersionHeaderValue = version.ResourceVersion.ToString(); - } - } - else - { - apiVersionHeaderValue = version.ToString(); - } - - NameValueHeaderValue existingHeader = headerValues.FirstOrDefault(h => String.Equals(c_apiVersionHeaderKey, h.Name)); - if (existingHeader != null) - { - if (replaceExisting) - { - existingHeader.Value = apiVersionHeaderValue; - if (!String.IsNullOrEmpty(resVersionHeaderValue)) - { - NameValueHeaderValue existingResHeader = headerValues.FirstOrDefault(h => String.Equals(c_legacyResourceVersionHeaderKey, h.Name)); - if (existingResHeader != null) - { - existingResHeader.Value = resVersionHeaderValue; - } - else - { - headerValues.Add(new NameValueHeaderValue(c_legacyResourceVersionHeaderKey, resVersionHeaderValue)); - } - } - } - } - else - { - headerValues.Add(new NameValueHeaderValue(c_apiVersionHeaderKey, apiVersionHeaderValue)); - if (!String.IsNullOrEmpty(resVersionHeaderValue)) - { - headerValues.Add(new NameValueHeaderValue(c_legacyResourceVersionHeaderKey, resVersionHeaderValue)); - } - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssCamelCasePropertyNamesContractResolver.cs b/src/Sdk/WebApi/WebApi/VssCamelCasePropertyNamesContractResolver.cs deleted file mode 100644 index 84e7a6c0f..000000000 --- a/src/Sdk/WebApi/WebApi/VssCamelCasePropertyNamesContractResolver.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using Newtonsoft.Json.Serialization; - -namespace GitHub.Services.WebApi -{ - internal class VssCamelCasePropertyNamesContractResolver : CamelCasePropertyNamesContractResolver - { - protected override JsonDictionaryContract CreateDictionaryContract(Type type) - { - // We need to preserve case for keys in the PropertiesCollection - JsonDictionaryContract contract = base.CreateDictionaryContract(type); - contract.DictionaryKeyResolver = (name) => name; - return contract; - } - } - - internal class VssCamelCasePropertyNamesPreserveEnumsContractResolver : CamelCasePropertyNamesContractResolver - { - protected override JsonDictionaryContract CreateDictionaryContract(Type type) - { - // We need to preserve case for keys in the PropertiesCollection and optionally use integer values for enum keys - JsonDictionaryContract contract = base.CreateDictionaryContract(type); - - Type keyType = contract.DictionaryKeyType; - Boolean isEnumKey = keyType != null ? keyType.IsEnum : false; - - if (isEnumKey) - { - contract.DictionaryKeyResolver = (name) => ((int)Enum.Parse(keyType, name)).ToString(); - } - else - { - contract.DictionaryKeyResolver = (name) => name; - } - - return contract; - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssClientHttpRequestSettings.cs b/src/Sdk/WebApi/WebApi/VssClientHttpRequestSettings.cs deleted file mode 100644 index b7b741667..000000000 --- a/src/Sdk/WebApi/WebApi/VssClientHttpRequestSettings.cs +++ /dev/null @@ -1,161 +0,0 @@ -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Security; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Utilities.Internal; -using Microsoft.Win32; - -namespace GitHub.Services.WebApi -{ - /// - /// Provides access to common settings which control the behavior of requests for a VssHttpClient instance. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public sealed class VssClientHttpRequestSettings : VssHttpRequestSettings - { - public VssClientHttpRequestSettings() - : base() - { - } - - private VssClientHttpRequestSettings(VssClientHttpRequestSettings settingsToBeCloned) - : base(settingsToBeCloned) - { - } - - /// - /// Gets the default request settings. - /// - public static VssClientHttpRequestSettings Default => s_defaultSettings.Value; - - public VssClientHttpRequestSettings Clone() - { - return new VssClientHttpRequestSettings(this); - } - - /// - /// Reload the defaults from the Registry. - /// - internal static void ResetDefaultSettings() - { - s_defaultSettings = new Lazy(ConstructDefaultSettings); - } - - /// - /// Creates an instance of the default request settings. - /// - /// The default request settings - private static VssClientHttpRequestSettings ConstructDefaultSettings() - { - // Set up reasonable defaults in case the registry keys are not present - var settings = new VssClientHttpRequestSettings(); - -#if !NETSTANDARD - try - { - // Prefer HKCU over HKLM. - RegistryKey key = null; - - // Default store: HKCU - using (RegistryKey userRoot = VssClientEnvironment.TryGetUserRegistryRoot()) - { - if (userRoot != null) - { - key = userRoot.OpenSubKey(c_settingsKey); - } - } - - // Alternate store: HKLM - if (key == null) - { - using (RegistryKey applicationRoot = VssClientEnvironment.TryGetApplicationRegistryRoot()) - { - if (applicationRoot != null) - { - key = applicationRoot.OpenSubKey(c_settingsKey); - } - } - } - - // If no store, create the default store - if (key == null) - { - using (RegistryKey userRoot = VssClientEnvironment.TryGetUserRegistryRoot()) - { - if (userRoot != null) - { - key = userRoot.CreateSubKey(c_settingsKey); - } - } - - // Write defaults - String defaultAgentId = String.Format(CultureInfo.InvariantCulture, "VSS: {0}", Guid.NewGuid().ToString("D")); - key.SetValue(c_settingsAgentId, defaultAgentId); - } - - if (key != null) - { - using (key) - { - Boolean boolValue; - - if (Boolean.TryParse(key.GetValue(c_settingBypassProxyOnLocal) as String, out boolValue)) - { - settings.BypassProxyOnLocal = boolValue; - } - - if (Boolean.TryParse(key.GetValue(c_settingEnableCompression) as String, out boolValue)) - { - settings.CompressionEnabled = boolValue; - } - - if (key.GetValue(c_settingsDefaultTimeout) != null && key.GetValueKind(c_settingsDefaultTimeout) == RegistryValueKind.DWord) - { - settings.SendTimeout = TimeSpan.FromMilliseconds(Math.Max(1, (Int32)key.GetValue(c_settingsDefaultTimeout))); - } - - if (key.GetValue(c_settingsAgentId) != null && key.GetValueKind(c_settingsAgentId) == RegistryValueKind.String) - { - settings.AgentId = (String)key.GetValue(c_settingsAgentId); - } - } - } - - String bypass = Environment.GetEnvironmentVariable("TFS_BYPASS_PROXY_ON_LOCAL"); - if (!String.IsNullOrEmpty(bypass)) - { - settings.BypassProxyOnLocal = String.Equals(bypass, "1", StringComparison.Ordinal); - } - } - catch (Exception e) - { - // If the current account doesn't have privileges to access the registry (e.g. TFS service account) - // ignore any registry access errors... - if (!(e is SecurityException || e is UnauthorizedAccessException)) - { - Trace.WriteLine("An exception was encountered and ignored while reading settings: " + e); - } - } -#endif - - settings.UserAgent = UserAgentUtility.GetDefaultRestUserAgent(); - -#if !NETSTANDARD - //default this to true on client\server connections - settings.ClientCertificateManager = VssClientCertificateManager.Instance; -#endif - return settings; - } - - private static Lazy s_defaultSettings - = new Lazy(ConstructDefaultSettings); - - private const String c_settingsKey = "Services\\RequestSettings"; - private const String c_settingBypassProxyOnLocal = "BypassProxyOnLocal"; - private const String c_settingEnableCompression = "EnableCompression"; - private const String c_settingsDefaultTimeout = "DefaultTimeout"; - private const String c_settingsAgentId = "AgentId"; - } -} diff --git a/src/Sdk/WebApi/WebApi/VssClientSettings.cs b/src/Sdk/WebApi/WebApi/VssClientSettings.cs deleted file mode 100644 index 01d2097a2..000000000 --- a/src/Sdk/WebApi/WebApi/VssClientSettings.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.IO; -using GitHub.Services.Common; -using GitHub.Services.Common.ClientStorage; -using GitHub.Services.WebApi.Internal; -using Microsoft.Win32; - -namespace GitHub.Services.WebApi -{ - /// - /// Helper for retrieving client settings which are environment-specific or retrieved from the Windows Registry - /// - internal static class VssClientSettings - { - /// - /// Directory containing the client cache files which resides below the settings directory. - /// - /// This will look something like this: - /// C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\VisualStudio Services\[GeneratedVersionInfo.TfsProductVersion]\Cache - /// - internal static string ClientCacheDirectory - { - get - { - return Path.Combine(ClientSettingsDirectory, "Cache"); - } - } - - /// - /// Directory containing the client settings files. - /// - /// This will look something like this: - /// C:\Documents and Settings\username\Local Settings\Application Data\Microsoft\VisualStudio Services\[GeneratedVersionInfo.TfsProductVersion] - /// - internal static string ClientSettingsDirectory - { - get - { - // We purposely do not cache this value. This value needs to change if - // Windows Impersonation is being used. - return Path.Combine(VssFileStorage.ClientSettingsDirectory, GeneratedVersionInfo.TfsProductVersion); - } - } - -#if !NETSTANDARD - /// - /// Defines the expiration interval for the location service client disk cache. - /// - internal static int? ClientCacheTimeToLive - { - get - { - if (s_clientCacheTimeToLive == null && !s_checkedClientCacheTimeToLive) - { - // Check once per process lifetime, but don't keep checking the registry over and over - s_checkedClientCacheTimeToLive = true; - - // Prefer HKCU over HKLM. - RegistryKey key = null; - - // Default store: HKCU - using (RegistryKey userRoot = VssClientEnvironment.TryGetUserRegistryRoot()) - { - if (userRoot != null) - { - key = userRoot.OpenSubKey(c_cacheSettingsKey); - } - } - - // Alternate store: HKLM - if (key == null) - { - using (RegistryKey applicationRoot = VssClientEnvironment.TryGetApplicationRegistryRoot()) - { - if (applicationRoot != null) - { - key = applicationRoot.OpenSubKey(c_cacheSettingsKey); - } - } - } - - if (key != null) - { - if (key.GetValue(c_settingClientCacheTimeToLive) != null && key.GetValueKind(c_settingClientCacheTimeToLive) == RegistryValueKind.DWord) - { - s_clientCacheTimeToLive = Math.Max(1, (int)key.GetValue(c_settingClientCacheTimeToLive)); - } - } - } - - return s_clientCacheTimeToLive; - } - set - { - // For testing purposes only - s_clientCacheTimeToLive = value; - } - } - - /// - /// Gets Connect() options which are overriden in the user registry hive. - /// - internal static void GetConnectionOverrides( - out VssConnectMode? connectModeOverride, - out string userOverride) - { - connectModeOverride = null; - userOverride = VssClientEnvironment.GetSharedConnectedUserValue(VssConnectionParameterOverrideKeys.FederatedAuthenticationUser); - - var modeOverride = VssClientEnvironment.GetSharedConnectedUserValue(VssConnectionParameterOverrideKeys.FederatedAuthenticationMode); - - VssConnectMode modeOverrideValue = VssConnectMode.Automatic; - - if (modeOverride != null && Enum.TryParse(modeOverride, out modeOverrideValue)) - { - connectModeOverride = modeOverrideValue; - } - } - - private static int? s_clientCacheTimeToLive; - private static bool s_checkedClientCacheTimeToLive; -#endif - private const string c_cacheSettingsKey = "Services\\CacheSettings"; - private const string c_settingClientCacheTimeToLive = "ClientCacheTimeToLive"; - } -} diff --git a/src/Sdk/WebApi/WebApi/VssConnectMode.cs b/src/Sdk/WebApi/WebApi/VssConnectMode.cs deleted file mode 100644 index 07ae1b94e..000000000 --- a/src/Sdk/WebApi/WebApi/VssConnectMode.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace GitHub.Services.WebApi -{ - public enum VssConnectMode - { - Automatic = 0, - Licensing = 1, - Profile = 2, - Secure = 3, - User = 4, - Resource = 5 - } -} diff --git a/src/Sdk/WebApi/WebApi/VssConnection.cs b/src/Sdk/WebApi/WebApi/VssConnection.cs deleted file mode 100644 index ee7d6aa50..000000000 --- a/src/Sdk/WebApi/WebApi/VssConnection.cs +++ /dev/null @@ -1,905 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Net.Http; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.Location; -using GitHub.Services.WebApi.Internal; -using GitHub.Services.WebApi.Location; -using GitHub.Services.WebApi.Utilities; - -namespace GitHub.Services.WebApi -{ - public class VssConnection : IDisposable - { - public VssConnection( - Uri baseUrl, - VssCredentials credentials) - : this(baseUrl, credentials, VssClientHttpRequestSettings.Default.Clone()) - { - } - - public VssConnection( - Uri baseUrl, - VssCredentials credentials, - VssHttpRequestSettings settings) - : this(baseUrl, new VssHttpMessageHandler(credentials, settings), null) - { - } - - public VssConnection( - Uri baseUrl, - VssHttpMessageHandler innerHandler, - IEnumerable delegatingHandlers) - : this(baseUrl, innerHandler, delegatingHandlers, true) - { - } - - private VssConnection( - Uri baseUrl, - VssHttpMessageHandler innerHandler, - IEnumerable delegatingHandlers, - Boolean allowUnattributedClients) - { - ArgumentUtility.CheckForNull(baseUrl, "baseUrl"); - ArgumentUtility.CheckForNull(innerHandler, "innerHandler"); - - // Permit delegatingHandlers to be null - m_delegatingHandlers = delegatingHandlers = delegatingHandlers ?? Enumerable.Empty(); - - m_baseUrl = baseUrl; - m_innerHandler = innerHandler; - m_allowUnattributedClients = allowUnattributedClients; - - // Do we need to add a retry handler to the pipeline? If so, it needs to come last. - if (this.Settings.MaxRetryRequest > 0) - { - delegatingHandlers = delegatingHandlers.Concat(new DelegatingHandler[] { new VssHttpRetryMessageHandler(this.Settings.MaxRetryRequest) }); - } - - // Create and persist the pipeline. - if (delegatingHandlers.Any()) - { - m_pipeline = HttpClientFactory.CreatePipeline(m_innerHandler, delegatingHandlers); - } - else - { - m_pipeline = m_innerHandler; - } - - m_serverDataProvider = new VssServerDataProvider(this, m_pipeline, m_baseUrl.AbsoluteUri); - - if (innerHandler.Credentials != null) - { - // store base url on credentials, as it is required when creating a token storage key. - if (innerHandler.Credentials.Federated != null) - { - innerHandler.Credentials.Federated.TokenStorageUrl = baseUrl; - } - if (innerHandler.Credentials.Windows != null) - { - innerHandler.Credentials.Windows.TokenStorageUrl = baseUrl; - } - } - } - - /// - /// - /// - public Task ConnectAsync( - CancellationToken cancellationToken = default(CancellationToken)) - { - return ConnectAsync(VssConnectMode.Automatic, null, cancellationToken); - } - - public Task ConnectAsync( - VssConnectMode connectMode, - CancellationToken cancellationToken = default(CancellationToken)) - { - return ConnectAsync(connectMode, null, cancellationToken); - } - - public Task ConnectAsync( - VssConnectMode connectMode, - IDictionary parameters, - CancellationToken cancellationToken = default(CancellationToken)) - { - CheckForDisposed(); - // Set the connectMode on the credential's FederatedPrompt - if (Credentials.Federated != null && Credentials.Federated.Prompt != null) - { - if (parameters != null) - { - // Create a copy of the parameters if any were supplied. - parameters = new Dictionary(parameters); - } - else - { - parameters = new Dictionary(); - } - - IVssCredentialPrompt promptToSetParametersOn; - - // prompt can be a VssCredentialPrompts with VssFederatedCredentialPrompt inside it - IVssCredentialPrompts credentialPrompts = Credentials.Federated.Prompt as IVssCredentialPrompts; - if (credentialPrompts != null && credentialPrompts.FederatedPrompt != null) - { - // IVssCredentialPrompts contains an inner federatedPrompt, then set the paramaters on the inner one - promptToSetParametersOn = credentialPrompts.FederatedPrompt; - } - else - { - promptToSetParametersOn = Credentials.Federated.Prompt; - } - -#if DEBUG && !NETSTANDARD - VssConnectMode? connectModeOverride; - String userOverride; - VssClientSettings.GetConnectionOverrides(out connectModeOverride, out userOverride); - - if (connectModeOverride != null) - { - connectMode = connectModeOverride.Value; - } - if (userOverride != null) - { - parameters[VssConnectionParameterKeys.User] = userOverride; - } -#endif - parameters[VssConnectionParameterKeys.VssConnectionMode] = connectMode.ToString(); - promptToSetParametersOn.Parameters = parameters; - } - - return ServerDataProvider.ConnectAsync(ConnectOptions.None, cancellationToken); - } - - /// - /// - /// - public void Disconnect() - { - try - { - if (HasAuthenticated) - { - m_innerHandler.Credentials.SignOut(Uri, null, null); - } - } - finally - { - ServerDataProvider.DisconnectAsync().SyncResult(); - } - } - - /// - /// - /// - /// - /// - public T GetService() where T : IVssClientService - { - return (T)GetClientServiceImplAsync(typeof(T), Guid.Empty, GetServiceInstanceAsync).SyncResult(); - } - - /// - /// - /// - /// - /// - public async Task GetServiceAsync(CancellationToken cancellationToken = default(CancellationToken)) where T : IVssClientService - { - return (T)await GetClientServiceImplAsync(typeof(T), Guid.Empty, GetServiceInstanceAsync, cancellationToken).ConfigureAwait(false); - } - - /// - /// Retrieves an HTTP client of the specified type. - /// - /// The type of client to retrieve - /// The client of the specified type - public T GetClient() where T : VssHttpClientBase - { - return GetClientAsync().SyncResult(); - } - - /// - /// Retrieves an HTTP client of the specified type. - /// - /// The type of client to retrieve - /// Optional parameter. If supplied, the identifier will be used to resolve the - /// base address for the HTTP client. Otherwise the base address will be resolved using the service identifier - /// in the metadata of the requested client type (i.e. the ResourceArea attribute) - /// The client of the specified type - public T GetClient(Guid serviceIdentifier) where T : VssHttpClientBase - { - return GetClientAsync(serviceIdentifier).SyncResult(); - } - - /// - /// Retrieves an HTTP client of the specified type. - /// - /// The type of client to retrieve - /// The client of the specified type - public T GetClient(CancellationToken cancellationToken) where T : VssHttpClientBase - { - return GetClientAsync(cancellationToken).SyncResult(); - } - - /// - /// Retrieves an HTTP client of the specified type. - /// - /// The type of client to retrieve - /// Optional parameter. If supplied, the identifier will be used to resolve the - /// base address for the HTTP client. Otherwise the base address will be resolved using the service identifier - /// in the metadata of the requested client type (i.e. the ResourceArea attribute) - /// The client of the specified type - public T GetClient(Guid serviceIdentifier, CancellationToken cancellationToken) where T : VssHttpClientBase - { - return GetClientAsync(serviceIdentifier, cancellationToken).SyncResult(); - } - - /// - /// Retrieves an HTTP client of the specified type. - /// - /// The type of client to retrieve - /// The client of the specified type - public async Task GetClientAsync(CancellationToken cancellationToken = default(CancellationToken)) where T : VssHttpClientBase - { - CheckForDisposed(); - Type clientType = typeof(T); - Guid serviceIdentifier = GetServiceIdentifier(clientType); - - if (serviceIdentifier == Guid.Empty && !m_allowUnattributedClients) - { - throw new CannotGetUnattributedClientException(clientType); - } - - return (T)await GetClientServiceImplAsync(typeof(T), serviceIdentifier, GetClientInstanceAsync, cancellationToken).ConfigureAwait(false); - } - - /// - /// Retrieves an HTTP client of the specified type. - /// - /// The type of client to retrieve - /// Optional parameter. If supplied, the identifier will be used to resolve the - /// base address for the HTTP client. Otherwise the base address will be resolved using the service identifier - /// in the metadata of the requested client type (i.e. the ResourceArea attribute) - /// The client of the specified type - public async Task GetClientAsync(Guid serviceIdentifier, CancellationToken cancellationToken = default(CancellationToken)) where T : VssHttpClientBase - { - return (T)await GetClientServiceImplAsync(typeof(T), serviceIdentifier, GetClientInstanceAsync, cancellationToken).ConfigureAwait(false); - } - - /// - /// - /// - /// - /// - public Object GetClient(Type clientType) - { - // Verify incoming type is assignable from VssHttpClientBase - Type requiredBaseType = typeof(VssHttpClientBase); - - if (!requiredBaseType.GetTypeInfo().IsAssignableFrom(clientType.GetTypeInfo())) - { - throw new ArgumentException(requiredBaseType.FullName); - } - - // Return client instance - return GetClientServiceImplAsync(clientType, GetServiceIdentifier(clientType), GetClientInstanceAsync).SyncResult(); - } - - /// - /// - /// - /// - /// - /// - private async Task GetClientServiceImplAsync( - Type requestedType, - Guid serviceIdentifier, - Func> getInstanceAsync, - CancellationToken cancellationToken = default(CancellationToken)) - { - CheckForDisposed(); - Object requestedObject = null; - - // Get the actual type to lookup or instantiate, which will either be requestedType itself - // or an extensible type if one was registered - Type managedType = GetExtensibleType(requestedType); - - ClientCacheKey cacheKey = new ClientCacheKey(managedType, serviceIdentifier); - - // First check if we have this type already constructed - if (!m_cachedTypes.TryGetValue(cacheKey, out requestedObject)) - { - AsyncLock typeLock = m_loadingTypes.GetOrAdd(cacheKey, (t) => new AsyncLock()); - - // This ensures only a single thread at a time will be performing the work to initialize this particular type - // The other threads will go async awaiting the lock task. This is still an improvement over the old synchronous locking, - // as this thread won't be blocked (like a Monitor.Enter), but can return a task to the caller so that the thread - // can continue to be used to do useful work while the result is being worked on. - // We are trusting that getInstanceAsync does not have any code paths that lead back here (for the same type), otherwise we can deadlock on ourselves. - // The old code also extended the same trust which (if violated) would've resulted in a StackOverflowException, - // but with async tasks it will lead to a deadlock. - using (await typeLock.LockAsync(cancellationToken).ConfigureAwait(false)) - { - if (!m_cachedTypes.TryGetValue(cacheKey, out requestedObject)) - { - requestedObject = await getInstanceAsync(managedType, serviceIdentifier, cancellationToken).ConfigureAwait(false); - m_cachedTypes[cacheKey] = requestedObject; - - AsyncLock removed; - m_loadingTypes.TryRemove(cacheKey, out removed); - } - } - } - - return requestedObject; - } - - /// - /// - /// - /// - /// - /// - private Task GetClientInstanceAsync( - Type managedType, - Guid serviceIdentifier, - CancellationToken cancellationToken) - { - return GetClientInstanceAsync(managedType, serviceIdentifier, cancellationToken, null, null); - } - - /// - /// - /// - /// - /// - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - internal Task GetClientInstanceAsync( - Type managedType, - CancellationToken cancellationToken, - VssHttpRequestSettings settings, - DelegatingHandler[] handlers) - { - return GetClientInstanceAsync(managedType, GetServiceIdentifier(managedType), cancellationToken, settings, handlers); - } - - /// - /// - /// - /// - /// - private async Task GetClientInstanceAsync( - Type managedType, - Guid serviceIdentifier, - CancellationToken cancellationToken, - VssHttpRequestSettings settings, - DelegatingHandler[] handlers) - { - CheckForDisposed(); - ILocationService locationService = await GetServiceAsync(cancellationToken).ConfigureAwait(false); - ILocationDataProvider locationData = await locationService.GetLocationDataAsync(serviceIdentifier, cancellationToken).ConfigureAwait(false); - - if (locationData == null) - { - throw new VssServiceException(WebApiResources.ServerDataProviderNotFound(serviceIdentifier)); - } - - String serviceLocationString = await locationData.LocationForCurrentConnectionAsync( - ServiceInterfaces.LocationService2, - LocationServiceConstants.SelfReferenceIdentifier, - cancellationToken).ConfigureAwait(false); - - // This won't ever be null because of compat code in ServerDataProvider - Uri clientBaseUri = new Uri(serviceLocationString); - - VssHttpClientBase toReturn = null; - - if (settings != null) - { - toReturn = (VssHttpClientBase)Activator.CreateInstance(managedType, clientBaseUri, Credentials, settings, handlers); - } - else - { - toReturn = (VssHttpClientBase)Activator.CreateInstance(managedType, clientBaseUri, m_pipeline, false /* disposeHandler */); - } - - ApiResourceLocationCollection resourceLocations = await locationData.GetResourceLocationsAsync(cancellationToken).ConfigureAwait(false); - toReturn.SetResourceLocations(resourceLocations); - - return toReturn; - } - - /// - /// Gets the service and fallback identifiers from the [ResourceArea] attribute of the specified type - /// - private Guid GetServiceIdentifier( - Type requestedType) - { - ResourceAreaAttribute[] attributes = (ResourceAreaAttribute[])requestedType.GetTypeInfo().GetCustomAttributes(true); - - if (attributes.Length > 0) - { - return attributes[0].AreaId; - } - else - { - return Guid.Empty; - } - } - - /// - /// - /// - /// - /// - /// - private Task GetServiceInstanceAsync( - Type managedType, - Guid serviceIdentifier, - CancellationToken cancellationToken) - { - CheckForDisposed(); - IVssClientService clientService; - - try - { - // Create our instance of the managed service object. - clientService = (IVssClientService)Activator.CreateInstance(managedType); - } - catch (MissingMemberException ex) - { - throw new ArgumentException(WebApiResources.GetServiceArgumentError(managedType), ex); - } - - - // We successfully created an object, initialize him and finally set the - // return value. - clientService.Initialize(this); - - return Task.FromResult(clientService); - } - - /// - /// - /// - /// - /// - private Type GetExtensibleType(Type managedType) - { - if (managedType.GetTypeInfo().IsAbstract || managedType.GetTypeInfo().IsInterface) - { - Type extensibleType = null; - - // We can add extensible type registration for the client later (app.config? windows registry?). For now it is based solely on the attribute - if (!m_extensibleServiceTypes.TryGetValue(managedType.Name, out extensibleType)) - { - VssClientServiceImplementationAttribute[] attributes = (VssClientServiceImplementationAttribute[])managedType.GetTypeInfo().GetCustomAttributes(true); - if (attributes.Length > 0) - { - if (attributes[0].Type != null) - { - extensibleType = attributes[0].Type; - m_extensibleServiceTypes[managedType.Name] = extensibleType; - } - else if (!String.IsNullOrEmpty(attributes[0].TypeName)) - { - extensibleType = Type.GetType(attributes[0].TypeName); - - if (extensibleType != null) - { - m_extensibleServiceTypes[managedType.Name] = extensibleType; - } - else - { - Debug.Assert(false, "VssConnection: Could not load type from type name: " + attributes[0].TypeName); - } - } - } - } - - if (extensibleType == null) - { - throw new ExtensibleServiceTypeNotRegisteredException(managedType); - } - - if (!managedType.GetTypeInfo().IsAssignableFrom(extensibleType.GetTypeInfo())) - { - throw new ExtensibleServiceTypeNotValidException(managedType, extensibleType); - } - - return extensibleType; - } - else - { - return managedType; - } - } - - /// - /// Used for Testing Only - /// - /// - /// - internal void RegisterExtensibleType( - String typeName, - Type type) - { - ArgumentUtility.CheckStringForNullOrEmpty(typeName, "typeName"); - ArgumentUtility.CheckForNull(type, "type"); - - m_extensibleServiceTypes[typeName] = type; - } - - /// - /// Used for Testing Only - /// - /// - /// - internal void RegisterClientServiceInstance( - Type type, - Object instance) - { - ArgumentUtility.CheckForNull(type, "type"); - ArgumentUtility.CheckForNull(instance, "instance"); - CheckForDisposed(); - - if (!type.GetTypeInfo().IsAssignableFrom(instance.GetType().GetTypeInfo())) - { - // This is just a test method -- no need to resource the string - throw new ArgumentException("Object is not an instance of the specified type."); - } - - Type instanceType = instance.GetType(); - ClientCacheKey cacheKey = new ClientCacheKey(instanceType, GetServiceIdentifier(type)); - - // Now add the service to the service list. - RegisterExtensibleType(type.Name, instanceType); - m_cachedTypes[cacheKey] = instance; - } - - private bool m_isDisposed = false; - private object m_disposeLock = new object(); - - public void Dispose() - { - if (!m_isDisposed) - { - lock (m_disposeLock) - { - if (!m_isDisposed) - { - m_isDisposed = true; - foreach (var cachedType in m_cachedTypes.Values.Where(v => v is IDisposable).Select(v => v as IDisposable)) - { - cachedType.Dispose(); - } - m_cachedTypes.Clear(); - Disconnect(); - if (m_parentConnection != null) - { - m_parentConnection.Dispose(); - m_parentConnection = null; - } - } - } - } - } - - private void CheckForDisposed() - { - if (m_isDisposed) - { - throw new ObjectDisposedException(this.GetType().Name); - } - } - - /// - /// - /// - public Uri Uri - { - get - { - return m_baseUrl; - } - } - - /// - /// - /// - public VssHttpMessageHandler InnerHandler - { - get - { - return m_innerHandler; - } - } - - /// - /// - /// - public IEnumerable DelegatingHandlers - { - get - { - return m_delegatingHandlers; - } - } - - /// - /// - /// - public VssCredentials Credentials - { - get - { - return m_innerHandler.Credentials; - } - } - - /// - /// - /// - public VssClientHttpRequestSettings Settings - { - get - { - return (VssClientHttpRequestSettings)m_innerHandler.Settings; - } - } - - /// - /// The Guid that identifies the server associated with the VssConnection. - /// - public Guid ServerId - { - get - { - return ServerDataProvider.GetInstanceIdAsync().SyncResult(); - } - } - - /// - /// The Guid that identifies the type of server associated with the VssConnection - /// - public Guid ServerType - { - get - { - return ServerDataProvider.GetInstanceTypeAsync().SyncResult(); - } - } - - /// - /// The Id of the identity who the calls to the server are being made for. - /// - public Identity.Identity AuthorizedIdentity - { - get - { - return ServerDataProvider.GetAuthorizedIdentityAsync().SyncResult(); - } - } - - /// - /// - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public Identity.Identity AuthenticatedIdentity - { - get - { - return ServerDataProvider.GetAuthenticatedIdentityAsync().SyncResult(); - } - } - - /// - /// - /// - public Boolean HasAuthenticated - { - get - { - return ServerDataProvider.HasConnected; - } - } - - /// - /// The connection to the parent host for this VSS connection. If this connection is to a collection host, - /// then this property will return a connection to the account/tenant host. - /// The property will return null if a parent cannot be located for the current connection. - /// - public VssConnection ParentConnection - { - get - { - CheckForDisposed(); - if (m_parentConnection == null) - { - lock (m_parentConnectionLock) - { - ILocationService locationService = GetService(); - ILocationDataProvider locationData = locationService.GetLocationData(Guid.Empty); - - String applicationLocation = locationData.LocationForCurrentConnection( - ServiceInterfaces.LocationService2, - LocationServiceConstants.ApplicationIdentifier); - - if (String.IsNullOrEmpty(applicationLocation)) - { - throw new VssServiceException(WebApiResources.ServerDataProviderNotFound(LocationServiceConstants.ApplicationIdentifier)); - } - - m_parentConnection = new VssConnection( - new Uri(applicationLocation), - new VssHttpMessageHandler(Credentials, VssClientHttpRequestSettings.Default.Clone()), - null, - allowUnattributedClients: false); - } - } - - return m_parentConnection; - } - } - - /// - /// Used for testing. Do not use for product code. - /// - internal IVssServerDataProvider ServerDataProvider - { - get - { - return m_serverDataProvider; - } - set - { - // Used for testing - m_serverDataProvider = value; - } - } - - private IVssServerDataProvider m_serverDataProvider; - private VssConnection m_parentConnection; - private Object m_parentConnectionLock = new Object(); - - private readonly Uri m_baseUrl; - private readonly HttpMessageHandler m_pipeline; - private readonly VssHttpMessageHandler m_innerHandler; - private readonly IEnumerable m_delegatingHandlers; - private readonly Boolean m_allowUnattributedClients; - - private readonly ConcurrentDictionary m_loadingTypes = new ConcurrentDictionary(ClientCacheKey.Comparer); - private readonly ConcurrentDictionary m_cachedTypes = new ConcurrentDictionary(ClientCacheKey.Comparer); - private readonly ConcurrentDictionary m_extensibleServiceTypes = new ConcurrentDictionary(); - - private struct ClientCacheKey - { - public ClientCacheKey(Type type, Guid serviceIdentifier) - { - this.Type = type; - this.ServiceIdentifier = serviceIdentifier; - } - - public readonly Type Type; - public readonly Guid ServiceIdentifier; - - public static readonly IEqualityComparer Comparer = new ClientCacheKeyComparer(); - - private class ClientCacheKeyComparer : IEqualityComparer - { - public bool Equals(ClientCacheKey x, ClientCacheKey y) - { - return x.Type.Equals(y.Type) && - x.ServiceIdentifier.Equals(y.ServiceIdentifier); - } - - public int GetHashCode(ClientCacheKey obj) - { - return obj.Type.GetHashCode() ^ obj.ServiceIdentifier.GetHashCode(); - } - } - } - } - - /// - /// - /// - public interface IVssClientService - { - /// - /// - /// - /// - void Initialize(VssConnection connection); - } - - /// - /// - /// - [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] - [SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "FxCop can't tell that we have an accessor.")] - public sealed class VssClientServiceImplementationAttribute : Attribute - { - public VssClientServiceImplementationAttribute(Type type) - { - this.Type = type; - } - - public VssClientServiceImplementationAttribute(String typeName) - { - this.TypeName = typeName; - } - - public Type Type - { - get; - set; - } - - public String TypeName - { - get; - set; - } - } - - /// - /// - /// - [ExceptionMapping("0.0", "3.0", "ExtensibleServiceTypeNotRegisteredException", "GitHub.Services.Client.ExtensibleServiceTypeNotRegisteredException, GitHub.Services.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ExtensibleServiceTypeNotRegisteredException : VssException - { - public ExtensibleServiceTypeNotRegisteredException(Type managedType) - : base(WebApiResources.ExtensibleServiceTypeNotRegistered(managedType.Name)) - { - } - - public ExtensibleServiceTypeNotRegisteredException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - /// - /// - /// - [ExceptionMapping("0.0", "3.0", "ExtensibleServiceTypeNotValidException", "GitHub.Services.Client.ExtensibleServiceTypeNotValidException, GitHub.Services.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class ExtensibleServiceTypeNotValidException : VssException - { - public ExtensibleServiceTypeNotValidException(Type managedType, Type extensibleType) - : base(WebApiResources.ExtensibleServiceTypeNotValid(managedType.Name, extensibleType.Name)) - { - } - - public ExtensibleServiceTypeNotValidException(String message, Exception innerException) - : base(message, innerException) - { - } - } - - public class CannotGetUnattributedClientException : VssException - { - public CannotGetUnattributedClientException(Type clientType) - : base(WebApiResources.CannotGetUnattributedClient(clientType.Name)) - { - } - - public CannotGetUnattributedClientException(String message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssConnectionParameterKeys.cs b/src/Sdk/WebApi/WebApi/VssConnectionParameterKeys.cs deleted file mode 100644 index 11969bec2..000000000 --- a/src/Sdk/WebApi/WebApi/VssConnectionParameterKeys.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.ComponentModel; - -namespace GitHub.Services.WebApi.Internal -{ - [EditorBrowsable(EditorBrowsableState.Never)] - public static class VssConnectionParameterKeys - { - public const string User = "user"; - public const string AccessToken = "accessToken"; - public const string VssConnectionMode = "vssConnectionMode"; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static class VssConnectionParameterOverrideKeys - { - public const string AadInstance = "AadInstance"; - public const string AadNativeClientIdentifier = "AadClientIdentifier"; - public const string AadNativeClientRedirect = "AadNativeClientRedirect"; - public const string AadApplicationTenant = "AadApplicationTenant"; - public const string ConnectedUserRoot = "ConnectedUser"; - public const string FederatedAuthenticationMode = "FederatedAuthenticationMode"; - public const string FederatedAuthenticationUser = "FederatedAuthenticationUser"; - public const string UseAadWindowsIntegrated = "UseAadWindowsIntegrated"; - } -} diff --git a/src/Sdk/WebApi/WebApi/VssEventId.cs b/src/Sdk/WebApi/WebApi/VssEventId.cs deleted file mode 100644 index 0c5fd4236..000000000 --- a/src/Sdk/WebApi/WebApi/VssEventId.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace GitHub.Services.WebApi -{ - /// Define event log id ranges - /// This corresponds with values in Framework\Server\Common\EventLog.cs - public static class VssEventId - { - public static readonly int DefaultEventId = 0; - - // Errors - public static readonly int ExceptionBaseEventId = 3000; - - private static readonly int EtmBaseEventId = ExceptionBaseEventId + 1200; // 4200 - public static readonly int VssIdentityServiceException = EtmBaseEventId + 7; - public static readonly int AccountException = EtmBaseEventId + 36; - - //File Container Service range - public static readonly int FileContainerBaseEventId = ExceptionBaseEventId + 1700; // 4700 - } -} diff --git a/src/Sdk/WebApi/WebApi/VssHttpClientBase.cs b/src/Sdk/WebApi/WebApi/VssHttpClientBase.cs deleted file mode 100644 index d0fffda2b..000000000 --- a/src/Sdk/WebApi/WebApi/VssHttpClientBase.cs +++ /dev/null @@ -1,1318 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2014 All Rights Reserved -// -//----------------------------------------------------------------------- - -using System; -using System.Collections; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Net.Http.Headers; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.Common.Diagnostics; -using GitHub.Services.Common.Internal; -using GitHub.Services.WebApi.Utilities.Internal; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi -{ - /// - /// This class is used as the base class for all the REST client classes. - /// It wraps a System.Net.Http.HttpClient and sets up standard defaults. - /// - public abstract class VssHttpClientBase : IDisposable - { - protected VssHttpClientBase( - Uri baseUrl, - VssCredentials credentials) - : this(baseUrl, credentials, settings: null) - { - } - - protected VssHttpClientBase( - Uri baseUrl, - VssCredentials credentials, - VssHttpRequestSettings settings) - : this(baseUrl, credentials, settings: settings, handlers: null) - { - } - - protected VssHttpClientBase( - Uri baseUrl, - VssCredentials credentials, - params DelegatingHandler[] handlers) - : this(baseUrl, credentials, null, handlers) - { - } - - protected VssHttpClientBase( - Uri baseUrl, - VssCredentials credentials, - VssHttpRequestSettings settings, - params DelegatingHandler[] handlers) - : this(baseUrl, BuildHandler(credentials, settings, handlers), disposeHandler: true) - { - } - - protected VssHttpClientBase( - Uri baseUrl, - HttpMessageHandler pipeline, - bool disposeHandler) - { - m_client = new HttpClient(pipeline, disposeHandler); - - // Disable their timeout since we handle it ourselves - m_client.Timeout = TimeSpan.FromMilliseconds(-1.0); - m_client.BaseAddress = baseUrl; - m_formatter = new VssJsonMediaTypeFormatter(); - - SetServicePointOptions(); - - SetTokenStorageUrlIfNeeded(pipeline); - } - - private void SetTokenStorageUrlIfNeeded(HttpMessageHandler handler) - { - // The TokenStorageUrl should be set by the VssConnection, so that the same - // url is used for the token storage key regardless of the service this client - // talks to. If the VssHttpClient is created directly, then the best we can do - // is to set the storage url to match the base url of the client. - if (handler is VssHttpMessageHandler vssHttpMessageHandler) - { - if (vssHttpMessageHandler.Credentials != null) - { - if (vssHttpMessageHandler.Credentials.Federated != null - && vssHttpMessageHandler.Credentials.Federated.TokenStorageUrl == null) - { - vssHttpMessageHandler.Credentials.Federated.TokenStorageUrl = m_client.BaseAddress; - } - if (vssHttpMessageHandler.Credentials.Windows != null - && vssHttpMessageHandler.Credentials.Windows.TokenStorageUrl == null) - { - vssHttpMessageHandler.Credentials.Windows.TokenStorageUrl = m_client.BaseAddress; - } - } - } - else if (handler is DelegatingHandler delegatingHandler) - { - SetTokenStorageUrlIfNeeded(delegatingHandler.InnerHandler); - } - } - - private static HttpMessageHandler BuildHandler(VssCredentials credentials, VssHttpRequestSettings settings, DelegatingHandler[] handlers) - { - VssHttpMessageHandler innerHandler = new VssHttpMessageHandler(credentials, settings ?? new VssHttpRequestSettings()); - - if (null == handlers || - 0 == handlers.Length) - { - return innerHandler; - } - - return HttpClientFactory.CreatePipeline(innerHandler, handlers); - } - - /// - /// The base address. - /// - public Uri BaseAddress - { - get - { - return m_client.BaseAddress; - } - } - - /// - /// - /// - public VssResponseContext LastResponseContext - { - get { return m_LastResponseContext; } - } - - /// - /// The inner client. - /// - /// - /// Note to implementers: You should not update or expose the inner client - /// unless you instantiate your own instance of this class. Getting - /// an instance of this class from method such as GetClient<T> - /// a cached and shared instance. - /// - protected HttpClient Client - { - get - { - return m_client; - } - } - - /// - /// The media type formatter. - /// - /// - /// Note to implementers: You should not update or expose the media type formatter - /// unless you instantiate your own instance of this class. Getting - /// an instance of this class from method such as GetClient<T> - /// a cached and shared instance. - /// - protected MediaTypeFormatter Formatter - { - get - { - return m_formatter; - } - } - - /// - /// - /// - protected virtual IDictionary TranslatedExceptions - { - get - { - return null; - } - } - - protected HttpResponseMessage Send( - HttpRequestMessage message, - Object userState = null) - { - try - { - var response = SendAsync(message, userState); - - return response.Result; - } - catch (AggregateException ag) - { - ag = ag.Flatten(); - if (ag.InnerExceptions.Count == 1) - { - throw ag.InnerExceptions[0]; - } - throw; - } - } - - protected Task DeleteAsync( - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Delete, - locationId, - routeValues, - version, - /*content:*/ null, - queryParameters, - userState, - cancellationToken); - } - - protected Task GetAsync( - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Get, - locationId, - routeValues, - version, - /*content:*/ null, - queryParameters, - userState, - cancellationToken); - } - - protected Task GetAsync( - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Get, - locationId, - routeValues, - version, - /*content:*/ null, - queryParameters, - userState, - cancellationToken); - } - - protected Task PatchAsync( - T value, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ s_patchMethod.Value, - locationId, - routeValues, - version, - /*content:*/ new ObjectContent(value, m_formatter), - queryParameters, - userState, - cancellationToken); - } - - protected Task PatchAsync( - T value, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ s_patchMethod.Value, - locationId, - routeValues, - version, - /*content:*/ new ObjectContent(value, m_formatter), - queryParameters, - userState, - cancellationToken); - } - - protected Task PostAsync( - T value, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Post, - locationId, - routeValues, - version, - /*content:*/ new ObjectContent(value, m_formatter), - queryParameters, - userState, - cancellationToken); - } - - protected Task PostAsync( - T value, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Post, - locationId, - routeValues, - version, - /*content:*/ new ObjectContent(value, m_formatter), - queryParameters, - userState, - cancellationToken); - } - - protected Task PutAsync( - T value, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Put, - locationId, - routeValues, - version, - /*content:*/ new ObjectContent(value, m_formatter), - queryParameters, - userState, - cancellationToken); - } - - protected Task PutAsync( - T value, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return this.SendAsync( - /*method:*/ HttpMethod.Put, - locationId, - routeValues, - version, - /*content:*/ new ObjectContent(value, m_formatter), - queryParameters, - userState, - cancellationToken); - } - - protected Task SendAsync( - HttpMethod method, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - return SendAsync(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken); - } - - protected async Task SendAsync( - HttpMethod method, - IEnumerable> additionalHeaders, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) - using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) - { - return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false); - } - } - - protected async Task SendAsync( - HttpMethod method, - IEnumerable> additionalHeaders, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) - using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) - { - return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false); - } - } - - protected HttpResponseMessage Send( - HttpMethod method, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null) - { - using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) - using (HttpRequestMessage requestMessage = CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, CancellationToken.None).SyncResult()) - { - return Send(requestMessage, userState); - } - } - - protected async Task SendAsync( - HttpMethod method, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) - using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) - { - return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false); - } - } - - protected async Task SendAsync( - HttpMethod method, - Guid locationId, - HttpCompletionOption completionOption, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - using (VssTraceActivity.GetOrCreate().EnterCorrelationScope()) - using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false)) - { - return await SendAsync(requestMessage, completionOption, userState, cancellationToken).ConfigureAwait(false); - } - } - - /// - /// Create an HTTP request message for the given location, replacing parameters in the location's route template - /// with values in the supplied routeValues dictionary. - /// - /// HTTP verb to use - /// Id of the location to use - /// Values to use to replace parameters in the location's route template - /// Version to send in the request or null to use the VSS latest API version - /// The mediatype to set in request header. - /// HttpRequestMessage - protected Task CreateRequestMessageAsync( - HttpMethod method, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken), - String mediaType = c_jsonMediaType) - { - return CreateRequestMessageAsync(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, mediaType); - } - - /// - /// Create an HTTP request message for the given location, replacing parameters in the location's route template - /// with values in the supplied routeValues dictionary. - /// - /// HTTP verb to use - /// Id of the location to use - /// Values to use to replace parameters in the location's route template - /// Version to send in the request or null to use the VSS latest API version - /// The mediatype to set in request header. - /// HttpRequestMessage - protected virtual async Task CreateRequestMessageAsync( - HttpMethod method, - IEnumerable> additionalHeaders, - Guid locationId, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken), - String mediaType = c_jsonMediaType) - { - // Lookup the location - ApiResourceLocation location = await GetResourceLocationAsync(locationId, userState, cancellationToken).ConfigureAwait(false); - if (location == null) - { - throw new VssResourceNotFoundException(locationId, BaseAddress); - } - - return CreateRequestMessage(method, additionalHeaders, location, routeValues, version, content, queryParameters, mediaType); - } - - /// - /// Create an HTTP request message for the given location, replacing parameters in the location's route template - /// with values in the supplied routeValues dictionary. - /// - /// HTTP verb to use - /// API resource location - /// Values to use to replace parameters in the location's route template - /// Version to send in the request or null to use the VSS latest API version - /// The mediatype to set in request header. - /// HttpRequestMessage - protected HttpRequestMessage CreateRequestMessage( - HttpMethod method, - ApiResourceLocation location, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - String mediaType = c_jsonMediaType) - { - return CreateRequestMessage(method, null, location, routeValues, version, content, queryParameters, mediaType); - } - - /// - /// Create an HTTP request message for the given location, replacing parameters in the location's route template - /// with values in the supplied routeValues dictionary. - /// - /// HTTP verb to use - /// API resource location - /// Values to use to replace parameters in the location's route template - /// Version to send in the request or null to use the VSS latest API version - /// The mediatype to set in request header. - /// HttpRequestMessage - protected HttpRequestMessage CreateRequestMessage( - HttpMethod method, - IEnumerable> additionalHeaders, - ApiResourceLocation location, - Object routeValues = null, - ApiResourceVersion version = null, - HttpContent content = null, - IEnumerable> queryParameters = null, - String mediaType = c_jsonMediaType) - { - CheckForDisposed(); - // Negotiate the request version to send - ApiResourceVersion requestVersion = NegotiateRequestVersion(location, version); - if (requestVersion == null) - { - throw new VssVersionNotSupportedException(location, version.ApiVersion, location.MinVersion, BaseAddress); - } - - // Construct the url - Dictionary valuesDictionary = VssHttpUriUtility.ToRouteDictionary(routeValues, location.Area, location.ResourceName); - - String locationRelativePath = VssHttpUriUtility.ReplaceRouteValues(location.RouteTemplate, valuesDictionary); - Uri locationUri = VssHttpUriUtility.ConcatUri(BaseAddress, locationRelativePath); - if (queryParameters != null && queryParameters.Any()) - { - locationUri = locationUri.AppendQuery(queryParameters); - } - - // Create the message and populate headers - HttpRequestMessage requestMessage = new HttpRequestMessage(method, locationUri.AbsoluteUri); - - MediaTypeWithQualityHeaderValue acceptType = CreateAcceptHeader(requestVersion, mediaType); - - if (m_excludeUrlsHeader) - { - acceptType.Parameters.Add(new NameValueHeaderValue(VssHttpRequestSettings.ExcludeUrlsHeader, "true")); - } - if (m_lightweightHeader) - { - acceptType.Parameters.Add(new NameValueHeaderValue(VssHttpRequestSettings.LightweightHeader, "true")); - } - - requestMessage.Headers.Accept.Add(acceptType); - - if (additionalHeaders != null) - { - foreach (KeyValuePair kvp in additionalHeaders) - { - requestMessage.Headers.Add(kvp.Key, kvp.Value); - } - } - - if (content != null) - { - requestMessage.Content = content; - if (requestMessage.Content.Headers.ContentType != null && !requestMessage.Content.Headers.ContentType.Parameters.Any(p => p.Name.Equals(ApiResourceVersionExtensions.c_apiVersionHeaderKey))) - { - // add the api-version to the content header, which will be used by the JsonCompatConverter to know which version of the model to convert to. - requestMessage.Content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue(ApiResourceVersionExtensions.c_apiVersionHeaderKey, requestVersion.ToString())); - } - } - - return requestMessage; - } - - protected virtual MediaTypeWithQualityHeaderValue CreateAcceptHeader(ApiResourceVersion requestVersion, String mediaType) - { - MediaTypeWithQualityHeaderValue acceptType = new MediaTypeWithQualityHeaderValue(mediaType); - acceptType.Parameters.AddApiResourceVersionValues(requestVersion, replaceExisting: true, useLegacyFormat: requestVersion.ApiVersion.Major <= 1); - return acceptType; - } - - protected virtual void AddModelAsQueryParams(IList> queryParams, string parameterName, object model) - { - JObject jObject = JObject.FromObject(model, new VssJsonMediaTypeFormatter().CreateJsonSerializer()); - AddModelAsQueryParams(queryParams, parameterName, jObject); - } - - protected virtual void AddIEnumerableAsQueryParams(IList> queryParams, string parameterName, object model) - { - JArray jArray = JArray.FromObject(model, new VssJsonMediaTypeFormatter().CreateJsonSerializer()); - AddModelAsQueryParams(queryParams, parameterName, jArray); - } - - private void AddModelAsQueryParams(IList> queryParams, string parameterName, JObject jObject) - { - foreach (JProperty property in jObject.Properties()) - { - AddModelAsQueryParams(queryParams, parameterName, property); - } - } - - private void AddModelAsQueryParams(IList> queryParams, string key, JProperty property) - { - if (property.Value != null) - { - string newKey = string.Format("{0}[{1}]", key, property.Name); - AddModelAsQueryParams(queryParams, newKey, property.Value); - } - } - - private void AddModelAsQueryParams(IList> queryParams, string key, JArray array) - { - int i = 0; - foreach (JToken childToken in array.Children()) - { - string newKey = string.Format("{0}[{1}]", key, i); - AddModelAsQueryParams(queryParams, newKey, childToken); - i++; - } - } - - private void AddModelAsQueryParams(IList> queryParams, string key, JToken token) - { - if (token.Type == JTokenType.Array) - { - AddModelAsQueryParams(queryParams, key, (JArray)token); - } - else if (token.Type == JTokenType.Object) - { - AddModelAsQueryParams(queryParams, key, (JObject)token); - } - else if (token.Type == JTokenType.Property) - { - AddModelAsQueryParams(queryParams, key, (JProperty)token); - } - else if (token.Type == JTokenType.Date) - { - AddDateTimeToQueryParams(queryParams, key, (DateTime)token); - } - else - { - queryParams.Add(key, token.ToString()); - } - } - - /// - /// Ensures we are using a standard format for sending DateTime value as a query parameter (o: 2015-02-16T16:11:31.1398684Z) - /// - /// - /// - /// local DateTime value - protected void AddDateTimeToQueryParams(IList> queryParams, String name, DateTime localDateTime) - { - // converting to universal time to match json serialization server is using - queryParams.Add(name, localDateTime.ToUniversalTime().ToString("o", CultureInfo.InvariantCulture)); - } - - /// - /// Ensures we are using a standard format for sending DateTime value as a query parameter (o: 2015-02-16T16:11:31.1398684Z) - /// - /// - /// - /// - protected void AddDateTimeToQueryParams(IList> queryParams, String name, DateTimeOffset dateTimeOffset) - { - queryParams.Add(name, dateTimeOffset.ToString("o", CultureInfo.InvariantCulture)); - } - - /// - /// Ensures we are using a standard format (HTTP-date) for sending DateTime value as header - /// (r: Wed, 1 Jan 2016 18:43:31 GMT) per W3C specification. - /// - /// - /// - /// - protected void AddDateTimeToHeaders(IList> queryParams, String name, DateTimeOffset dateTimeOffset) - { - queryParams.Add(name, dateTimeOffset.ToString("r", CultureInfo.InvariantCulture)); - } - - protected async Task SendAsync( - HttpRequestMessage message, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - //ConfigureAwait(false) enables the continuation to be run outside - //any captured SyncronizationContext (such as ASP.NET's) which keeps things - //from deadlocking... - using (HttpResponseMessage response = await this.SendAsync(message, userState, cancellationToken).ConfigureAwait(false)) - { - return await ReadContentAsAsync(response, cancellationToken).ConfigureAwait(false); - } - } - - protected async Task ReadContentAsAsync(HttpResponseMessage response, CancellationToken cancellationToken = default(CancellationToken)) - { - CheckForDisposed(); - Boolean isJson = IsJsonResponse(response); - bool mismatchContentType = false; - try - { - //deal with wrapped collections in json - if (isJson && - typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) && - !typeof(Byte[]).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) && - !typeof(JObject).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo())) - { - // expect it to come back wrapped, if it isn't it is a bug! - var wrapper = await ReadJsonContentAsync>(response, cancellationToken).ConfigureAwait(false); - return wrapper.Value; - } - else if (isJson) - { - return await ReadJsonContentAsync(response, cancellationToken).ConfigureAwait(false); - } - } - catch (JsonReaderException) - { - // We thought the content was JSON but failed to parse. - // In this case, do nothing and utilize the HandleUnknownContentType call below - mismatchContentType = true; - } - - if (HasContent(response)) - { - return await HandleInvalidContentType(response, mismatchContentType).ConfigureAwait(false); - } - else - { - return default(T); - } - } - - protected virtual async Task ReadJsonContentAsync(HttpResponseMessage response, CancellationToken cancellationToken = default(CancellationToken)) - { - return await response.Content.ReadAsAsync(new[] { m_formatter }, cancellationToken).ConfigureAwait(false); - } - - protected Task SendAsync( - HttpRequestMessage message, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - // the default in httpClient for HttpCompletionOption is ResponseContentRead so that is what we do here - return this.SendAsync( - message, - /*completionOption:*/ HttpCompletionOption.ResponseContentRead, - userState, - cancellationToken); - } - - protected async Task SendAsync( - HttpRequestMessage message, - HttpCompletionOption completionOption, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - CheckForDisposed(); - if (message.Headers.UserAgent != null) - { - foreach (ProductInfoHeaderValue headerValue in UserAgentUtility.GetDefaultRestUserAgent()) - { - if (!message.Headers.UserAgent.Contains(headerValue)) - { - message.Headers.UserAgent.Add(headerValue); - } - } - } - - VssTraceActivity traceActivity = VssTraceActivity.GetOrCreate(); - using (traceActivity.EnterCorrelationScope()) - { - if (userState != null) - { - message.Properties[UserStatePropertyName] = userState; - } - - if (!message.Headers.Contains(Common.Internal.HttpHeaders.VssE2EID)) - { - message.Headers.Add(Common.Internal.HttpHeaders.VssE2EID, Guid.NewGuid().ToString("D")); - } - VssHttpEventSource.Log.HttpRequestStart(traceActivity, message); - message.Trace(); - message.Properties[VssTraceActivity.PropertyName] = traceActivity; - - // Send the completion option to the inner handler stack so we know when it's safe to buffer - // and when we should avoid buffering. - message.Properties[VssHttpRequestSettings.HttpCompletionOptionPropertyName] = completionOption; - - //ConfigureAwait(false) enables the continuation to be run outside - //any captured SyncronizationContext (such as ASP.NET's) which keeps things - //from deadlocking... - HttpResponseMessage response = await Client.SendAsync(message, completionOption, cancellationToken).ConfigureAwait(false); - - // Inject delay or failure for testing - if (TestDelay != TimeSpan.Zero) - { - await ProcessDelayAsync().ConfigureAwait(false); - } - - await HandleResponseAsync(response, cancellationToken).ConfigureAwait(false); - - return response; - } - } - - [Obsolete("Use VssHttpClientBase.HandleResponseAsync instead")] - protected virtual void HandleResponse(HttpResponseMessage response) - { - - } - - protected virtual async Task HandleResponseAsync( - HttpResponseMessage response, - CancellationToken cancellationToken) - { - response.Trace(); - VssHttpEventSource.Log.HttpRequestStop(VssTraceActivity.Current, response); - - m_LastResponseContext = new VssResponseContext(response.StatusCode, response.Headers); - - if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired) - { - throw (m_LastResponseContext.Exception = new ProxyAuthenticationRequiredException()); - } - else if (ShouldThrowError(response)) - { - Exception exToThrow = null; - if (IsJsonResponse(response)) - { - exToThrow = await UnwrapExceptionAsync(response.Content, cancellationToken).ConfigureAwait(false); - } - - if (exToThrow == null || !(exToThrow is VssException)) - { - String message = null; - if (exToThrow != null) - { - message = exToThrow.Message; - } - - IEnumerable serviceError; - if (response.Headers.TryGetValues(Common.Internal.HttpHeaders.TfsServiceError, out serviceError)) - { - message = UriUtility.UrlDecode(serviceError.FirstOrDefault()); - } - else if (String.IsNullOrEmpty(message) && !String.IsNullOrEmpty(response.ReasonPhrase)) - { - message = response.ReasonPhrase; - } - exToThrow = new VssServiceResponseException(response.StatusCode, message, exToThrow); - } - - m_LastResponseContext.Exception = exToThrow; - throw exToThrow; - } - } - - protected async Task UnwrapExceptionAsync(HttpContent content, CancellationToken cancellationToken) - { - WrappedException wrappedException = await content.ReadAsAsync(new MediaTypeFormatter[] { m_formatter }, cancellationToken).ConfigureAwait(false); - return wrappedException.Unwrap(this.TranslatedExceptions); - } - - protected virtual bool ShouldThrowError(HttpResponseMessage response) - { - return !response.IsSuccessStatusCode; - } - - /// - /// Negotiate the appropriate request version to use for the given api resource location, based on - /// the client and server capabilities - /// - /// Id of the API resource location - /// Client version to attempt to use (use the latest VSS API version if unspecified) - /// Max API version supported on the server that is less than or equal to the client version. Returns null if the server does not support this location or this version of the client. - protected async Task NegotiateRequestVersionAsync( - Guid locationId, - ApiResourceVersion version = null, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - ApiResourceLocation location = await GetResourceLocationAsync(locationId, userState, cancellationToken).ConfigureAwait(false); - if (location == null) - { - return null; - } - else - { - return NegotiateRequestVersion(location, version); - } - } - - /// - /// Negotiate the appropriate request version to use for the given api resource location, based on - /// the client and server capabilities - /// - /// Location of the API resource - /// Client version to attempt to use (use the latest VSS API version if unspecified) - /// Max API version supported on the server that is less than or equal to the client version. Returns null if the server does not support this location or this version of the client. - protected ApiResourceVersion NegotiateRequestVersion( - ApiResourceLocation location, - ApiResourceVersion version = null) - { - if (version == null) - { - version = m_defaultApiVersion; - } - - if (location.MinVersion > version.ApiVersion) - { - // Client is older than the server. The server no longer supports this resource (deprecated). - return null; - } - else if (location.MaxVersion < version.ApiVersion) - { - // Client is newer than the server. Negotiate down to the latest version on the server - ApiResourceVersion negotiatedVersion = new ApiResourceVersion(location.MaxVersion, 0); - negotiatedVersion.IsPreview = location.ReleasedVersion < location.MaxVersion; - return negotiatedVersion; - } - else - { - // We can send at the requested api version. Make sure the resource version is not bigger than what the server supports - int resourceVersion = Math.Min(version.ResourceVersion, location.ResourceVersion); - ApiResourceVersion negotiatedVersion = new ApiResourceVersion(version.ApiVersion, resourceVersion); - if (location.ReleasedVersion < version.ApiVersion) - { - negotiatedVersion.IsPreview = true; - } - else - { - negotiatedVersion.IsPreview = version.IsPreview; - } - return negotiatedVersion; - } - } - - /// - /// Sets the ApiResourceLocationCollection for this VssHttpClientBase. - /// If unset and needed, the data will be fetched through an OPTIONS request. - /// - public void SetResourceLocations(ApiResourceLocationCollection resourceLocations) - { - if (null == m_resourceLocations) - { - m_resourceLocations = resourceLocations; - } - } - - /// - /// Adds the excludeUrls=true accept header to the requests generated by this client. - /// If respected by the server, urls will not be included in the responses. - /// - public bool ExcludeUrlsHeader - { - get - { - return m_excludeUrlsHeader; - } - - set - { - m_excludeUrlsHeader = value; - } - } - - - /// - /// Add the lightWeight=true option to the accept header in the requests generated by this client. - /// If respected by the server, light weight responses carrying only basic metadata information - /// will be returned and urls will be excluded. - /// - public bool LightweightHeader - { - get - { - return m_lightweightHeader; - } - set - { - m_lightweightHeader = value; - } - } - - /// - /// Get information about an API resource location by its location id - /// - /// Id of the API resource location - /// - protected async Task GetResourceLocationAsync( - Guid locationId, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - CheckForDisposed(); - await EnsureResourceLocationsPopulated(userState, cancellationToken).ConfigureAwait(false); - return m_resourceLocations.TryGetLocationById(locationId); - } - - internal virtual async Task> GetResourceLocationsAsync( - Boolean allHostTypes, - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - CheckForDisposed(); - // Send an Options request to retrieve all api resource locations if the collection of resource locations is not populated. - Uri optionsUri = VssHttpUriUtility.ConcatUri(BaseAddress, allHostTypes ? c_optionsRelativePathWithAllHostTypes : c_optionsRelativePath); - using (HttpRequestMessage optionsRequest = new HttpRequestMessage(HttpMethod.Options, optionsUri)) - { - return await SendAsync>(optionsRequest, userState, cancellationToken: cancellationToken).ConfigureAwait(false); - } - } - - internal async Task EnsureResourceLocationsPopulated( - Object userState = null, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (m_resourceLocations == null) - { - // Send an Options request to retrieve all api resource locations if the collection of resource locations is not populated. - Uri optionsUri = VssHttpUriUtility.ConcatUri(BaseAddress, c_optionsRelativePath); - IEnumerable locations = await GetResourceLocationsAsync(allHostTypes: false, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false); - ApiResourceLocationCollection resourceLocations = new ApiResourceLocationCollection(); - resourceLocations.AddResourceLocations(locations); - m_resourceLocations = resourceLocations; - } - } - - private Boolean HasContent(HttpResponseMessage response) - { - if (response != null && - response.StatusCode != HttpStatusCode.NoContent && - response.RequestMessage?.Method != HttpMethod.Head && - response.Content?.Headers != null && - (!response.Content.Headers.ContentLength.HasValue || - (response.Content.Headers.ContentLength.HasValue && response.Content.Headers.ContentLength != 0))) - { - return true; - } - - return false; - } - - private Boolean IsJsonResponse( - HttpResponseMessage response) - { - if (HasContent(response) - && response.Content.Headers != null && response.Content.Headers.ContentType != null - && !String.IsNullOrEmpty(response.Content.Headers.ContentType.MediaType)) - { - return (0 == String.Compare("application/json", response.Content.Headers.ContentType.MediaType, StringComparison.OrdinalIgnoreCase)); - } - - return false; - } - - private async Task HandleInvalidContentType(HttpResponseMessage response, bool isMismatchedContentType) - { - //the response is not Json, cannot read it with Json formatter, get the string and throw an exception - String responseType = response.Content?.Headers?.ContentType?.MediaType ?? "Unknown"; - using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) - { - using (var streamReader = new StreamReader(responseStream)) - { - //read at most 4K - const int oneK = 1024; - char[] contentBuffer = new char[4 * oneK]; - int contentLength = 0; - for (int i = 0; i < 4; i++) - { - int read = await streamReader.ReadAsync(contentBuffer, i * oneK, oneK).ConfigureAwait(false); - contentLength += read; - if (read < oneK) break; - } - - string responseText; - if (isMismatchedContentType) - { - responseText = $"Mismatched response content type. {responseType} Response Content: {new String(contentBuffer, 0, contentLength)}"; - } - else - { - responseText = $"Invalid response content type: {responseType} Response Content: {new String(contentBuffer, 0, contentLength)}"; - } - - throw new VssServiceResponseException(response.StatusCode, responseText, null); - } - } - } - - private void SetServicePointOptions() - { - if (BaseAddress != null) - { - ServicePoint servicePoint = ServicePointManager.FindServicePoint(BaseAddress); - servicePoint.UseNagleAlgorithm = false; - servicePoint.SetTcpKeepAlive( - enabled: true, - keepAliveTime: c_keepAliveTime, - keepAliveInterval: c_keepAliveInterval); - } - } - - // ServicePoint defaults - private const int c_keepAliveTime = 30000; - private const int c_keepAliveInterval = 5000; - - #region IDisposable Support - private bool m_isDisposed = false; - private object m_disposeLock = new object(); - - [Obsolete("This overload of Dispose has been deprecated. Use the Dispose() method.")] - [EditorBrowsable(EditorBrowsableState.Never)] - protected virtual void Dispose(bool disposing) - { - if (disposing) - { - Dispose(); - } - } - - public void Dispose() - { - if (!m_isDisposed) - { - lock (m_disposeLock) - { - if (!m_isDisposed) - { - m_isDisposed = true; - m_client.Dispose(); - } - } - } - } - - private void CheckForDisposed() - { - if (m_isDisposed) - { - throw new ObjectDisposedException(this.GetType().Name); - } - } - #endregion - - protected IEnumerable GetHeaderValue(HttpResponseMessage response, string headerName) - { - IEnumerable headerValue; - if (!response.Headers.TryGetValues(headerName, out headerValue)) - { - if (response.Content != null) - { - response.Content.Headers.TryGetValues(headerName, out headerValue); - } - } - return headerValue; - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static TimeSpan TestDelay { get; set; } - - private async Task ProcessDelayAsync() - { - await Task.Delay(Math.Abs((Int32)TestDelay.TotalMilliseconds)).ConfigureAwait(false); - if (TestDelay < TimeSpan.Zero) - { - throw new Exception("User injected failure."); - } - } - - /// - /// Internal for testing only. - /// - internal bool HasResourceLocations - { - get - { - return m_resourceLocations != null; - } - } - - private readonly HttpClient m_client; - private MediaTypeFormatter m_formatter; - private VssResponseContext m_LastResponseContext; - private ApiResourceLocationCollection m_resourceLocations; - private ApiResourceVersion m_defaultApiVersion = new ApiResourceVersion(1.0); - - /// - /// Client option to suppress the generation of links in the responses for the requests made by this client. - /// If set, "excludeUrls=true" will be appended to the Accept header of the request. - /// - private bool m_excludeUrlsHeader; - - /// - /// Client option to generate lightweight responses that carry only basic metadata information for the - /// requests made by this client. Links should not be generated either. - /// If set, "lightweight=true" will be appended to the Accept header of the request. - /// - private bool m_lightweightHeader; - - private Lazy s_patchMethod = new Lazy(() => new HttpMethod("PATCH")); - - /// - /// This is only needed for the Options request that we are making right now. Eventually - /// we will use the Location Service and the Options request will not be needed and we can remove this. - /// - private const String c_optionsRelativePath = "_apis/"; - - private const String c_optionsRelativePathWithAllHostTypes = "_apis/?allHostTypes=true"; - - private const String c_jsonMediaType = "application/json"; - - public readonly static String UserStatePropertyName = "VssClientBaseUserState"; - - protected sealed class OperationScope : IDisposable - { - public OperationScope( - String area, - String operation) - { - m_area = area; - m_operation = operation; - m_activity = VssTraceActivity.GetOrCreate(); - m_correlationScope = m_activity.EnterCorrelationScope(); - VssHttpEventSource.Log.HttpOperationStart(m_activity, m_area, operation); - } - - public void Dispose() - { - if (!m_disposed) - { - m_disposed = true; - VssHttpEventSource.Log.HttpOperationStop(m_activity, m_area, m_operation); - - if (m_correlationScope != null) - { - m_correlationScope.Dispose(); - m_correlationScope = null; - } - } - } - - private String m_area; - private String m_operation; - private Boolean m_disposed; - private VssTraceActivity m_activity; - private IDisposable m_correlationScope; - } - - } -} diff --git a/src/Sdk/WebApi/WebApi/VssHttpUriUtility.cs b/src/Sdk/WebApi/WebApi/VssHttpUriUtility.cs deleted file mode 100644 index e3d6f8580..000000000 --- a/src/Sdk/WebApi/WebApi/VssHttpUriUtility.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Text; - -namespace GitHub.Services.WebApi -{ - public static class VssHttpUriUtility - { - /// - /// Replace values in a templated route with the given route values dictionary. - /// - /// - /// - /// Set true to escape the replaced route Uri string prior to returning it - /// Set true to append any unused routeValues as query parameters to the returned route - /// If set to true requires all the route parameters to be explicitly passed in routeParams - /// - public static String ReplaceRouteValues( - String routeTemplate, - Dictionary routeValues, - bool escapeUri = false, - bool appendUnusedAsQueryParams = false, - bool requireExplicitRouteParams = false) - { - RouteReplacementOptions routeReplacementOptions = escapeUri ? RouteReplacementOptions.EscapeUri : 0; - routeReplacementOptions |= appendUnusedAsQueryParams ? RouteReplacementOptions.AppendUnusedAsQueryParams : 0; - routeReplacementOptions |= requireExplicitRouteParams ? RouteReplacementOptions.RequireExplicitRouteParams : 0; - - return ReplaceRouteValues( - routeTemplate, - routeValues, - routeReplacementOptions); - } - - /// - /// Replace values in a templated route with the given route values dictionary. - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public static String ReplaceRouteValues( - String routeTemplate, - Dictionary routeValues, - RouteReplacementOptions routeReplacementOptions) - { - StringBuilder sbResult = new StringBuilder(); - StringBuilder sbCurrentPathPart = new StringBuilder(); - int paramStart = -1, paramLength = 0; - bool insideParam = false; - HashSet unusedValues = new HashSet(routeValues.Keys, StringComparer.OrdinalIgnoreCase); - Dictionary caseIncensitiveRouteValues = new Dictionary(routeValues, StringComparer.OrdinalIgnoreCase); - - for (int i = 0; i < routeTemplate.Length; i++) - { - char c = routeTemplate[i]; - - if (insideParam) - { - if (c == '}') - { - insideParam = false; - String paramName = routeTemplate.Substring(paramStart, paramLength); - paramLength = 0; - if (paramName.StartsWith("*")) - { - if (routeReplacementOptions.HasFlag(RouteReplacementOptions.WildcardAsQueryParams)) - { - continue; - } - // wildcard route - paramName = paramName.Substring(1); - } - - Object paramValue; - if (caseIncensitiveRouteValues.TryGetValue(paramName, out paramValue)) - { - if (paramValue != null) - { - sbCurrentPathPart.Append(paramValue.ToString()); - unusedValues.Remove(paramName); - } - } - else if (routeReplacementOptions.HasFlag(RouteReplacementOptions.RequireExplicitRouteParams)) - { - throw new ArgumentException("Missing route param " + paramName); - } - } - else - { - paramLength++; - } - } - else - { - if (c == '/') - { - if (sbCurrentPathPart.Length > 0) - { - sbResult.Append('/'); - sbResult.Append(sbCurrentPathPart.ToString()); - sbCurrentPathPart.Clear(); - } - } - else if (c == '{') - { - if ((i + 1) < routeTemplate.Length && routeTemplate[i + 1] == '{') - { - // Escaped '{' - sbCurrentPathPart.Append(c); - i++; - } - else - { - insideParam = true; - paramStart = i + 1; - } - } - else if (c == '}') - { - sbCurrentPathPart.Append(c); - if ((i + 1) < routeTemplate.Length && routeTemplate[i + 1] == '}') - { - // Escaped '}' - i++; - } - } - else - { - sbCurrentPathPart.Append(c); - } - } - } - - if (sbCurrentPathPart.Length > 0) - { - sbResult.Append('/'); - sbResult.Append(sbCurrentPathPart.ToString()); - } - - if (routeReplacementOptions.HasFlag(RouteReplacementOptions.EscapeUri)) - { - sbResult = new StringBuilder(Uri.EscapeUriString(sbResult.ToString())); - } - - if (routeReplacementOptions.HasFlag(RouteReplacementOptions.AppendUnusedAsQueryParams) && unusedValues.Count > 0) - { - bool isFirst = true; - - foreach (String paramName in unusedValues) - { - Object paramValue; - if (caseIncensitiveRouteValues.TryGetValue(paramName, out paramValue) && paramValue != null) - { - sbResult.Append(isFirst ? '?' : '&'); - isFirst = false; - sbResult.Append(Uri.EscapeDataString(paramName)); - sbResult.Append('='); - sbResult.Append(Uri.EscapeDataString(paramValue.ToString())); - } - } - } - - return sbResult.ToString(); - } - - /// - /// Create a route values dictionary, and add the specified area and resource if they aren't present. - /// - /// - /// Area name - /// Resource name - /// - public static Dictionary ToRouteDictionary(Object routeValues, string area, string resourceName) - { - Dictionary valuesDictionary = VssHttpUriUtility.ToRouteDictionary(routeValues); - VssHttpUriUtility.AddRouteValueIfNotPresent(valuesDictionary, "area", area); - VssHttpUriUtility.AddRouteValueIfNotPresent(valuesDictionary, "resource", resourceName); - - return valuesDictionary; - } - - public static Uri ConcatUri(Uri baseUri, String relativeUri) - { - StringBuilder sbCombined = new StringBuilder(baseUri.GetLeftPart(UriPartial.Path).TrimEnd('/')); - sbCombined.Append('/'); - sbCombined.Append(relativeUri.TrimStart('/')); - sbCombined.Append(baseUri.Query); - return new Uri(sbCombined.ToString()); - } - - public static Dictionary ToRouteDictionary(Object values) - { - if (values == null) - { - return new Dictionary(); - } - else if (values is Dictionary) - { - return (Dictionary)values; - } - else - { - Dictionary dictionary = new Dictionary(); - foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values)) - { - dictionary[descriptor.Name] = descriptor.GetValue(values); - } - return dictionary; - } - } - private static void AddRouteValueIfNotPresent(Dictionary dictionary, String key, Object value) - { - if (!dictionary.ContainsKey(key)) - { - dictionary.Add(key, value); - } - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - [Flags] - public enum RouteReplacementOptions - { - None = 0, - EscapeUri = 1, - AppendUnusedAsQueryParams = 2, - RequireExplicitRouteParams = 4, - WildcardAsQueryParams = 8, - } -} diff --git a/src/Sdk/WebApi/WebApi/VssJsonCollectionWrapper.cs b/src/Sdk/WebApi/WebApi/VssJsonCollectionWrapper.cs deleted file mode 100644 index e4a2365b6..000000000 --- a/src/Sdk/WebApi/WebApi/VssJsonCollectionWrapper.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections; -using System.Linq; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - - [DataContract] - public abstract class VssJsonCollectionWrapperBase : ISecuredObject - { - protected VssJsonCollectionWrapperBase() - { - } - - public VssJsonCollectionWrapperBase(IEnumerable source) - { - if (source == null) - { - this.Count = 0; - } - else if (source is ICollection) - { - this.Count = ((ICollection)source).Count; - } - else - { - this.Count = source.Cast().Count(); - } - this._value = source; - } - - [DataMember(Order=0)] - public Int32 Count { get; private set; } - - //not serialized from here, see sub class... - private IEnumerable _value; - - protected IEnumerable BaseValue - { - get - { - return _value; - } - set - { - _value = value; - } - } - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => throw new NotImplementedException(); - - int ISecuredObject.RequiredPermissions => throw new NotImplementedException(); - - string ISecuredObject.GetToken() => throw new NotImplementedException(); - #endregion - } - - [DataContract] - public sealed class VssJsonCollectionWrapper : VssJsonCollectionWrapperBase - { - public VssJsonCollectionWrapper() - : base() - { - } - public VssJsonCollectionWrapper(IEnumerable source) - : base(source) - { - } - - [DataMember(Order = 1)] - public IEnumerable Value - { - get - { - return BaseValue; - } - private set - { - BaseValue = value; - } - } - - } - - /// - /// This class is used to serialized collections as a single - /// JSON object on the wire, to avoid serializing JSON arrays - /// directly to the client, which can be a security hole - /// - /// - [DataContract] - public sealed class VssJsonCollectionWrapper : VssJsonCollectionWrapperBase - { - public VssJsonCollectionWrapper() - : base() - { - } - - public VssJsonCollectionWrapper(IEnumerable source) - :base (source) - { - } - - [DataMember] - public T Value - { - get - { - return (T)BaseValue; - } - private set - { - BaseValue = (IEnumerable)value; - } - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssJsonCreationConverter.cs b/src/Sdk/WebApi/WebApi/VssJsonCreationConverter.cs deleted file mode 100644 index 7c50ddbcb..000000000 --- a/src/Sdk/WebApi/WebApi/VssJsonCreationConverter.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Reflection; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace GitHub.Services.WebApi -{ - public abstract class VssJsonCreationConverter : VssSecureJsonConverter - where T : class - { - protected abstract T Create(Type objectType, JObject jsonObject); - - public override bool CanConvert(Type objectType) - { - return typeof(T).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo()); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType == JsonToken.Null) - { - return null; - } - - var jsonObject = JObject.Load(reader); - var target = Create(objectType, jsonObject); - serializer.Populate(jsonObject.CreateReader(), target); - return target; - } - - // fallback to default behavior for writes - public override bool CanWrite => false; - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssJsonMediaTypeFormatter.cs b/src/Sdk/WebApi/WebApi/VssJsonMediaTypeFormatter.cs deleted file mode 100644 index d4a711bfc..000000000 --- a/src/Sdk/WebApi/WebApi/VssJsonMediaTypeFormatter.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.Collections; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Formatting; -using System.Net.Http.Headers; -using System.Reflection; -using System.Runtime.Serialization; -using System.Threading.Tasks; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Patch; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json.Serialization; - -namespace GitHub.Services.WebApi -{ - /// - /// Constants related to JSON serialization customizations - /// - public static class VssJsonSerializationConstants - { - /// - /// Header which indicates to serialize enums as numbers. - /// - public const string EnumsAsNumbersHeader = "enumsAsNumbers"; - - /// - /// Header which indicates to serialize dates using the Microsoft Ajax date format - /// - public const string MsDateFormatHeader = "msDateFormat"; - - /// - /// Header which indicates to return a root array in a JSON response rather than wrapping it in an object - /// - public const string NoArrayWrapHeader = "noArrayWrap"; - } - - - public class VssJsonMediaTypeFormatter : JsonMediaTypeFormatter - { - /// - /// - /// - /// This should typically be false. A true value will cause the wrapping to be skipped which is neccesary when creating ObjectContent from arrays on client to prepare a request - public VssJsonMediaTypeFormatter(bool bypassSafeArrayWrapping = false) - : this(bypassSafeArrayWrapping, false, false) - { - } - - public VssJsonMediaTypeFormatter(bool bypassSafeArrayWrapping, bool enumsAsNumbers = false, bool useMsDateFormat = false) - { - this.SetSerializerSettings(bypassSafeArrayWrapping, enumsAsNumbers, useMsDateFormat); - } - - /// - /// - /// - /// This should typically be false. A true value will cause the wrapping to be skipped which is neccesary when creating ObjectContent from arrays on client to prepare a request - public VssJsonMediaTypeFormatter(HttpRequestMessage request, bool bypassSafeArrayWrapping = false) - { - Request = request; - SerializerSettings.Context = new StreamingContext(0, Request); - - bool enumsAsNumbers = String.Equals("true", GetAcceptHeaderOptionValue(request, VssJsonSerializationConstants.EnumsAsNumbersHeader), StringComparison.OrdinalIgnoreCase); - bool useMsDateFormat = String.Equals("true", GetAcceptHeaderOptionValue(request, VssJsonSerializationConstants.MsDateFormatHeader), StringComparison.OrdinalIgnoreCase); - if (!bypassSafeArrayWrapping) - { - // We can override the array-wrapping behavior based on a header. We haven't supported Firefox pre-2.0 in years, and even then the array prototype exploit - // is not possible if you have to send a custom header in the request to get a JSON array to be returned. - bypassSafeArrayWrapping = String.Equals("true", GetAcceptHeaderOptionValue(request, VssJsonSerializationConstants.NoArrayWrapHeader), StringComparison.OrdinalIgnoreCase); - } - - this.SetSerializerSettings(bypassSafeArrayWrapping, enumsAsNumbers, useMsDateFormat); - } - - private void SetSerializerSettings(bool bypassSafeArrayWrapping, bool enumsAsNumbers, bool useMsDateFormat) - { - this.SerializerSettings.ContractResolver = GetContractResolver(enumsAsNumbers); - - if (!enumsAsNumbers) - { - // Serialze enums as camelCased string values - this.SerializerSettings.Converters.Add(new StringEnumConverter { CamelCaseText = true }); - } - - if (useMsDateFormat) - { - this.SerializerSettings.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat; - } - - m_bypassSafeArrayWrapping = bypassSafeArrayWrapping; - - EnumsAsNumbers = enumsAsNumbers; - UseMsDateFormat = useMsDateFormat; - } - - protected virtual IContractResolver GetContractResolver(bool enumsAsNumbers) - { - if (enumsAsNumbers) - { - return new VssCamelCasePropertyNamesPreserveEnumsContractResolver(); - } - else - { - return new VssCamelCasePropertyNamesContractResolver(); - } - } - - protected HttpRequestMessage Request { get; private set; } - - /// - /// Whether or not to wrap a root array into an object with a "value" property equal to the array. - /// This protects against an old browser vulnerability (Firefox 2.0) around overriding the 'Array' - /// prototype and referencing a REST endpoint through in a script tag, and stealing the results - /// cross-origin. - /// - public Boolean BypassSafeArrayWrapping - { - get - { - return m_bypassSafeArrayWrapping; - } - set - { - m_bypassSafeArrayWrapping = value; - } - } - - /// - /// True if enums are serialized as numbers rather than user-friendly strings - /// - public Boolean EnumsAsNumbers { get; private set; } - - /// - /// True if dates are to be emitted using MSJSON format rather than ISO format. - /// - public Boolean UseMsDateFormat { get; private set; } - - public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, HttpRequestMessage request, MediaTypeHeaderValue mediaType) - { - if (GetType().Equals(typeof(VssJsonMediaTypeFormatter))) // ensures we don't return a VssJsonMediaTypeFormatter when this instance is not a VssJsonMediaTypeFormatter - { - return new VssJsonMediaTypeFormatter(request, m_bypassSafeArrayWrapping); - } - else - { - return base.GetPerRequestFormatterInstance(type, request, mediaType); // basically returns this instance - } - } - - private String GetAcceptHeaderOptionValue(HttpRequestMessage request, String acceptOptionName) - { - foreach (var header in request.Headers.Accept) - { - foreach (var parameter in header.Parameters) - { - if (String.Equals(parameter.Name, acceptOptionName, StringComparison.OrdinalIgnoreCase)) - { - return parameter.Value; - } - } - } - - return null; - } - - /// - /// Because JSON PATCH and JSON both use the JSON format, we explicitly are - /// blocking the default JSON formatter from being able to read the PATCH - /// format. - /// - public override bool CanReadType(Type type) - { - return !type.IsOfType(typeof(IPatchDocument<>)); - } - - public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext) - { - // Do not wrap byte arrays as this is incorrect behavior (they are written as base64 encoded strings and - // not as array objects like other types). - - Type typeToWrite = type; - if (!m_bypassSafeArrayWrapping - && typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo()) - && !type.Equals(typeof(Byte[])) - && !type.Equals(typeof(JObject))) - { - typeToWrite = typeof(VssJsonCollectionWrapper); - - // IEnumerable will need to be materialized if they are currently not. - object materializedValue = value is ICollection || value is string ? - value : // Use the regular input if it is already materialized or it is a string - ((IEnumerable)value)?.Cast().ToList() ?? value; // Otherwise, try materialize it - - value = new VssJsonCollectionWrapper((IEnumerable)materializedValue); - } - return base.WriteToStreamAsync(typeToWrite, value, writeStream, content, transportContext); - } - - private bool m_bypassSafeArrayWrapping; - } -} diff --git a/src/Sdk/WebApi/WebApi/VssRequestTimerTrace.cs b/src/Sdk/WebApi/WebApi/VssRequestTimerTrace.cs deleted file mode 100644 index 86826b0b3..000000000 --- a/src/Sdk/WebApi/WebApi/VssRequestTimerTrace.cs +++ /dev/null @@ -1,181 +0,0 @@ -using GitHub.Services.Common; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Runtime.InteropServices; - -namespace GitHub.Services.WebApi -{ - internal static class HttpMessageExtensions - { - private const string tracerKey = "VSS_HTTP_TIMER_TRACE"; - - internal static void Trace(this HttpRequestMessage request) - { - Object tracerObj = null; - VssRequestTimerTrace tracer = null; - if (request.Properties.TryGetValue(tracerKey, out tracerObj)) - { - tracer = tracerObj as VssRequestTimerTrace; - Debug.Assert(tracer != null, "Tracer object is the wrong type!"); - } - else - { - tracer = new VssRequestTimerTrace(); - request.Properties[tracerKey] = tracer; - } - - if (tracer != null) - { - tracer.TraceRequest(request); - } - } - - internal static void Trace(this HttpResponseMessage response) - { - Object tracerObj = null; - VssRequestTimerTrace tracer = null; - if (response.RequestMessage.Properties.TryGetValue(tracerKey, out tracerObj)) - { - tracer = tracerObj as VssRequestTimerTrace; - Debug.Assert(tracer != null, "Tracer object is the wrong type!"); - } - - if (tracer != null) - { - tracer.TraceResponse(response); - } - } - } - - // a little class to trace perf of web requests - // does nothing without TRACE set - internal class VssRequestTimerTrace - { - internal VssRequestTimerTrace() - { -#if TRACE - _requestTimer = new Stopwatch(); -#endif - } - internal void TraceRequest(HttpRequestMessage message) - { -#if TRACE - string requestString = message.GetRequestString(); - - VssPerformanceEventSource.Log.RESTStart(Guid.Empty, requestString); - _requestTimer.Start(); - -#if !NETSTANDARD - EventActivityIdControl(1, ref _activityId); -#endif -#endif - } - internal void TraceResponse(HttpResponseMessage response) - { -#if TRACE - _requestTimer.Stop(); - String responseString = response.GetResponseString(_requestTimer.ElapsedMilliseconds); - -#if !NETSTANDARD - VssPerformanceEventSource.Log.RESTStop(Guid.Empty, _activityId, responseString, _requestTimer.ElapsedMilliseconds); -#endif -#endif - } -#if TRACE - private Stopwatch _requestTimer; -#if !NETSTANDARD - private Guid _activityId; -#endif -#endif - -#if !NETSTANDARD - [DllImport("ADVAPI32.DLL", ExactSpelling = true, EntryPoint = "EventActivityIdControl")] - internal static extern uint EventActivityIdControl([In] int ControlCode, [In][Out] ref Guid ActivityId); -#endif - } - -#if TRACE - internal static class VssRequestLoggingExtensions - { - internal static String GetRequestString(this HttpRequestMessage message) - { - String verb, area, resource; - Guid vssE2EId; - - TryGetHeaderGuid(message.Headers, Common.Internal.HttpHeaders.VssE2EID, out vssE2EId); - - ExtractRequestStrings(message, out verb, out resource, out area); - - return String.Format(CultureInfo.InvariantCulture, _requestFormat, message.RequestUri.AbsoluteUri, verb, resource, area, vssE2EId); - } - - internal static String GetResponseString(this HttpResponseMessage response, long milliseconds) - { - String verb, area, resource; - Guid activityId = Guid.Empty, vssE2EId = Guid.Empty; - - ExtractRequestStrings(response.RequestMessage, out verb, out resource, out area); - - TryGetHeaderGuid(response.Headers, Common.Internal.HttpHeaders.VssE2EID, out vssE2EId); - TryGetHeaderGuid(response.Headers, Common.Internal.HttpHeaders.ActivityId, out activityId); - - return String.Format(CultureInfo.InvariantCulture, _responseFormat, response.RequestMessage.RequestUri.AbsoluteUri, verb, resource, area, vssE2EId, activityId, milliseconds); - } - - private static void ExtractRequestStrings(HttpRequestMessage message, out String verb, out String resource, out String area) - { - verb = message.Method.ToString().ToUpper(); - resource = _unknown; - area = _unknown; - - int segments = message.RequestUri.Segments.Length; - - if (segments > 0) - { - //if we did our REST APIs right the resource had better be the last - //segment. - resource = message.RequestUri.Segments[segments - 1].TrimEnd('/'); - } - - for (int i = 0; i < segments; i++) - { - //area should be the first segment after _apis - //some resources don't have an area, so it will be the same - //which is OK, we'll know what it means :) - if (String.Compare(message.RequestUri.Segments[i], _apis, StringComparison.OrdinalIgnoreCase) == 0) - { - if (segments > (i + 1)) - { - area = message.RequestUri.Segments[i + 1].TrimEnd('/'); - } - break; - } - } - } - - private static bool TryGetHeaderGuid(HttpHeaders headers, string key, out Guid value) - { - IEnumerable values; - value = Guid.Empty; - if (headers.TryGetValues(key, out values)) - { - return Guid.TryParse(values.FirstOrDefault(), out value); - } - - return false; - } - - //[URI] (VERB)RESOURCE[AREA] E2EId: E2EId - private const String _requestFormat = "Web method running: [{0}] ({1}){2}[{3}] E2EId: {4}"; - //[URI] (VERB)RESOURCE[AREA] E2EId: E2EId, ActivityId: ActivityId N ms - private const String _responseFormat = "Web method response: [{0}] ({1}){2}[{3}] E2EId: {4}, ActivityId: {5} {6} ms"; - private const String _unknown = ""; - private const String _apis = "_apis/"; - } -#endif -} diff --git a/src/Sdk/WebApi/WebApi/VssResponseContext.cs b/src/Sdk/WebApi/WebApi/VssResponseContext.cs deleted file mode 100644 index e3060f2f2..000000000 --- a/src/Sdk/WebApi/WebApi/VssResponseContext.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Net.Http.Headers; -using System.Text.RegularExpressions; -using GitHub.Services.Common; -using Newtonsoft.Json; - -namespace GitHub.Services.WebApi -{ - public class VssResponseContext - { - internal VssResponseContext(HttpStatusCode statusCode, HttpResponseHeaders headers) - { - if (headers.Contains(Common.Internal.HttpHeaders.ActivityId)) - { - IEnumerable values = headers.GetValues(Common.Internal.HttpHeaders.ActivityId); - string activityId = values.FirstOrDefault(); - Guid result; - Guid.TryParse(activityId, out result); - ActivityId = result; - } - - IEnumerable headerValues; - if (headers.TryGetValues(PerformanceTimerConstants.Header, out headerValues)) - { - Timings = JsonConvert.DeserializeObject>(headerValues.First()); - } - - HttpStatusCode = statusCode; - Headers = headers; - } - - public bool TryGetException(out Exception value) - { - value = Exception; - return Exception != null; - } - - public bool TryGetErrorCode(out string value) - { - value = null; - if (Exception == null) - { - return false; - } - var message = Exception.Message; - var match = Regex.Match(message, @"(TF[0-9]+)"); - if (match.Success) - { - value = match.Value; - return true; - } - match = Regex.Match(message, @"(VSS[0-9]+)"); - if (match.Success) - { - value = match.Value; - return true; - } - return false; - } - - public HttpStatusCode HttpStatusCode { get; private set; } - - public Guid ActivityId { get; private set; } - - public Exception Exception { get; internal set; } - - public IDictionary Timings { get; private set; } - - public HttpResponseHeaders Headers { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssSecureJsonConverter.cs b/src/Sdk/WebApi/WebApi/VssSecureJsonConverter.cs deleted file mode 100644 index 3280dfb6d..000000000 --- a/src/Sdk/WebApi/WebApi/VssSecureJsonConverter.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.ComponentModel; -using Newtonsoft.Json; -using Newtonsoft.Json.Converters; - -namespace GitHub.Services.WebApi -{ - public abstract class VssSecureJsonConverter : JsonConverter - { - public override abstract bool CanConvert(Type objectType); - - public override abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer); - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - Validate(value, serializer); - } - - private void Validate(object value, JsonSerializer serializer) - { - VssSecureJsonConverterHelper.Validate?.Invoke(value, serializer); - } - } - - public abstract class VssSecureCustomCreationConverter : CustomCreationConverter - { - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - Validate(value, serializer); - } - - private void Validate(object value, JsonSerializer serializer) - { - VssSecureJsonConverterHelper.Validate?.Invoke(value, serializer); - } - } - - public abstract class VssSecureDateTimeConverterBase : DateTimeConverterBase - { - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - Validate(value, serializer); - } - - private void Validate(object value, JsonSerializer serializer) - { - VssSecureJsonConverterHelper.Validate?.Invoke(value, serializer); - } - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public static class VssSecureJsonConverterHelper - { - /// - /// The action to validate the object being converted. - /// - public static Action Validate { get; set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssServiceResponseException.cs b/src/Sdk/WebApi/WebApi/VssServiceResponseException.cs deleted file mode 100644 index 473229514..000000000 --- a/src/Sdk/WebApi/WebApi/VssServiceResponseException.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Net; -using System.Runtime.Serialization; -using System.Security; -using GitHub.Services.Common; - -namespace GitHub.Services.WebApi -{ - [Serializable] - [SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors")] - [ExceptionMapping("0.0", "3.0", "VssServiceResponseException", "GitHub.Services.WebApi.VssServiceResponseException, GitHub.Services.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] - public class VssServiceResponseException : VssServiceException - { - public VssServiceResponseException(HttpStatusCode code, String message, Exception innerException) - : base(message, innerException) - { - this.HttpStatusCode = code; - } - - protected VssServiceResponseException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - HttpStatusCode = (HttpStatusCode)info.GetInt32("HttpStatusCode"); - } - - [SecurityCritical] - public override void GetObjectData(SerializationInfo info, StreamingContext context) - { - base.GetObjectData(info, context); - info.AddValue("HttpStatusCode", (int)HttpStatusCode); - } - - public HttpStatusCode HttpStatusCode { get; private set; } - } -} diff --git a/src/Sdk/WebApi/WebApi/VssSigningCredentials.cs b/src/Sdk/WebApi/WebApi/VssSigningCredentials.cs deleted file mode 100644 index 70c3ebf05..000000000 --- a/src/Sdk/WebApi/WebApi/VssSigningCredentials.cs +++ /dev/null @@ -1,490 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using GitHub.Services.Common; -using GitHub.Services.WebApi.Jwt; - -namespace GitHub.Services.WebApi -{ - /// - /// Provides a contract for signing, and verifying signatures of, blobs of data. - /// - public abstract class VssSigningCredentials - { - protected VssSigningCredentials() - { - m_effectiveDate = DateTime.UtcNow; - } - - /// - /// Gets a value indicating whether or not this token may be used to sign data. - /// - public abstract Boolean CanSignData - { - get; - } - - /// - /// Gets the size of the key, in bits, used for signing and verification. - /// - public abstract Int32 KeySize - { - get; - } - - /// - /// Gets the date from which this signing token is valid. - /// - public virtual DateTime ValidFrom - { - get - { - return m_effectiveDate; - } - } - - /// - /// Gets the datetime at which this signing token expires. - /// - public virtual DateTime ValidTo - { - get - { - return DateTime.MaxValue; - } - } - - /// - /// Gets the signature algorithm used by this signing token. - /// - public abstract JWTAlgorithm SignatureAlgorithm - { - get; - } - - /// - /// Signs the array with the signing key associated with the token. - /// - /// The data which should be signed - /// A blob of data representing the signature of the input data - /// Thrown when the current instance cannot be used for signing - public virtual Byte[] SignData(Byte[] input) - { - if (!CanSignData) - { - throw new InvalidOperationException(); - } - - return GetSignature(input); - } - - /// - /// Signs the array with the signing key associated with the token. - /// - /// The data which should be signed - /// A blob of data representing the signature of the input data - protected abstract Byte[] GetSignature(Byte[] input); - - /// - /// Verifies the signature of the input data, returning true if the signature is valid. - /// - /// The data which should be signed - /// The signature which should be verified - /// True if the provided signature matches the current signing token; otherwise, false - public abstract Boolean VerifySignature(Byte[] input, Byte[] signature); - - /// - /// Creates a new VssSigningCredentials instance using the specified instance - /// as the signing key. - /// - /// The certificate which contains the key used for signing and verification - /// A new VssSigningCredentials instance which uses the specified certificate for signing - public static VssSigningCredentials Create(X509Certificate2 certificate) - { - ArgumentUtility.CheckForNull(certificate, nameof(certificate)); - - if (certificate.HasPrivateKey) - { - -// Once we move the ClientObjectModelTargetFrameworkVersion to 4.6 we should remove the #else sections -// in this file. The NETSTANDARD sections should be the code for both NetStandard and desktop. 4.5 does -// not support these new cryptography classes, which is why we need these #ifs for now. -#if NETSTANDARD - var rsa = certificate.GetRSAPrivateKey(); - if (rsa == null) - { - throw new SignatureAlgorithmUnsupportedException(certificate.SignatureAlgorithm.FriendlyName); - } -#else - var rsa = certificate.PrivateKey as RSACryptoServiceProvider; - if (rsa == null) - { - throw new SignatureAlgorithmUnsupportedException(certificate.PrivateKey.SignatureAlgorithm); - } - - if (rsa.CspKeyContainerInfo.ProviderType != 24) - { - throw new SignatureAlgorithmUnsupportedException(rsa.CspKeyContainerInfo.ProviderType); - } -#endif - - if (rsa.KeySize < c_minKeySize) - { - throw new InvalidCredentialsException(JwtResources.SigningTokenKeyTooSmall()); - } - } - - return new X509Certificate2SigningToken(certificate); - } - -#if NETSTANDARD - /// - /// Creates a new VssSigningCredentials instance using the specified - /// callback function to retrieve the signing key. - /// - /// The factory which creates RSA keys used for signing and verification - /// A new VssSigningCredentials instance which uses the specified provider for signing - public static VssSigningCredentials Create(Func factory) - { - ArgumentUtility.CheckForNull(factory, nameof(factory)); - - using (var rsa = factory()) - { - if (rsa == null) - { - throw new InvalidCredentialsException(JwtResources.SignatureAlgorithmUnsupportedException("None")); - } - - if (rsa.KeySize < c_minKeySize) - { - throw new InvalidCredentialsException(JwtResources.SigningTokenKeyTooSmall()); - } - - return new RSASigningToken(factory, rsa.KeySize); - } - } -#else - /// - /// Creates a new VssSigningCredentials instance using the specified - /// callback function to retrieve the signing key. - /// - /// The factory which creates RSACryptoServiceProvider keys used for signing and verification - /// A new VssSigningCredentials instance which uses the specified provider for signing - public static VssSigningCredentials Create(Func factory) - { - ArgumentUtility.CheckForNull(factory, nameof(factory)); - - using (var rsa = factory()) - { - if (rsa == null) - { - throw new InvalidCredentialsException(JwtResources.SignatureAlgorithmUnsupportedException("None")); - } - - if (rsa.KeySize < c_minKeySize) - { - throw new InvalidCredentialsException(JwtResources.SigningTokenKeyTooSmall()); - } - - return new RSASigningToken(factory, rsa.KeySize); - } - } -#endif - - /// - /// Creates a new VssSigningCredentials instance using the specified as the signing - /// key. The returned signing token performs symmetric key signing and verification. - /// - /// The key used for signing and verification - /// A new VssSigningCredentials instance which uses the specified key for signing - public static VssSigningCredentials Create(Byte[] key) - { - ArgumentUtility.CheckForNull(key, nameof(key)); - - // Probably should have validation here, but there was none previously - return new SymmetricKeySigningToken(key); - } - - private const Int32 c_minKeySize = 2048; - private readonly DateTime m_effectiveDate; - -#region Concrete Implementations - - private class SymmetricKeySigningToken : VssSigningCredentials - { - public SymmetricKeySigningToken(Byte[] key) - { - m_key = new Byte[key.Length]; - Buffer.BlockCopy(key, 0, m_key, 0, m_key.Length); - } - - public override Boolean CanSignData - { - get - { - return true; - } - } - - public override Int32 KeySize - { - get - { - return m_key.Length * 8; - } - } - - public override JWTAlgorithm SignatureAlgorithm - { - get - { - return JWTAlgorithm.HS256; - } - } - - protected override Byte[] GetSignature(Byte[] input) - { - using (var hash = new HMACSHA256(m_key)) - { - return hash.ComputeHash(input); - } - } - - public override Boolean VerifySignature( - Byte[] input, - Byte[] signature) - { - var computedSignature = SignData(input); - return SecureCompare.TimeInvariantEquals(computedSignature, signature); - } - - private readonly Byte[] m_key; - } - - private abstract class AsymmetricKeySigningToken : VssSigningCredentials - { - protected abstract Boolean HasPrivateKey(); - - public override JWTAlgorithm SignatureAlgorithm - { - get - { - return JWTAlgorithm.RS256; - } - } - - public override Boolean CanSignData - { - get - { - if (m_hasPrivateKey == null) - { - m_hasPrivateKey = HasPrivateKey(); - } - return m_hasPrivateKey.Value; - } - } - - private Boolean? m_hasPrivateKey; - } - - private class X509Certificate2SigningToken : AsymmetricKeySigningToken, IJsonWebTokenHeaderProvider - { - public X509Certificate2SigningToken(X509Certificate2 certificate) - { - m_certificate = certificate; - } - - public override Int32 KeySize - { - get - { -#if NETSTANDARD - return m_certificate.GetRSAPublicKey().KeySize; -#else - return m_certificate.PublicKey.Key.KeySize; -#endif - } - } - - public override DateTime ValidFrom - { - get - { - return m_certificate.NotBefore; - } - } - - public override DateTime ValidTo - { - get - { - return m_certificate.NotAfter; - } - } - - public override Boolean VerifySignature( - Byte[] input, - Byte[] signature) - { -#if NETSTANDARD - var rsa = m_certificate.GetRSAPublicKey(); - return rsa.VerifyData(input, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); -#else - var rsa = m_certificate.PublicKey.Key as RSACryptoServiceProvider; - - using (var hash = SHA256CryptoServiceProvider.Create()) - { - return rsa.VerifyData(input, hash, signature); - } -#endif - } - - protected override Byte[] GetSignature(Byte[] input) - { -#if NETSTANDARD - var rsa = m_certificate.GetRSAPrivateKey(); - return rsa.SignData(input, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); -#else - var rsa = m_certificate.PrivateKey as RSACryptoServiceProvider; - - using (var hash = SHA256CryptoServiceProvider.Create()) - { - return rsa.SignData(input, hash); - } -#endif - } - - protected override Boolean HasPrivateKey() - { - return m_certificate.HasPrivateKey; - } - - void IJsonWebTokenHeaderProvider.SetHeaders(IDictionary headers) - { - headers[JsonWebTokenHeaderParameters.X509CertificateThumbprint] = m_certificate.GetCertHash().ToBase64StringNoPadding(); - } - - private readonly X509Certificate2 m_certificate; - } - -#if NETSTANDARD - private class RSASigningToken : AsymmetricKeySigningToken - { - public RSASigningToken( - Func factory, - Int32 keySize) - { - m_keySize = keySize; - m_factory = factory; - } - - public override Int32 KeySize - { - get - { - return m_keySize; - } - } - - protected override Byte[] GetSignature(Byte[] input) - { - using (var rsa = m_factory()) - { - return rsa.SignData(input, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - } - } - - protected override Boolean HasPrivateKey() - { - try - { - // As unfortunate as this is, there is no way to tell from an RSA implementation, based on querying - // properties alone, if it supports signature operations or has a private key. This is a one-time - // hit for the signing credentials implementation, so it shouldn't be a huge deal. - GetSignature(new Byte[1] { 1 }); - return true; - } - catch (CryptographicException) - { - return false; - } - } - - public override Boolean VerifySignature( - Byte[] input, - Byte[] signature) - { - using (var rsa = m_factory()) - { - return rsa.VerifyData(input, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); - } - } - - private readonly Int32 m_keySize; - private readonly Func m_factory; - } -#else - private class RSASigningToken : AsymmetricKeySigningToken - { - public RSASigningToken( - Func factory, - Int32 keySize) - { - m_keySize = keySize; - m_factory = factory; - } - - public override Int32 KeySize - { - get - { - return m_keySize; - } - } - - protected override Byte[] GetSignature(Byte[] input) - { - using (var rsa = m_factory()) - using (var hash = new SHA256CryptoServiceProvider()) - { - return rsa.SignData(input, hash); - } - } - - protected override Boolean HasPrivateKey() - { - try - { - // As unfortunate as this is, there is no way to tell from an RSA implementation, based on querying - // properties alone, if it supports signature operations or has a private key. This is a one-time - // hit for the signing credentials implementation, so it shouldn't be a huge deal. - GetSignature(new Byte[1] { 1 }); - return true; - } - catch (CryptographicException) - { - return false; - } - } - - public override Boolean VerifySignature( - Byte[] input, - Byte[] signature) - { - using (var rsa = m_factory()) - using (var hash = new SHA256CryptoServiceProvider()) - { - return rsa.VerifyData(input, hash, signature); - } - } - - private readonly Int32 m_keySize; - private readonly Func m_factory; - } -#endif - - #endregion - } -} diff --git a/src/Sdk/WebApi/WebApi/WrappedException.cs b/src/Sdk/WebApi/WebApi/WrappedException.cs deleted file mode 100644 index a202b0ea2..000000000 --- a/src/Sdk/WebApi/WebApi/WrappedException.cs +++ /dev/null @@ -1,621 +0,0 @@ -using GitHub.Services.Common; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Runtime.Serialization; - -namespace GitHub.Services.WebApi -{ - [DataContract(IsReference = true)] - public class WrappedException : ISecuredObject - { - public WrappedException() - { - } - - public WrappedException(Exception exception, Boolean includeErrorDetail, Version restApiVersion) - { - // if we have an AggregateException AND there is only one exception beneath it, let's use that - // exception here instead. for S2S calls, the exception coming in will be an Aggregate and will - // loose type information if only the Aggregate is returned to the caller. - if ((exception is AggregateException) && - (((AggregateException)exception).InnerExceptions != null) && - (((AggregateException)exception).Flatten().InnerExceptions.Count == 1)) - { - // take the first one - exception = ((AggregateException)exception).Flatten().InnerException; - } - - // Populate the Type, TypeName, and TypeKey properties. - Type type = exception.GetType(); - String typeName, typeKey; - - if (exception is VssServiceResponseException) - { - /* - * VssServiceResponseException takes an HttpStatusCode in its constructor which is - * not compatible with the WrappableConstructors. Its not necessary to persist the - * status code since it is bound to the response, so we just cast down to - * VssServiceException to avoid conflict when unwrapping - */ - // It is okay for VssServiceResponseExceptions to happen on the server during S2S scenarios. - // just do the translation -- don't Debug.Fail! - //Debug.Fail("Do not throw VssServiceResponseException from the server side."); - type = typeof(VssServiceException); - VssException.GetTypeNameAndKeyForExceptionType(type, restApiVersion, out typeName, out typeKey); - } - else if (exception is VssServiceException) - { - ((VssServiceException)exception).GetTypeNameAndKey(restApiVersion, out typeName, out typeKey); - } - else - { - // Fall back to the base implementation - VssException.GetTypeNameAndKeyForExceptionType(type, restApiVersion, out typeName, out typeKey); - } - - this.Type = type; - this.TypeName = typeName; - this.TypeKey = typeKey; - - if (includeErrorDetail && exception.InnerException != null) - { - InnerException = new WrappedException(exception.InnerException, includeErrorDetail, restApiVersion); - } - - Message = exception.Message; - - if (includeErrorDetail) - { - //if the exception was not thrown, it won't have a stack trace, so - //capture it here in that case. Skip last two frames, we don't want WrappedException - //or its caller on the stack. - StackTrace = exception.StackTrace ?? new StackTrace(2, true).ToString(); - } - - if (!string.IsNullOrWhiteSpace(exception.HelpLink)) - { - HelpLink = exception.HelpLink; - } - - if (exception is VssException) - { - EventId = ((VssException)exception).EventId; - ErrorCode = ((VssException)exception).ErrorCode; - } - - TryWrapCustomProperties(exception); - } - - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public Dictionary CustomProperties - { - get; - set; - } - - [DataMember] - public WrappedException InnerException { get; set; } - - public Exception UnwrappedInnerException { get; set; } - - [DataMember] - public String Message { get; set; } - - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public String HelpLink { get; set; } - - public Type Type - { - get - { - if (m_type == null) - { - //try to create the type from the TypeName - if (!String.IsNullOrEmpty(TypeName)) - { - m_type = LoadType(TypeName); - } - } - - return m_type; - } - - set - { - m_type = value; - } - } - - private Type m_type; - - private string m_typeName; - - [DataMember] - public String TypeName - { - get - { - return m_typeName; - } - - set - { - if (value.Contains("Microsoft.VisualStudio")) - { - m_typeName = value.Replace("Microsoft.VisualStudio", "GitHub"); - m_typeName = m_typeName.Substring(0, m_typeName.IndexOf(",")) + ", Sdk"; - } - else if (value.Contains("Microsoft.Azure.DevOps")) - { - m_typeName = value.Replace("Microsoft.Azure.DevOps", "GitHub"); - m_typeName = m_typeName.Substring(0, m_typeName.IndexOf(",")) + ", Sdk"; - } - else if (value.Contains("Microsoft.TeamFoundation")) - { - m_typeName = value.Replace("Microsoft.TeamFoundation", "GitHub"); - m_typeName = m_typeName.Substring(0, m_typeName.IndexOf(",")) + ", Sdk"; - } - else - { - m_typeName = value; - } - } - } - - [DataMember] - public String TypeKey - { - get; - set; - } - - [DataMember] - public int ErrorCode - { - get; - set; - } - - [DataMember] - public int EventId - { - get; - set; - } - - [DataMember(EmitDefaultValue = false, IsRequired = false)] - public string StackTrace - { - get; - set; - } - - public Exception Unwrap(IDictionary typeMapping) - { - Exception innerException = null; - if (InnerException != null) - { - innerException = InnerException.Unwrap(typeMapping); - UnwrappedInnerException = innerException; - } - - Exception exception = null; - - // if they have bothered to map type, use that first. - if (!String.IsNullOrEmpty(TypeKey)) - { - Type type; - if (typeMapping != null && typeMapping.TryGetValue(TypeKey, out type) || - baseTranslatedExceptions.TryGetValue(TypeKey, out type)) - { - try - { - this.Type = type; - exception = Activator.CreateInstance(this.Type, Message, innerException) as Exception; - } - catch (Exception) - { - // do nothing - } - } - } - - if (exception == null) - { - //no standard mapping, fallback to - exception = UnWrap(innerException); - } - - if (exception is VssException) - { - ((VssException)exception).EventId = this.EventId; - ((VssException)exception).ErrorCode = this.ErrorCode; - } - - if (exception == null && !String.IsNullOrEmpty(Message)) - { - // NOTE: We can get exceptions that we can't create, IE. SqlException, AzureExceptions. - // This is not a failure, we will just wrap the exception in a VssServiceException - // since the type is not available. - exception = new VssServiceException(Message, innerException); - } - - if (exception == null && !string.IsNullOrEmpty(TypeName)) - { - Debug.Assert(false, string.Format("Server exception cannot be resolved. Type name: {0}", TypeName)); - } - - if (exception != null - && !string.IsNullOrEmpty(HelpLink)) - { - exception.HelpLink = HelpLink; - } - - if (exception != null - && !string.IsNullOrEmpty(this.StackTrace)) - { - FieldInfo stackTraceField = typeof(Exception).GetTypeInfo().GetDeclaredField("_stackTraceString"); - if (stackTraceField != null && !stackTraceField.Attributes.HasFlag(FieldAttributes.Public) && !stackTraceField.Attributes.HasFlag(FieldAttributes.Static)) - { - stackTraceField.SetValue(exception, this.StackTrace); - } - } - - if (exception != null && exception.GetType() == this.Type) - { - TryUnWrapCustomProperties(exception); - } - - return exception; - } - - private Exception UnWrap(Exception innerException) - { - Exception exception = null; - if (this.Type != null) // m_type is typically null when this.Type getter is hit from here, so the LoadType method will get invoked here. - { - try - { - Object[] args = null; - - ConstructorInfo info = GetMatchingConstructor(new[] { typeof(WrappedException) }); - if (info != null) - { - // a constructor overload on an exception that takes a WrappedException, is useful - // in cases where the other constructors manipulate the string that we pass in, - // which we do not want to happen when unwrapping an exception. - args = new object[] { this }; - } - else - { - info = GetMatchingConstructor(new[] { typeof(String), typeof(Exception) }); - if (info != null) - { - args = new object[] { Message, innerException }; - } - else - { - //try just string - info = GetMatchingConstructor(new[] { typeof(String) }); - if (info != null) - { - args = new object[] { Message }; - } - else - { - //try default constructor - info = GetMatchingConstructor(new Type[0]); - } - } - } - if (info != null) - { - exception = info.Invoke(args) as Exception; - // only check exceptions that derive from VssExceptions, since we don't have control - // to make code changes to exceptions that we don't own. - Debug.Assert(!(exception is VssException) || exception.Message == Message, - "The unwrapped exception message does not match the original exception message.", - "Type: {0}{1}Expected: {2}{1}Actual: {3}{1}{1}This can happen if the exception has a contructor that manipulates the input string. You can work around this by creating a constructor that takes in a WrappedException which sets the message verbatim and optionally the inner exception.", - exception.GetType(), - Environment.NewLine, - Message, - exception.Message); - } - } - catch (Exception) - { } - } - return exception; - } - - private ConstructorInfo GetMatchingConstructor(params Type[] parameterTypes) - { - return this.Type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null); - } - - private static Type LoadType(String typeName) - { - // For rest api version < 3.0, the server transmits the fulllAssemblyQualifiedName of exception at time that version was initially released, - // which means normal loading will fail due to version mismatch, as the version will alwyas be <= 14.0.0.0. - // Example: typeName=GitHub.Core.WebApi.ProjectDoesNotExistWithNameException, GitHub.Core.WebApi, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - - // For rest api version >= 3.0 (dev15), it just sends an assembly qualified type name without Version and PublicKeyToken, so it is version agnostic. - // Example: typeName=GitHub.Core.WebApi.ProjectDoesNotExistWithNameException, GitHub.Core.WebApi - - // Order of precedence, - // 1. Standard .net type loading - // 2. Check exception mapping attributes for compat scenarios with older severs - // 3. If version 14 is specified in typeName, resolve assembly by switching to version 15 - // 4. Try and load, binary from same folder as this binary - - Type ret = null; - - //try normal loading first - try - { - ret = Type.GetType(typeName, false, true); - } - catch (Exception) - { - // GetType can still throw an exception despite sending in false for throwOnError - } - - if (ret == null) - { - // try and look up type mapping based on exception attributes. - ret = LookupExceptionAttributeMapping(typeName); - if (ret == null) - { - try - { - //probably assembly version is wrong - //fortunately, .NET provides an overload for just such an eventuality - //without forcing us to parse the string - ret = Type.GetType(typeName, - ResolveAssembly, - null, - false, - true); - } - catch (Exception) - { - //we swallow all exceptions, some can potentially - //still occur, like BadImageFormat, even with throwOnError=false above - } - } - } - return ret; - } - - private static Assembly ResolveAssembly(AssemblyName asmName) - { - //if we get here we are probably in a back compat scenario - //check the version of the asmName, and if it is 14.0, upgrade it to - //the same as this assembly version and try it - if (asmName.Version == null || asmName.Version.Major <= c_backCompatVer) - { - //create new instance, don't copy unknown params... - AssemblyName newName = new AssemblyName - { - Name = asmName.Name, - CultureInfo = asmName.CultureInfo - }; - // DEVNOTE: Do not tack-on the version information, instead let the - // assembly load without it so that it may resolve to the appropriate. - // Otherwise, translation down the stack may fail due to version mismatch - // and that end's up creating un-necessary retries on certain user defined exceptions. - // newName.Version = Assembly.GetExecutingAssembly().GetName().Version; - newName.SetPublicKeyToken(asmName.GetPublicKeyToken()); - - try - { - var ret = Assembly.Load(newName); - if (ret != null) - { - return ret; - } - } - catch (Exception) - { } - } - - //Next,we look in the same directory, add .dll to the name and do a "LoadFrom" just - //like in the AssemblyResolve event in other places - //the assembly should be in the same directory as this one. - string currentPath = Assembly.GetExecutingAssembly().Location; - if (!String.IsNullOrEmpty(currentPath)) - { - string fullPath = Path.Combine(Path.GetDirectoryName(currentPath), asmName.Name + ".dll"); - - if (File.Exists(fullPath)) - { - return Assembly.LoadFrom(fullPath); - } - } - return null; - } - - private const int c_backCompatVer = 14; - - private static Type LookupExceptionAttributeMapping(string typeName) - { - Type mappedType = null; - Tuple cacheEntry = null; - lock (syncObject) - { - if (!s_exceptionsWithAttributeMapping.TryGetValue(typeName, out cacheEntry)) - { - // if not in the cache, then we should update the cache and try again - UpdateExceptionAttributeMappingCache(); - s_exceptionsWithAttributeMapping.TryGetValue(typeName, out cacheEntry); - } - } - if (cacheEntry != null) - { - mappedType = cacheEntry.Item2; - } - return mappedType; - } - - /// - /// Loop through all types in all loaded assemblies that we haven't looked at yet, and cache ExceptionMappingAttribute data - /// - private static void UpdateExceptionAttributeMappingCache() - { - foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies().Where(a => !s_assembliesCheckedForExceptionMappings.Contains(a))) - { - if (DoesAssemblyQualify(assembly)) // only look at assemblies that match this binary's major version and public key token - { - try - { - - IEnumerable types; - try - { - // calling GetTypes has side effect of loading direct dependancies of the assembly. - types = assembly.GetTypes(); - } - catch (ReflectionTypeLoadException ex) - { - // if dependant assembly fails to load, we should still be able to get all the exceptions, since it would be unlikely, - // that an exception is referencing a type from the assembly that failed to load. - types = ex.Types.Where(t => t != null); - } - - foreach (TypeInfo typeInfo in types) - { - foreach (ExceptionMappingAttribute attribute in typeInfo.GetCustomAttributes()) - { - Tuple cachedValue; - - // Check if the TypeName already exists in cache and add it if not. if it does exist, update if it has a higher ExclusiveMaxApiVersion. - // (In theory an old exception could be mapped to more then one type in the case we want the latest server - // to send different older types to different versions of older clients. This method is used only on client when converting a type - // from an older server, so we want the latest mapping of the older type.) - if (!s_exceptionsWithAttributeMapping.TryGetValue(attribute.TypeName, out cachedValue) || attribute.ExclusiveMaxApiVersion > cachedValue.Item1) - { - s_exceptionsWithAttributeMapping[attribute.TypeName] = new Tuple(attribute.ExclusiveMaxApiVersion, typeInfo.AsType()); - } - } - } - } - catch (Exception) - { - // if for any reason we can't get the defined types, we don't want an exception here to mask the real exception. - } - } - s_assembliesCheckedForExceptionMappings.Add(assembly); // keep track of all assemblies we have either ruled out or cached mappings for, so we don't have to consider them again - } - } - - /// - /// Checks Assembly to see if it has the possibility to contain an ExceptionMappingAttribute. Does this by matching the Version and PublicKeyToken - /// with the current executing assembly. - /// - /// - /// - private static bool DoesAssemblyQualify(Assembly assembly) - { - if (s_currentAssemblyPublicKeyToken == null || s_currentAssemblyVersion == null) - { - // cache these so we don't have to recompute every time we check an assembly - AssemblyName thisAssemblyName = typeof(WrappedException).GetTypeInfo().Assembly.GetName(); - s_currentAssemblyPublicKeyToken = thisAssemblyName.GetPublicKeyToken(); - s_currentAssemblyVersion = thisAssemblyName.Version; - } - AssemblyName assemblyName = assembly.GetName(); - if (assemblyName.Version.Major != s_currentAssemblyVersion.Major) - { - return false; - } - byte[] assemblyPublicKeyToken = assemblyName.GetPublicKeyToken(); - - // Allow the test code public key token as well, because we have an L0 test which declares an exception - // that has ExceptionMappingAttribute. - return ArrayUtility.Equals(s_currentAssemblyPublicKeyToken, assemblyPublicKeyToken) || - ArrayUtility.Equals(s_testCodePublicKeyToken, assemblyPublicKeyToken); - } - - private static object syncObject = new Object(); - private static byte[] s_currentAssemblyPublicKeyToken = null; - private static Version s_currentAssemblyVersion = null; - private static HashSet s_assembliesCheckedForExceptionMappings = new HashSet(); - private static readonly byte[] s_testCodePublicKeyToken = new byte[] { 0x68, 0x9d, 0x5c, 0x3b, 0x19, 0xaa, 0xe6, 0x23 }; - - /// - /// Exception Attribute Mapping Cache. key = exception type name from a response, value = ExclusiveMaxApiVersion and the mapped Type for that type name - /// - private static Dictionary> s_exceptionsWithAttributeMapping = new Dictionary>(); - - private void TryWrapCustomProperties(Exception exception) - { - var customPropertiesWithDataMemberAttribute = GetCustomPropertiesInfo(); - - if (customPropertiesWithDataMemberAttribute.Any()) - { - this.CustomProperties = new Dictionary(); - } - - foreach (var customProperty in customPropertiesWithDataMemberAttribute) - { - try - { - this.CustomProperties.Add(customProperty.Name, customProperty.GetValue(exception)); - } - catch - { - // skip this property - } - } - } - - private void TryUnWrapCustomProperties(Exception exception) - { - if (this.CustomProperties != null) - { - foreach (var property in GetCustomPropertiesInfo()) - { - if (this.CustomProperties.ContainsKey(property.Name)) - { - try - { - var propertyValue = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(CustomProperties[property.Name]), property.PropertyType); - property.SetValue(exception, propertyValue); - } - catch - { - // skip this property - } - } - } - } - } - - private IEnumerable GetCustomPropertiesInfo() - { - return this.Type.GetTypeInfo().DeclaredProperties.Where(p => p.GetMethod.Attributes.HasFlag(MethodAttributes.Public) - && !p.GetMethod.Attributes.HasFlag(MethodAttributes.Static) - && p.CustomAttributes.Any(a => a.AttributeType.GetTypeInfo().IsAssignableFrom(typeof(DataMemberAttribute).GetTypeInfo()))); - } - - - #region ISecuredObject - Guid ISecuredObject.NamespaceId => throw new NotImplementedException(); - - int ISecuredObject.RequiredPermissions => throw new NotImplementedException(); - - string ISecuredObject.GetToken() => throw new NotImplementedException(); - #endregion - - // Exception translation rules which apply to all VssHttpClientBase subclasses - private static readonly IDictionary baseTranslatedExceptions = new Dictionary() - { - { "VssAccessCheckException", typeof(Security.AccessCheckException) } - }; - } -}