Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -903,9 +903,6 @@ public async Task<IActionResult> UpdateInstanceRights(
[FromBody] RightKeyListDto updateDto,
CancellationToken cancellationToken = default)
{
return NotFound();

/* ToDo: Implement instance support in connection service and uncomment code below when ready. Currently we return the same result as UpdateResourceRights, but with the intention to include instance information in the result once supported in connection service.
var byId = AuthenticationHelper.GetPartyUuid(HttpContext);
var fromEntity = await EntityService.GetEntity(party, cancellationToken);
var toEntity = await EntityService.GetEntity(to, cancellationToken);
Expand All @@ -928,7 +925,6 @@ public async Task<IActionResult> UpdateInstanceRights(
}

return Ok();
*/
}

/// <summary>
Expand All @@ -950,18 +946,13 @@ public async Task<IActionResult> RemoveInstance(
[Required][FromQuery(Name = "instance")] string instance,
CancellationToken cancellationToken = default)
{
return NotFound();

/* ToDo: Implement instance support in connection service and uncomment code below when ready. Currently we return the same result as RemoveResources, but with the intention to include instance information in the result once supported in connection service.
var byId = AuthenticationHelper.GetPartyUuid(HttpContext);
var problem = await ConnectionService.RemoveInstance(from, to, resource, instance, ConfigureConnections, cancellationToken);
if (problem is { })
{
return problem.ToActionResult();
}

return NoContent();
*/
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@

public async Task<List<InstanceRule>> TryWriteInstanceDelegationPolicyRules(Entity from, Entity to, Resource resource, string instanceId, List<string> ruleKeys, Entity performedBy, bool ignoreExistingPolicy = false, CancellationToken cancellationToken = default)
{
var instanceRules = await GenerateInstanceRules(resource, instanceId, ruleKeys, cancellationToken);
var instanceRules = await GenerateInstanceRules(from, to, resource, instanceId, ruleKeys, performedBy, cancellationToken);

var instanceRight = new InstanceRight
{
Expand Down Expand Up @@ -208,7 +208,7 @@
return rules;
}

private async Task<List<InstanceRule>> GenerateInstanceRules(Resource resource, string instanceId, List<string> ruleKeys, CancellationToken cancellationToken = default)
private async Task<List<InstanceRule>> GenerateInstanceRules(Entity from, Entity to, Resource resource, string instanceId, List<string> ruleKeys, Entity performedBy, CancellationToken cancellationToken = default)

Check warning on line 211 in src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/SingleRightsService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Remove this unused method parameter 'to'.

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qXFiX5OK5Qm2bT5&open=AZz75qXFiX5OK5Qm2bT5&pullRequest=2522

Check warning on line 211 in src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/SingleRightsService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Remove this unused method parameter 'from'.

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qXEiX5OK5Qm2bT4&open=AZz75qXEiX5OK5Qm2bT4&pullRequest=2522

Check warning on line 211 in src/apps/Altinn.AccessManagement/src/Altinn.AccessManagement.Core/Services/SingleRightsService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Remove this unused method parameter 'performedBy'.

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qXFiX5OK5Qm2bT6&open=AZz75qXFiX5OK5Qm2bT6&pullRequest=2522
{
List<InstanceRule> instanceRules = [];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Text;

Check warning on line 3 in src/apps/Altinn.AccessManagement/src/Altinn.AccessMgmt.Core/Services/ConnectionService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Using directives should be ordered alphabetically by the namespaces

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz78J5SX68zK3457N9o&open=AZz78J5SX68zK3457N9o&pullRequest=2522
using System.Linq;
using Altinn.AccessManagement.Core.Clients.Interfaces;
using Altinn.AccessManagement.Core.Enums.ResourceRegistry;
using Altinn.AccessManagement.Core.Errors;
Expand Down Expand Up @@ -1010,13 +1011,12 @@
List<Models.Right> rights = DelegationCheckHelper.DecomposePolicy(policy, resource);

var packages = await CheckPackageForResource(party, authenticatedUserUuid, null, configureConnection, cancellationToken);
bool isMainAdminForFrom = packages.Value.Any(p => p.Result && p.Package.Id == PackageConstants.MainAdministrator.Id);
bool isMainAdminForFrom = packages.Value.Any(p => p.Result == true && p.Package.Id == PackageConstants.MainAdministrator.Id);

Check warning on line 1014 in src/apps/Altinn.AccessManagement/src/Altinn.AccessMgmt.Core/Services/ConnectionService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Remove the unnecessary Boolean literal(s).

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qV_iX5OK5Qm2bTz&open=AZz75qV_iX5OK5Qm2bTz&pullRequest=2522

var roles = await RoleDelegationCheck(party, authenticatedUserUuid, isMainAdminForFrom, cancellationToken);
var resources = await GetResourceRights(party, authenticatedUserUuid, resourceDto.Id, null, cancellationToken);
var instances = await GetInstanceRights(party, authenticatedUserUuid, resourceDto.Id, instanceId, RoleConstants.Rightholder, cancellationToken);

ProcessTheAccessToTheRightKeys(rights, packages.Value, roles.Value, resources, instances);
ProcessTheAccessToTheRightKeys(rights, packages.Value, roles.Value, resources);

// Map to result
IEnumerable<RightCheckDto> checkRights = await MapFromInternalToExternalRights(rights, resource, accessListMode, fromParty, rightKeys, isResourceDelegable, isMaskinPortenSchema, cancellationToken);
Expand Down Expand Up @@ -1219,9 +1219,12 @@
return canDelegate.Problem;
}

if (rightKeys.DirectRightKeys.Any(rightKey => !canDelegate.Value.Rights.Any(a => a.Right.Key == rightKey && a.Result)))
foreach (var rightKey in rightKeys.DirectRightKeys)

Check warning on line 1222 in src/apps/Altinn.AccessManagement/src/Altinn.AccessMgmt.Core/Services/ConnectionService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Loops should be simplified using the "Where" LINQ method

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qV_iX5OK5Qm2bT1&open=AZz75qV_iX5OK5Qm2bT1&pullRequest=2522
{
return Problems.NotAuthorizedForDelegationRequest;
if (!canDelegate.Value.Rights.Any(a => a.Right.Key == rightKey && a.Result))
{
return Problems.NotAuthorizedForDelegationRequest;
}
}

var connection = await Get(from.Id, from.Id, to.Id, configureConnections: configureConnection, cancellationToken: cancellationToken);
Expand All @@ -1240,6 +1243,89 @@
return true;
}

public async Task<Result<bool>> UpdateInstance(Entity from, Entity to, Resource resourceObj, string instanceId, IEnumerable<string> rightKeys, Entity by, Action<ConnectionOptions> configureConnection = null, CancellationToken cancellationToken = default)
{
var canDelegate = await InstanceDelegationCheck(by.Id, from.Id, resourceObj?.RefId, instanceId, ConfigureConnections, cancellationToken: cancellationToken);
if (canDelegate.IsProblem)
{
Comment on lines +1246 to +1250
return canDelegate.Problem;
}

foreach (var rightKey in rightKeys)

Check warning on line 1254 in src/apps/Altinn.AccessManagement/src/Altinn.AccessMgmt.Core/Services/ConnectionService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Loops should be simplified using the "Where" LINQ method

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qV_iX5OK5Qm2bT2&open=AZz75qV_iX5OK5Qm2bT2&pullRequest=2522
{
if (!canDelegate.Value.Rights.Any(a => a.Right.Key == rightKey && a.Result))
{
return Problems.NotAuthorizedForDelegationRequest;
}
}

List<InstanceRule> result = await singleRightsService.TryWriteInstanceDelegationPolicyRules(from, to, resourceObj, instanceId, rightKeys.ToList(), by, ignoreExistingPolicy: true, cancellationToken: cancellationToken);
Comment on lines +1254 to +1262

if (!result.All(r => r.CreatedSuccessfully))
{
return Problems.DelegationPolicyRuleWriteFailed;
}

return true;
}

public async Task<ValidationProblemInstance> RemoveInstance(Guid fromId, Guid toId, string resource, string instanceId, Action<ConnectionOptions> configureConnection = null, CancellationToken cancellationToken = default)
{
var resourceObj = await dbContext.Resources.AsNoTracking().FirstOrDefaultAsync(t => t.RefId == resource, cancellationToken);
if (resourceObj == null)
{
return null;
}
Comment on lines +1274 to +1278

var options = new ConnectionOptions(configureConnection);
var (from, to) = await GetFromAndToEntities(fromId, toId, cancellationToken);
var problem = ValidateWriteOpInput(from, to, options);
if (problem is { })
{
return problem;
}

var assignment = await dbContext.Assignments
.AsNoTracking()
.Include(a => a.From)
.Include(a => a.To)
.Where(a => a.FromId == fromId)
.Where(a => a.ToId == toId)
.Where(a => a.RoleId == RoleConstants.Rightholder)
.FirstOrDefaultAsync(cancellationToken);

if (assignment is null)
{
return null;
}

problem = ValidateWriteOpInput(assignment.From, assignment.To, options);
if (problem is { })
{
return problem;
}

var existingAssignmentInstance = await dbContext.AssignmentInstances
.AsTracking()
.Where(a => a.AssignmentId == assignment.Id)
.Where(a => a.ResourceId == resourceObj.Id)
.Where(a => a.InstanceId == instanceId)
.FirstOrDefaultAsync(cancellationToken);

if (existingAssignmentInstance is null)
{
return null;
}

var newVersion = await singleRightsService.ClearPolicyRules(existingAssignmentInstance.PolicyPath, existingAssignmentInstance.PolicyVersion, cancellationToken);
existingAssignmentInstance.PolicyVersion = newVersion;

dbContext.Remove(existingAssignmentInstance);
await dbContext.SaveChangesAsync(cancellationToken);

return null;
}

private void ProcessRoleAllowAccessReasons(List<RoleDtoCheck> rolesAllowAccess, List<RightCheckDto.Permision> permisions)
{
if (rolesAllowAccess.Count > 0)
Expand Down Expand Up @@ -2017,7 +2103,6 @@
PolicyVersion = t.PolicyVersion,
Reason = AccessReasonFlag.KeyRole
});

var query = direct
.Union(keyRoleResult);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,35 @@
/// <returns>A task that represents the asynchronous operation. The task result contains a Result object indicating whether
/// the instance delegation was successfully added.</returns>
Task<Result<bool>> AddInstance(Entity from, Entity to, Resource resourceObj, string instanceId, RightKeyListDto rightKeys, Entity by, Action<ConnectionOptions> configureConnection = null, CancellationToken cancellationToken = default);

/// <summary>
/// Updates (replaces) a delegation to a resource instance between two entities with the specified action keys. If not all actions is posible nothing is performed and a Problem is returned
/// </summary>
/// <param name="from">The source entity from which the delegation originates.</param>
/// <param name="to">The target entity to which the delegation is granted.</param>
/// <param name="resourceObj">The resource to associate between the source and target entities.</param>
/// <param name="instanceId">The instance identifier for the resource instance.</param>
/// <param name="rightKeys">A list of rule keys that define the permissions or actions allowed for the resource instance.</param>
/// <param name="by">The entity performing the operation. Used for auditing and authorization purposes.</param>
/// <param name="configureConnection">An optional delegate to configure connection options for the operation. If null, default connection settings are used.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a Result object indicating whether
/// the instance delegation was successfully updated.</returns>
Task<Result<bool>> UpdateInstance(Entity from, Entity to, Resource resourceObj, string instanceId, IEnumerable<string> rightKeys, Entity by, Action<ConnectionOptions> configureConnection = null, CancellationToken cancellationToken = default);

Check warning on line 367 in src/apps/Altinn.AccessManagement/src/Altinn.AccessMgmt.Core/Services/Contracts/IConnectionService.cs

View check run for this annotation

SonarQubeCloud / [Authorization Altinn.AccessManagement] SonarCloud Code Analysis

Method has 8 parameters, which is greater than the 7 authorized.

See more on https://sonarcloud.io/project/issues?id=Authorization_AccessManagement&issues=AZz75qPXiX5OK5Qm2bTy&open=AZz75qPXiX5OK5Qm2bTy&pullRequest=2522

/// <summary>
/// Removes a resource instance (by resource string and instance id) from assignment based on a specific role between two entities.
/// </summary>
/// <param name="fromId">ID of the entity from which the assignment originates.</param>
/// <param name="toId">ID of the entity to which the assignment was made.</param>
/// <param name="resource">Resource reference id</param>
/// <param name="instanceId">Instance identifier</param>
/// <param name="configureConnection">ConnectionOptions</param>
/// <param name="cancellationToken">
/// Token to monitor for cancellation requests.
/// </param>
/// <returns>
/// A <see cref="ValidationProblemInstance"/> indicating success or describing any validation errors.
/// </returns>
Task<ValidationProblemInstance> RemoveInstance(Guid fromId, Guid toId, string resource, string instanceId, Action<ConnectionOptions> configureConnection = null, CancellationToken cancellationToken = default);
}
Loading