Merge pull request #7 from isaiahwilliams/dev

Corrected authentication issue with creating and deleting users.
This commit is contained in:
Isaiah Williams 2018-07-07 09:17:02 -05:00 коммит произвёл GitHub
Родитель ce5ab9f60b 6dbaab5598
Коммит 36e54da4a9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
11 изменённых файлов: 123 добавлений и 86 удалений

Просмотреть файл

@ -167,7 +167,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Controllers
token = await GetAccessTokenAsync( token = await GetAccessTokenAsync(
$"{Provider.Configuration.ActiveDirectoryEndpoint}/{model.CustomerId}").ConfigureAwait(false); $"{Provider.Configuration.ActiveDirectoryEndpoint}/{model.CustomerId}").ConfigureAwait(false);
using (ResourceManager manager = new ResourceManager(Provider, token.AccessToken)) using (AzureManagement manager = new AzureManagement(Provider, token.AccessToken))
{ {
await manager.ApplyTemplateAsync( await manager.ApplyTemplateAsync(
model.SubscriptionId, model.SubscriptionId,
@ -215,7 +215,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Controllers
token = await GetAccessTokenAsync( token = await GetAccessTokenAsync(
$"{Provider.Configuration.ActiveDirectoryEndpoint}/{customerId}").ConfigureAwait(false); $"{Provider.Configuration.ActiveDirectoryEndpoint}/{customerId}").ConfigureAwait(false);
using (ResourceManager manager = new ResourceManager(Provider, token.AccessToken)) using (AzureManagement manager = new AzureManagement(Provider, token.AccessToken))
{ {
groups = await manager.GetResourceGroupsAsync(subscriptionId).ConfigureAwait(false); groups = await manager.GetResourceGroupsAsync(subscriptionId).ConfigureAwait(false);
return Json(groups, JsonRequestBehavior.AllowGet); return Json(groups, JsonRequestBehavior.AllowGet);
@ -249,7 +249,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Controllers
token = await GetAccessTokenAsync( token = await GetAccessTokenAsync(
$"{Provider.Configuration.ActiveDirectoryEndpoint}/{customerId}").ConfigureAwait(false); $"{Provider.Configuration.ActiveDirectoryEndpoint}/{customerId}").ConfigureAwait(false);
using (ResourceManager manager = new ResourceManager(Provider, token.AccessToken)) using (AzureManagement manager = new AzureManagement(Provider, token.AccessToken))
{ {
deployments = await manager.GetDeploymentsAsync(subscriptionId, resourceGroupName).ConfigureAwait(false); deployments = await manager.GetDeploymentsAsync(subscriptionId, resourceGroupName).ConfigureAwait(false);

Просмотреть файл

@ -312,6 +312,7 @@
<Compile Include="App_Start\UnityConfig.cs" /> <Compile Include="App_Start\UnityConfig.cs" />
<Compile Include="App_Start\UnityMvcActivator.cs" /> <Compile Include="App_Start\UnityMvcActivator.cs" />
<Compile Include="Controllers\OfferController.cs" /> <Compile Include="Controllers\OfferController.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="Logic\IPartnerOperations.cs" /> <Compile Include="Logic\IPartnerOperations.cs" />
<Compile Include="Logic\PartnerOperations.cs" /> <Compile Include="Logic\PartnerOperations.cs" />
<Compile Include="Logic\TelemetryHandleErrorAttribute.cs" /> <Compile Include="Logic\TelemetryHandleErrorAttribute.cs" />
@ -382,7 +383,7 @@
</Compile> </Compile>
<Compile Include="Logic\Azure\AzureHealthEvent.cs" /> <Compile Include="Logic\Azure\AzureHealthEvent.cs" />
<Compile Include="Logic\Azure\IncidentEvent.cs" /> <Compile Include="Logic\Azure\IncidentEvent.cs" />
<Compile Include="Logic\Azure\ResourceManager.cs" /> <Compile Include="Logic\Azure\AzureManagement.cs" />
<Compile Include="Logic\HttpService.cs" /> <Compile Include="Logic\HttpService.cs" />
<Compile Include="Logic\CommunicationException.cs" /> <Compile Include="Logic\CommunicationException.cs" />
<Compile Include="Logic\Extensions.cs" /> <Compile Include="Logic\Extensions.cs" />
@ -477,6 +478,7 @@
<Content Include="Content\bootstrap-theme.min.css.map" /> <Content Include="Content\bootstrap-theme.min.css.map" />
<Content Include="Content\bootstrap-theme.css.map" /> <Content Include="Content\bootstrap-theme.css.map" />
<None Include="packages.config" /> <None Include="packages.config" />
<None Include="Properties\PublishProfiles\partnercenterexplorer - Web Deploy.pubxml" />
<None Include="Scripts\jquery-2.2.3.intellisense.js" /> <None Include="Scripts\jquery-2.2.3.intellisense.js" />
<Content Include="Scripts\ai.0.22.9-build00167.js" /> <Content Include="Scripts\ai.0.22.9-build00167.js" />
<Content Include="Scripts\ai.0.22.9-build00167.min.js" /> <Content Include="Scripts\ai.0.22.9-build00167.min.js" />

Просмотреть файл

@ -0,0 +1,9 @@

// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "This is requred function name.", Scope = "member", Target = "~M:Microsoft.Store.PartnerCenter.Explorer.MvcApplication.Application_Start")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "This function is called externally.", Scope = "member", Target = "~M:Microsoft.Store.PartnerCenter.Explorer.MvcApplication.Application_Start")]

Просмотреть файл

@ -1,5 +1,5 @@
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// <copyright file="ResourceManager.cs" company="Microsoft"> // <copyright file="AzureManagement.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved. // Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright> // </copyright>
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@ -20,7 +20,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic.Azure
/// Facilitates interactions with the Azure Resource Manager API. /// Facilitates interactions with the Azure Resource Manager API.
/// </summary> /// </summary>
/// <seealso cref="System.IDisposable" /> /// <seealso cref="System.IDisposable" />
public class ResourceManager : IDisposable public class AzureManagement : IDisposable
{ {
/// <summary> /// <summary>
/// Provides access to core services. /// Provides access to core services.
@ -38,7 +38,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic.Azure
private bool disposed; private bool disposed;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ResourceManager"/> class. /// Initializes a new instance of the <see cref="AzureManagement"/> class.
/// </summary> /// </summary>
/// <param name="provider">Provides access to core services.</param> /// <param name="provider">Provides access to core services.</param>
/// <param name="token">A valid JSON Web Token (JWT).</param> /// <param name="token">A valid JSON Web Token (JWT).</param>
@ -48,7 +48,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic.Azure
/// <exception cref="ArgumentNullException"> /// <exception cref="ArgumentNullException">
/// <paramref name="provider"/> is null. /// <paramref name="provider"/> is null.
/// </exception> /// </exception>
public ResourceManager(IExplorerProvider provider, string token) public AzureManagement(IExplorerProvider provider, string token)
{ {
provider.AssertNotNull(nameof(provider)); provider.AssertNotNull(nameof(provider));
token.AssertNotEmpty(nameof(token)); token.AssertNotEmpty(nameof(token));

Просмотреть файл

@ -9,6 +9,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Graph; using Graph;
using Models; using Models;
@ -21,6 +22,11 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
/// <seealso cref="IGraphClient" /> /// <seealso cref="IGraphClient" />
public class GraphClient : IGraphClient public class GraphClient : IGraphClient
{ {
/// <summary>
/// Static instance of the <see cref="HttpProvider" /> class.
/// </summary>
private static HttpProvider httpProvider = new HttpProvider(new HttpClientHandler(), false);
/// <summary> /// <summary>
/// Provides access to core services. /// Provides access to core services.
/// </summary> /// </summary>
@ -55,7 +61,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
this.customerId = customerId; this.customerId = customerId;
this.provider = provider; this.provider = provider;
client = new GraphServiceClient(new AuthenticationProvider(this.provider, customerId)); client = new GraphServiceClient(new AuthenticationProvider(this.provider, customerId), httpProvider);
} }
/// <summary> /// <summary>
@ -121,8 +127,8 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
if (customerId.Equals(provider.Configuration.PartnerCenterAccountId, StringComparison.InvariantCultureIgnoreCase)) if (customerId.Equals(provider.Configuration.PartnerCenterAccountId, StringComparison.InvariantCultureIgnoreCase))
{ {
groups = directoryGroups.CurrentPage.OfType<Group>().Where( groups = directoryGroups.CurrentPage.OfType<Group>().Where(
g => g.DisplayName.Equals("AdminAgents", StringComparison.InvariantCultureIgnoreCase) g => g.DisplayName.Equals("AdminAgents", StringComparison.InvariantCultureIgnoreCase)
|| g.DisplayName.Equals("HelpdeskAgents", StringComparison.InvariantCultureIgnoreCase) || g.DisplayName.Equals("HelpdeskAgents", StringComparison.InvariantCultureIgnoreCase)
|| g.DisplayName.Equals("SalesAgent", StringComparison.InvariantCultureIgnoreCase)).ToList(); || g.DisplayName.Equals("SalesAgent", StringComparison.InvariantCultureIgnoreCase)).ToList();
if (groups.Count > 0) if (groups.Count > 0)

Просмотреть файл

@ -48,12 +48,12 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
try try
{ {
using (HttpClient client = new HttpClient()) using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri))
{ {
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
response = await client.GetAsync(requestUri).ConfigureAwait(false); response = await client.SendAsync(request).ConfigureAwait(false);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {

Просмотреть файл

@ -13,8 +13,16 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic.Office
/// Represents a result from the Service Communication API. /// Represents a result from the Service Communication API.
/// </summary> /// </summary>
/// <typeparam name="T">Type return from the Service Communication API.</typeparam> /// <typeparam name="T">Type return from the Service Communication API.</typeparam>
internal class Result<T> public class Result<T>
{ {
/// <summary>
/// Initializes a new instance of the <see cref="Result{T}" /> class.
/// </summary>
public Result()
{
Value = new List<T>();
}
/// <summary> /// <summary>
/// Gets or sets the OData context. /// Gets or sets the OData context.
/// </summary> /// </summary>
@ -24,6 +32,6 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic.Office
/// <summary> /// <summary>
/// Gets or sets the value returned from the API. /// Gets or sets the value returned from the API.
/// </summary> /// </summary>
public List<T> Value { get; set; } public List<T> Value { get; }
} }
} }

Просмотреть файл

@ -294,7 +294,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
{ {
executionTime = DateTime.Now; executionTime = DateTime.Now;
correlationId = Guid.NewGuid(); correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false); operations = await GetUserOperationsAsync(correlationId).ConfigureAwait(false);
principal = new CustomerPrincipal(ClaimsPrincipal.Current); principal = new CustomerPrincipal(ClaimsPrincipal.Current);
@ -420,7 +420,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Logic
{ {
startTime = DateTime.Now; startTime = DateTime.Now;
correlationId = Guid.NewGuid(); correlationId = Guid.NewGuid();
operations = await GetAppOperationsAsync(correlationId).ConfigureAwait(false); operations = await GetUserOperationsAsync(correlationId).ConfigureAwait(false);
principal = new CustomerPrincipal(ClaimsPrincipal.Current); principal = new CustomerPrincipal(ClaimsPrincipal.Current);

Просмотреть файл

@ -48,7 +48,8 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Models
/// <summary> /// <summary>
/// Gets the usage location. /// Gets the usage location.
/// </summary> /// </summary>
public string UsageLocation => "US"; [Required]
public string UsageLocation { get; set; }
/// <summary> /// <summary>
/// Gets or sets the name of the user principal. /// Gets or sets the name of the user principal.

Просмотреть файл

@ -12,7 +12,7 @@ namespace Microsoft.Store.PartnerCenter.Explorer.Models
/// Represents an access token used to access Partner Center. /// Represents an access token used to access Partner Center.
/// </summary> /// </summary>
/// <seealso cref="IPartnerCredentials" /> /// <seealso cref="IPartnerCredentials" />
internal sealed class PartnerCenterToken : IPartnerCredentials public sealed class PartnerCenterToken : IPartnerCredentials
{ {
/// <summary> /// <summary>
/// Gets the expiry time in UTC for the token. /// Gets the expiry time in UTC for the token.

Просмотреть файл

@ -10,78 +10,89 @@
</div> </div>
@using (Ajax.BeginForm("Create", "Users", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, OnSuccess = "OnUserSuccessCallback", UpdateTargetId = "users" })) @using (Ajax.BeginForm("Create", "Users", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, OnSuccess = "OnUserSuccessCallback", UpdateTargetId = "users" }))
{ {
<fieldset> <fieldset>
<div class="row"> <div class="row">
&nbsp; &nbsp;
</div>
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
@Html.LabelFor(item => Model.DisplayName)
</div> </div>
<div class="row"> <div class="col-xs-5">
<div class="col-xs-3 col-xs-offset-1"> @Html.TextBoxFor(item => Model.DisplayName, new { @class = "form-control" })
@Html.LabelFor(item => Model.DisplayName)
</div>
<div class="col-xs-5">
@Html.TextBoxFor(item => Model.DisplayName, new { @class = "form-control" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => Model.DisplayName)
</div>
</div> </div>
<div class="row"> <div class="col-xs-3">
<div class="col-xs-3 col-xs-offset-1"> @Html.ValidationMessageFor(item => Model.DisplayName)
@Html.LabelFor(item => Model.FirstName)
</div>
<div class="col-xs-5">
@Html.TextBoxFor(item => Model.FirstName, new { @class = "form-control" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.FirstName)
</div>
</div> </div>
<div class="row"> </div>
<div class="col-xs-3 col-xs-offset-1"> <div class="row">
@Html.LabelFor(item => item.LastName) <div class="col-xs-3 col-xs-offset-1">
</div> @Html.LabelFor(item => Model.FirstName)
<div class="col-xs-5">
@Html.TextBoxFor(item => item.LastName, new { @class = "form-control" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.LastName)
</div>
</div> </div>
<div class="row"> <div class="col-xs-5">
<div class="col-xs-3 col-xs-offset-1"> @Html.TextBoxFor(item => Model.FirstName, new { @class = "form-control" })
@Html.LabelFor(item => item.UserPrincipalName)
</div>
<div class="col-xs-5">
@Html.TextBoxFor(item => item.UserPrincipalName, new { @class = "form-control" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.UserPrincipalName)
</div>
</div> </div>
<div class="row"> <div class="col-xs-3">
<div class="col-xs-3 col-xs-offset-1"> @Html.ValidationMessageFor(item => item.FirstName)
@Html.LabelFor(item => item.Password)
</div>
<div class="col-xs-5">
@Html.PasswordFor(item => item.Password, new { @class = "form-control", placeholder = "Password" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.Password)
</div>
</div> </div>
<div class="row"> </div>
<div class="col-xs-offset-1"> <div class="row">
<button type="button" class="btn btn-default" <div class="col-xs-3 col-xs-offset-1">
data-dismiss="modal"> @Html.LabelFor(item => item.LastName)
Cancel
</button>
<button type="submit" id="approve-btn"
class="btn btn-danger">
Create
</button>
</div>
</div> </div>
</fieldset> <div class="col-xs-5">
@Html.TextBoxFor(item => item.LastName, new { @class = "form-control" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.LastName)
</div>
</div>
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
@Html.LabelFor(item => item.UserPrincipalName)
</div>
<div class="col-xs-5">
@Html.TextBoxFor(item => item.UserPrincipalName, new { @class = "form-control" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.UserPrincipalName)
</div>
</div>
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
@Html.LabelFor(item => item.Password)
</div>
<div class="col-xs-5">
@Html.PasswordFor(item => item.Password, new { @class = "form-control", placeholder = "Password" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.Password)
</div>
</div>
<div class="row">
<div class="col-xs-3 col-xs-offset-1">
@Html.LabelFor(item => item.UsageLocation)
</div>
<div class="col-xs-5">
@Html.TextBoxFor(item => item.UsageLocation, new { @class = "form-control", placeholder = "US" })
</div>
<div class="col-xs-3">
@Html.ValidationMessageFor(item => item.UsageLocation)
</div>
</div>
<div class="row">
<div class="col-xs-offset-1">
<button type="button" class="btn btn-default"
data-dismiss="modal">
Cancel
</button>
<button type="submit" id="approve-btn"
class="btn btn-danger">
Create
</button>
</div>
</div>
</fieldset>
} }
@Scripts.Render("~/bundles/jqueryval") @Scripts.Render("~/bundles/jqueryval")