-
Notifications
You must be signed in to change notification settings - Fork 644
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Organizations] Fixes and unit tests for API upload for organizations (…
- Loading branch information
Scott Bommarito
authored
Jan 22, 2018
1 parent
5d29d53
commit 7a33bc3
Showing
19 changed files
with
1,070 additions
and
670 deletions.
There are no files selected for viewing
44 changes: 44 additions & 0 deletions
44
src/NuGetGallery/Authentication/ApiScopeEvaluationResult.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
namespace NuGetGallery.Authentication | ||
{ | ||
|
||
/// <summary> | ||
/// The result of evaluating the current user's scopes by using <see cref="ApiScopeEvaluator"/>. | ||
/// </summary> | ||
public class ApiScopeEvaluationResult | ||
{ | ||
/// <summary> | ||
/// True IFF any scope's subject (<see cref="Scope.Subject"/>) and allowed action (<see cref="Scope.AllowedAction"/>) match the subject being acted upon and the action being performed. | ||
/// </summary> | ||
public bool ScopesAreValid { get; } | ||
|
||
/// <summary> | ||
/// If <see cref="ScopesAreValid"/> is true, the <see cref="PermissionsCheckResult"/> returned by checking the permission of the scope's owner (<see cref="Scope.Owner"/>). | ||
/// Otherwise, <see cref="PermissionsCheckResult.Unknown"/>. | ||
/// </summary> | ||
public PermissionsCheckResult PermissionsCheckResult { get; } | ||
|
||
/// <summary> | ||
/// The owner of the scope as acquired from <see cref="Scope.Owner"/>. | ||
/// </summary> | ||
public User Owner { get; } | ||
|
||
public ApiScopeEvaluationResult(User owner, PermissionsCheckResult permissionsCheckResult, bool scopesAreValid) | ||
{ | ||
ScopesAreValid = scopesAreValid; | ||
PermissionsCheckResult = permissionsCheckResult; | ||
Owner = owner; | ||
} | ||
|
||
/// <summary> | ||
/// Returns whether or not this <see cref="ApiScopeEvaluationResult"/> represents a successful authentication. | ||
/// If this <see cref="ApiScopeEvaluationResult"/> does not represent a successful authentication, the current user should be denied from performing the action they are attempting to perform. | ||
/// </summary> | ||
public bool IsSuccessful() | ||
{ | ||
return ScopesAreValid && PermissionsCheckResult == PermissionsCheckResult.Allowed; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace NuGetGallery.Authentication | ||
{ | ||
public class ApiScopeEvaluator : IApiScopeEvaluator | ||
{ | ||
private readonly IUserService _userService; | ||
|
||
public ApiScopeEvaluator(IUserService userService) | ||
{ | ||
_userService = userService ?? throw new ArgumentNullException(nameof(userService)); | ||
} | ||
|
||
public ApiScopeEvaluationResult Evaluate( | ||
User currentUser, | ||
IEnumerable<Scope> scopes, | ||
IActionRequiringEntityPermissions<PackageRegistration> action, | ||
PackageRegistration packageRegistration, | ||
params string[] requestedActions) | ||
{ | ||
return Evaluate(currentUser, scopes, action, packageRegistration, pr => pr.Id, requestedActions); | ||
} | ||
|
||
public ApiScopeEvaluationResult Evaluate( | ||
User currentUser, | ||
IEnumerable<Scope> scopes, | ||
IActionRequiringEntityPermissions<ActionOnNewPackageContext> action, | ||
ActionOnNewPackageContext context, | ||
params string[] requestedActions) | ||
{ | ||
return Evaluate(currentUser, scopes, action, context, c => c.PackageId, requestedActions); | ||
} | ||
|
||
/// <remarks>This method is internal because it is tested directly.</remarks> | ||
internal ApiScopeEvaluationResult Evaluate<TEntity>( | ||
User currentUser, | ||
IEnumerable<Scope> scopes, | ||
IActionRequiringEntityPermissions<TEntity> action, | ||
TEntity entity, | ||
Func<TEntity, string> getSubjectFromEntity, | ||
params string[] requestedActions) | ||
{ | ||
User ownerInScope = null; | ||
|
||
if (scopes == null || !scopes.Any()) | ||
{ | ||
// Legacy V1 API key without scopes. | ||
// Evaluate it as if it has an unlimited scope. | ||
scopes = new[] { new Scope(ownerKey: null, subject: NuGetPackagePattern.AllInclusivePattern, allowedAction: NuGetScopes.All) }; | ||
} | ||
|
||
// Check that all scopes provided have the same owner scope. | ||
var ownerScopes = scopes.Select(s => s.OwnerKey); | ||
var ownerScope = ownerScopes.FirstOrDefault(); | ||
if (ownerScopes.Any(o => o != ownerScope)) | ||
{ | ||
throw new ArgumentException("All scopes provided must have the same owner scope."); | ||
} | ||
|
||
var matchingScope = scopes | ||
.FirstOrDefault(scope => | ||
scope.AllowsSubject(getSubjectFromEntity(entity)) && | ||
scope.AllowsActions(requestedActions)); | ||
|
||
ownerInScope = ownerScope.HasValue ? _userService.FindByKey(ownerScope.Value) : currentUser; | ||
|
||
if (matchingScope == null) | ||
{ | ||
return new ApiScopeEvaluationResult(ownerInScope, PermissionsCheckResult.Unknown, scopesAreValid: false); | ||
} | ||
|
||
var isActionAllowed = action.CheckPermissions(currentUser, ownerInScope, entity); | ||
return new ApiScopeEvaluationResult(ownerInScope, isActionAllowed, scopesAreValid: true); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace NuGetGallery.Authentication | ||
{ | ||
public interface IApiScopeEvaluator | ||
{ | ||
/// <summary> | ||
/// Evaluates the whether or not an action is allowed given a set of <paramref name="scopes"/>, an <paramref name="action"/>, and the <paramref name="requestedActions"/>. | ||
/// </summary> | ||
/// <param name="currentUser">The current user attempting to do the action with the given <paramref name="scopes"/>.</param> | ||
/// <param name="scopes">The scopes being evaluated.</param> | ||
/// <param name="action">The action that the scopes being evaluated are checked for permission to do.</param> | ||
/// <param name="packageRegistration">The <see cref="PackageRegistration"/> that the scopes being evaluated are checked for permission to <paramref name="action"/> on.</param> | ||
/// <param name="requestedActions">A list of actions that the scopes must match.</param> | ||
/// <returns>A <see cref="ApiScopeEvaluationResult"/> that describes the evaluation of the <see cref="Scope"/>s.</returns> | ||
ApiScopeEvaluationResult Evaluate( | ||
User currentUser, | ||
IEnumerable<Scope> scopes, | ||
IActionRequiringEntityPermissions<PackageRegistration> action, | ||
PackageRegistration packageRegistration, | ||
params string[] requestedActions); | ||
|
||
/// <summary> | ||
/// Evaluates the whether or not an action is allowed given a set of <paramref name="scopes"/>, an <paramref name="action"/>, and the <paramref name="requestedActions"/>. | ||
/// </summary> | ||
/// <param name="currentUser">The current user attempting to do the action with the given <paramref name="scopes"/>.</param> | ||
/// <param name="scopes">The scopes being evaluated.</param> | ||
/// <param name="action">The action that the scopes being evaluated are checked for permission to do.</param> | ||
/// <param name="context">The <see cref="ActionOnNewPackageContext"/> that the scopes being evaluated are checked for permission to <paramref name="action"/> on.</param> | ||
/// <param name="requestedActions">A list of actions that the scopes must match.</param> | ||
/// <returns>A <see cref="ApiScopeEvaluationResult"/> that describes the evaluation of the <see cref="Scope"/>s.</returns> | ||
ApiScopeEvaluationResult Evaluate( | ||
User currentUser, | ||
IEnumerable<Scope> scopes, | ||
IActionRequiringEntityPermissions<ActionOnNewPackageContext> action, | ||
ActionOnNewPackageContext context, | ||
params string[] requestedActions); | ||
} | ||
} |
Oops, something went wrong.