Skip to content

Commit

Permalink
Permission and roles (#11)
Browse files Browse the repository at this point in the history
* Add permission management

* Add role management
  • Loading branch information
itaihanski authored Mar 11, 2024
1 parent 5f78f0f commit 0e51344
Show file tree
Hide file tree
Showing 9 changed files with 584 additions and 1 deletion.
105 changes: 105 additions & 0 deletions Descope.Test/IntegrationTests/Management/PermissionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using Xunit;

namespace Descope.Test.Integration
{
public class PermissionTests
{
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();

[Fact]
public async Task Permission_CreateAndLoad()
{
string? name = null;
try
{
// Create a permission
name = Guid.NewGuid().ToString();
var desc = "desc";
await _descopeClient.Management.Permission.Create(name, desc);

// Load and compare
var loadedPermissions = await _descopeClient.Management.Permission.LoadAll();
var loadedPermission = loadedPermissions.Find(permission => permission.Name == name);
Assert.NotNull(loadedPermission);
Assert.Equal(loadedPermission.Description, desc);
}
finally
{
if (!string.IsNullOrEmpty(name))
{
try { await _descopeClient.Management.Permission.Delete(name); }
catch { }
}
}
}

[Fact]
public async Task Permission_UpdateAndSearch()
{
string? name = null;
string? updatedName = null;
try
{
// Create a permission
name = Guid.NewGuid().ToString();
string desc = "desc";
await _descopeClient.Management.Permission.Create(name, desc);
updatedName = name + "updated";

// Update and compare
await _descopeClient.Management.Permission.Update(name, updatedName);
// Load and compare
var loadedPermissions = await _descopeClient.Management.Permission.LoadAll();
var loadedPermission = loadedPermissions.Find(permission => permission.Name == updatedName);
var originalNamePermission = loadedPermissions.Find(permission => permission.Name == name);
Assert.Null(originalNamePermission);
Assert.NotNull(loadedPermission);
Assert.True(string.IsNullOrEmpty(loadedPermission.Description));
name = null;
}
finally
{
if (!string.IsNullOrEmpty(name))
{
try { await _descopeClient.Management.Permission.Delete(name); }
catch { }
}
if (!string.IsNullOrEmpty(updatedName))
{
try { await _descopeClient.Management.Permission.Delete(updatedName); }
catch { }
}
}
}

[Fact]
public async Task Permission_DeleteAndLoadAll()
{
string? name = null;
try
{
// Create a permission
name = Guid.NewGuid().ToString();
await _descopeClient.Management.Permission.Create(name);

// Delete it
await _descopeClient.Management.Permission.Delete(name);
name = null;

// Load all and make sure it's gone
var loadedPermissions = await _descopeClient.Management.Permission.LoadAll();
var loadedPermission = loadedPermissions.Find(permission => permission.Name == name);
Assert.Null(loadedPermission);
}
finally
{
if (!string.IsNullOrEmpty(name))
{
try { await _descopeClient.Management.Permission.Delete(name); }
catch { }
}
}
}
}

}
105 changes: 105 additions & 0 deletions Descope.Test/IntegrationTests/Management/RoleTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using Xunit;

namespace Descope.Test.Integration
{
public class RoleTests
{
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();

[Fact]
public async Task Role_CreateAndLoad()
{
string? name = null;
try
{
// Create a role
name = Guid.NewGuid().ToString();
var desc = "desc";
await _descopeClient.Management.Role.Create(name, desc);

// Load and compare
var loadedRoles = await _descopeClient.Management.Role.LoadAll();
var loadedRole = loadedRoles.Find(role => role.Name == name);
Assert.NotNull(loadedRole);
Assert.Equal(loadedRole.Description, desc);
}
finally
{
if (!string.IsNullOrEmpty(name))
{
try { await _descopeClient.Management.Role.Delete(name); }
catch { }
}
}
}

[Fact]
public async Task Role_UpdateAndSearch()
{
string? name = null;
string? updatedName = null;
try
{
// Create a role
name = Guid.NewGuid().ToString();
string desc = "desc";
await _descopeClient.Management.Role.Create(name, desc);
updatedName = name + "updated";

// Update and compare
await _descopeClient.Management.Role.Update(name, updatedName);
// Load and compare
var foundRoles = await _descopeClient.Management.Role.SearchAll(new RoleSearchOptions { RoleNames = new List<string> { updatedName } });
var role = foundRoles.Find(role => role.Name == updatedName);
Assert.NotNull(role);
Assert.True(string.IsNullOrEmpty(role.Description));
foundRoles = await _descopeClient.Management.Role.SearchAll(new RoleSearchOptions { RoleNames = new List<string> { name } });
role = foundRoles.Find(role => role.Name == name);
Assert.Null(role);
name = null;
}
finally
{
if (!string.IsNullOrEmpty(name))
{
try { await _descopeClient.Management.Role.Delete(name); }
catch { }
}
if (!string.IsNullOrEmpty(updatedName))
{
try { await _descopeClient.Management.Role.Delete(updatedName); }
catch { }
}
}
}

[Fact]
public async Task Role_DeleteAndLoadAll()
{
string? name = null;
try
{
// Create a role
name = Guid.NewGuid().ToString();
await _descopeClient.Management.Role.Create(name);

// Delete it
await _descopeClient.Management.Role.Delete(name);
name = null;

// Load all and make sure it's gone
var loadedRoles = await _descopeClient.Management.Role.LoadAll();
var loadedRole = loadedRoles.Find(role => role.Name == name);
Assert.Null(loadedRole);
}
finally
{
if (!string.IsNullOrEmpty(name))
{
try { await _descopeClient.Management.Role.Delete(name); }
catch { }
}
}
}
}
}
19 changes: 19 additions & 0 deletions Descope/Internal/Http/Routes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,25 @@ public static class Routes

#endregion AccessKey

#region Permission

public const string PermissionCreate = "/v1/mgmt/permission/create";
public const string PermissionUpdate = "/v1/mgmt/permission/update";
public const string PermissionDelete = "/v1/mgmt/permission/delete";
public const string PermissionLoadAll = "/v1/mgmt/permission/all";

#endregion Permission

#region Role

public const string RoleCreate = "/v1/mgmt/role/create";
public const string RoleUpdate = "/v1/mgmt/role/update";
public const string RoleDelete = "/v1/mgmt/role/delete";
public const string RoleLoadAll = "/v1/mgmt/role/all";
public const string RoleSearchAll = "/v1/mgmt/role/search";

#endregion Role

#region Project

public const string ProjectExport = "/v1/mgmt/project/export";
Expand Down
6 changes: 6 additions & 0 deletions Descope/Internal/Management/Managment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@ internal class Management : IManagement
public ITenant Tenant => _tenant;
public IUser User => _user;
public IAccessKey AccessKey => _accessKey;
public IPermission Permission => _permission;
public IRole Role => _role;
public IProject Project => _project;

private readonly Tenant _tenant;
private readonly User _user;
private readonly AccessKey _accessKey;
private readonly Permission _permission;
private readonly Role _role;
private readonly Project _project;

public Management(IHttpClient client, string managementKey)
{
_tenant = new Tenant(client, managementKey);
_user = new User(client, managementKey);
_accessKey = new AccessKey(client, managementKey);
_permission = new Permission(client, managementKey);
_role = new Role(client, managementKey);
_project = new Project(client, managementKey);
}
}
Expand Down
55 changes: 55 additions & 0 deletions Descope/Internal/Management/Permission.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Text.Json.Serialization;

namespace Descope.Internal.Management
{
internal class Permission : IPermission
{
private readonly IHttpClient _httpClient;
private readonly string _managementKey;

internal Permission(IHttpClient httpClient, string managementKey)
{
_httpClient = httpClient;
_managementKey = managementKey;
}

public async Task Create(string name, string? description = null)
{
if (string.IsNullOrEmpty(name)) throw new DescopeException("name is required for creation");
var body = new { name, description };
await _httpClient.Post<object>(Routes.PermissionCreate, _managementKey, body);
}

public async Task Update(string name, string newName, string? description = null)
{
if (string.IsNullOrEmpty(name)) throw new DescopeException("name is required for update");
if (string.IsNullOrEmpty(newName)) throw new DescopeException("new name cannot be updated to empty");
var body = new { name, newName, description };
await _httpClient.Post<object>(Routes.PermissionUpdate, _managementKey, body);
}

public async Task Delete(string name)
{
if (string.IsNullOrEmpty(name)) throw new DescopeException("name is required for deletion");
var body = new { name };
await _httpClient.Post<object>(Routes.PermissionDelete, _managementKey, body);
}

public async Task<List<PermissionResponse>> LoadAll()
{
var permissionList = await _httpClient.Get<PermissionListResponse>(Routes.PermissionLoadAll, _managementKey);
return permissionList.Permissions;
}
}

internal class PermissionListResponse
{
[JsonPropertyName("permissions")]
public List<PermissionResponse> Permissions { get; set; }

public PermissionListResponse(List<PermissionResponse> permissions)
{
Permissions = permissions;
}
}
}
61 changes: 61 additions & 0 deletions Descope/Internal/Management/Role.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System.Text.Json.Serialization;

namespace Descope.Internal.Management
{
internal class Role : IRole
{
private readonly IHttpClient _httpClient;
private readonly string _managementKey;

internal Role(IHttpClient httpClient, string managementKey)
{
_httpClient = httpClient;
_managementKey = managementKey;
}

public async Task Create(string name, string? description = null, List<string>? permissionNames = null, string? tenantId = null)
{
if (string.IsNullOrEmpty(name)) throw new DescopeException("name is required for creation");
var body = new { name, description, permissionNames, tenantId };
await _httpClient.Post<object>(Routes.RoleCreate, _managementKey, body);
}

public async Task Update(string name, string newName, string? description = null, List<string>? permissionNames = null, string? tenantId = null)
{
if (string.IsNullOrEmpty(name)) throw new DescopeException("name is required for update");
if (string.IsNullOrEmpty(newName)) throw new DescopeException("new name cannot be updated to empty");
var body = new { name, newName, description, permissionNames, tenantId };
await _httpClient.Post<object>(Routes.RoleUpdate, _managementKey, body);
}

public async Task Delete(string name, string? tenantId)
{
if (string.IsNullOrEmpty(name)) throw new DescopeException("name is required for deletion");
var body = new { name, tenantId };
await _httpClient.Post<object>(Routes.RoleDelete, _managementKey, body);
}

public async Task<List<RoleResponse>> LoadAll()
{
var roleList = await _httpClient.Get<RoleListResponse>(Routes.RoleLoadAll, _managementKey);
return roleList.Roles;
}

public async Task<List<RoleResponse>> SearchAll(RoleSearchOptions? options)
{
var roleList = await _httpClient.Post<RoleListResponse>(Routes.RoleSearchAll, _managementKey, options);
return roleList.Roles;
}
}

internal class RoleListResponse
{
[JsonPropertyName("roles")]
public List<RoleResponse> Roles { get; set; }

public RoleListResponse(List<RoleResponse> roles)
{
Roles = roles;
}
}
}
Loading

0 comments on commit 0e51344

Please sign in to comment.