Skip to content

Commit

Permalink
First Checkin related to Roles
Browse files Browse the repository at this point in the history
  • Loading branch information
Pooja Adhikari committed Dec 20, 2018
1 parent 17bffda commit abd7fb0
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System.Diagnostics;

namespace Microsoft.Health.ControlPlane.Core.Features.Exceptions
{
public class RoleNotFoundException : ControlPlaneException
{
public RoleNotFoundException(string name)
: base(string.Format(Resources.RoleNotFound, name))
{
Debug.Assert(!string.IsNullOrEmpty(name), "Role identifier should not be empty");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Health.ControlPlane.Core.Features.Rbac;
using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;

namespace Microsoft.Health.ControlPlane.Core.Features.Persistence
{
Expand All @@ -14,5 +15,9 @@ public interface IControlPlaneDataStore
Task<IdentityProvider> GetIdentityProviderAsync(string name, CancellationToken cancellationToken);

Task<IdentityProvider> UpsertIdentityProviderAsync(IdentityProvider identityProvider, CancellationToken cancellationToken);

Task<Role> GetRoleAsync(string name, CancellationToken cancellationToken);

Task<Role> UpsertRoleAsync(Role role, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

using System.Threading;
using System.Threading.Tasks;
using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;

namespace Microsoft.Health.ControlPlane.Core.Features.Rbac
{
Expand All @@ -13,5 +14,9 @@ public interface IRbacService
Task<IdentityProvider> GetIdentityProviderAsync(string name, CancellationToken cancellationToken);

Task<IdentityProvider> UpsertIdentityProviderAsync(IdentityProvider identityProvider, CancellationToken cancellationToken);

Task<Role> GetRoleAsync(string name, CancellationToken cancellationToken);

Task<Role> UpsertRoleAsync(Role role, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading.Tasks;
using EnsureThat;
using Microsoft.Health.ControlPlane.Core.Features.Persistence;
using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;

namespace Microsoft.Health.ControlPlane.Core.Features.Rbac
{
Expand All @@ -30,5 +31,15 @@ public async Task<IdentityProvider> UpsertIdentityProviderAsync(IdentityProvider
{
return await _controlPlaneDataStore.UpsertIdentityProviderAsync(identityProvider, cancellationToken);
}

public async Task<Role> GetRoleAsync(string name, CancellationToken cancellationToken)
{
return await _controlPlaneDataStore.GetRoleAsync(name, cancellationToken);
}

public async Task<Role> UpsertRoleAsync(Role role, CancellationToken cancellationToken)
{
return await _controlPlaneDataStore.UpsertRoleAsync(role, cancellationToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles
{
[JsonConverter(typeof(StringEnumConverter))]
public enum ResourceAction
{
/// <summary>
/// Read
/// </summary>
[EnumMember(Value = "read")]
Read,

/// <summary>
/// Write
/// </summary>
[EnumMember(Value = "write")]
Write,

/// <summary>
/// HardDelete
/// </summary>
[EnumMember(Value = "hardDelete")]
HardDelete,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System.Collections.Generic;

namespace Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles
{
public class ResourcePermission
{
public ResourcePermission()
{
Actions = new List<ResourceAction>();
}

public ResourcePermission(IList<ResourceAction> resourceActions)
{
Actions = resourceActions;
}

public IList<ResourceAction> Actions { get; }
}
}
31 changes: 31 additions & 0 deletions src/Microsoft.Health.ControlPlane.Core/Features/Rbac/Roles/Role.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using System.Collections.Generic;
using Newtonsoft.Json;

namespace Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles
{
public class Role
{
[JsonConstructor]
protected Role()
{
}

public Role(string name, IList<ResourcePermission> resourcePermissions, string version)
{
Name = name;
ResourcePermissions = resourcePermissions;
Version = version;
}

public string Name { get; set; }

public virtual string Version { get; set; }

public IList<ResourcePermission> ResourcePermissions { get; internal set; } = new List<ResourcePermission>();
}
}
8 changes: 8 additions & 0 deletions src/Microsoft.Health.ControlPlane.Core/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.Health.ControlPlane.Core.Features.Exceptions;
using Microsoft.Health.ControlPlane.Core.Features.Persistence;
using Microsoft.Health.ControlPlane.Core.Features.Rbac;
using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;
using Microsoft.Health.ControlPlane.CosmosDb.Features.Storage.Rbac;
using Microsoft.Health.CosmosDb.Configs;
using Microsoft.Health.CosmosDb.Features.Storage;
Expand Down Expand Up @@ -59,6 +60,28 @@ public async Task<IdentityProvider> GetIdentityProviderAsync(string name, Cancel
return identityProvider.ToIdentityProvider();
}

public async Task<Role> GetRoleAsync(string name, CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(name, nameof(name));

var role = await GetSystemDocumentByIdAsync<CosmosRole>(name, CosmosRole.RolePartition, cancellationToken);
if (role == null)
{
throw new RoleNotFoundException(name);
}

return role.ToRole();
}

public async Task<Role> UpsertRoleAsync(Role role, CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(role, nameof(role));

var cosmosRole = new CosmosRole(role);
var resultRole = await UpsertSystemObjectAsync(cosmosRole, CosmosRole.RolePartition, cancellationToken);
return resultRole.ToRole();
}

public async Task<IdentityProvider> UpsertIdentityProviderAsync(IdentityProvider identityProvider, CancellationToken cancellationToken)
{
EnsureArg.IsNotNull(identityProvider, nameof(identityProvider));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;
using Microsoft.Health.CosmosDb.Features.Storage;
using Newtonsoft.Json;

namespace Microsoft.Health.ControlPlane.CosmosDb.Features.Storage.Rbac
{
public class CosmosRole : Role
{
internal const string RolePartition = "Role_";

public CosmosRole(Role role)
: base(role.Name, role.ResourcePermissions, role.Version)
{
ETag = $"\"{role.Version}\"";
}

[JsonConstructor]
protected CosmosRole()
{
}

[JsonProperty("id")]
public string Id => Name;

[JsonProperty("partitionKey")]
public string PartitionKey { get; } = RolePartition;

[JsonProperty("_etag")]
public string ETag { get; protected set; }

[JsonProperty(KnownDocumentProperties.IsSystem)]
public bool IsSystem { get; } = true;

public override string Version => ETag;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// -------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// -------------------------------------------------------------------------------------------------

using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;

namespace Microsoft.Health.ControlPlane.CosmosDb.Features.Storage.Rbac
{
public static class CosmosRoleExtensions
{
public static Role ToRole(this CosmosRole cosmosRole)
{
return new Role(
cosmosRole.Name,
cosmosRole.ResourcePermissions,
cosmosRole.ETag.Trim('"'));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Health.ControlPlane.Core.Features.Rbac;
using Microsoft.Health.ControlPlane.Core.Features.Rbac.Roles;

namespace Microsoft.Health.Fhir.Api.Controllers
{
// TODO: Remove before PR
[Route("Admin/IdentityProvider/")]
public class ControlPlaneController : Controller
{
private readonly IRbacService _rbacService;
Expand All @@ -26,12 +25,40 @@ public ControlPlaneController(IRbacService rbacService)
}

[HttpGet]
[Route("{IdentityProviderName}")]
[Route("Admin/IdentityProvider/{IdentityProviderName}")]
[AllowAnonymous]
public async Task<IActionResult> Index(string identityProviderName, CancellationToken cancellationToken)
{
var response = await _rbacService.GetIdentityProviderAsync(identityProviderName, cancellationToken);
return Ok(response);
}

[HttpGet]
[Route("Admin/Roles/{RoleName}")]
[AllowAnonymous]
public async Task<IActionResult> GetRole(string roleName, CancellationToken cancellationToken)
{
var response = await _rbacService.GetRoleAsync(roleName, cancellationToken);
return Ok(response);
}

[HttpPut]
[Route("Admin/Roles")]
[AllowAnonymous]
public async Task<IActionResult> UpdateRole([FromBody] Role role, CancellationToken cancellationToken)
{
var response = await _rbacService.UpsertRoleAsync(role, cancellationToken);
return Ok(response);
}


[HttpPost]
[Route("Admin/Roles")]
[AllowAnonymous]
public async Task<IActionResult> CreateRole([FromBody] Role role, CancellationToken cancellationToken)
{
var response = await _rbacService.UpsertRoleAsync(role, cancellationToken);
return Ok(response);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>netcoreapp2.1</TargetFramework>
<CodeAnalysisRuleSet>..\..\CustomAnalysisRules.ruleset</CodeAnalysisRuleSet>
<GeneratorProjectPath>..\..\tools\Microsoft.Health.Extensions.BuildTimeCodeGenerator\Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj</GeneratorProjectPath>
<LangVersion>7.3</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Health.Fhir.Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"UseStrictConformance": true
},
"Security": {
"Enabled": true,
"Enabled": false,
"Authentication": {
"Audience": null,
"Authority": "https://localhost:44348"
Expand Down

0 comments on commit abd7fb0

Please sign in to comment.