-
Notifications
You must be signed in to change notification settings - Fork 643
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Temp keys policy onboarding #3854
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
d1f38a8
Temp keys onboarding
chenriksson 82af4f4
Bug fixes
chenriksson 003161f
Cleanup
chenriksson c3bc293
PR feedback
chenriksson e334a41
Fix test failure with ToList
chenriksson a89ad42
PR feedback
chenriksson 3f840d3
PR feedback
chenriksson 7222a3c
cleanup
chenriksson 5cebd42
PR feedback
chenriksson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
122 changes: 122 additions & 0 deletions
122
src/NuGetGallery/Areas/Admin/Controllers/SecurityPolicyController.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,122 @@ | ||
// 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; | ||
using System.Threading.Tasks; | ||
using System.Web.Mvc; | ||
using Newtonsoft.Json; | ||
using Newtonsoft.Json.Linq; | ||
using NuGetGallery.Areas.Admin.ViewModels; | ||
using NuGetGallery.Security; | ||
|
||
namespace NuGetGallery.Areas.Admin.Controllers | ||
{ | ||
/// <summary> | ||
/// Controller for the security policy management Admin view. | ||
/// </summary> | ||
public class SecurityPolicyController : AdminControllerBase | ||
{ | ||
protected IEntitiesContext EntitiesContext { get; set; } | ||
|
||
protected ISecurityPolicyService PolicyService { get; set; } | ||
|
||
protected SecurityPolicyController() | ||
{ | ||
} | ||
|
||
public SecurityPolicyController(IEntitiesContext entitiesContext, ISecurityPolicyService policyService) | ||
{ | ||
EntitiesContext = entitiesContext ?? throw new ArgumentNullException(nameof(entitiesContext)); | ||
PolicyService = policyService ?? throw new ArgumentNullException(nameof(policyService)); | ||
} | ||
|
||
[HttpGet] | ||
public virtual ActionResult Index() | ||
{ | ||
var model = new SecurityPolicyViewModel() | ||
{ | ||
SubscriptionNames = PolicyService.UserSubscriptions.Select(s => s.SubscriptionName) | ||
}; | ||
|
||
return View(model); | ||
} | ||
|
||
[HttpGet] | ||
public virtual JsonResult Search(string query) | ||
{ | ||
// Parse query and look for users in the DB. | ||
var usernames = GetUsernamesFromQuery(query ?? ""); | ||
var users = FindUsers(usernames); | ||
var usersNotFound = usernames.Except(users.Select(u => u.Username)); | ||
|
||
var results = new UserSecurityPolicySearchResult() | ||
{ | ||
// Found users and subscribed status for each policy subscription. | ||
Users = users.Select(u => new UserSecurityPolicySubscriptions() | ||
{ | ||
Username = u.Username, | ||
Subscriptions = PolicyService.UserSubscriptions.ToDictionary( | ||
s => s.SubscriptionName, | ||
s => PolicyService.IsSubscribed(u, s)) | ||
}), | ||
// Usernames that weren't found in the DB. | ||
UsersNotFound = usersNotFound | ||
}; | ||
|
||
return Json(results, JsonRequestBehavior.AllowGet); | ||
} | ||
|
||
[HttpPost] | ||
[ValidateAntiForgeryToken] | ||
public async Task<ActionResult> Update(SecurityPolicyViewModel viewModel) | ||
{ | ||
// Policy subscription requests by user. | ||
var subscriptions = viewModel.UserSubscriptions? | ||
.Select(json => JsonConvert.DeserializeObject<JObject>(json)) | ||
.GroupBy(obj => obj["u"].ToString()) | ||
.ToDictionary( | ||
g => g.Key, | ||
g => g.Select(obj => obj["g"].ToString()) | ||
); | ||
|
||
// Iterate all users and groups to handle both subscribe and unsubscribe. | ||
var usernames = GetUsernamesFromQuery(viewModel.UsersQuery); | ||
var users = FindUsers(usernames); | ||
foreach (var user in users) | ||
{ | ||
foreach (var subscription in PolicyService.UserSubscriptions) | ||
{ | ||
var userKeyExists = subscriptions?.ContainsKey(user.Username) ?? false; | ||
if (userKeyExists && subscriptions[user.Username].Contains(subscription.SubscriptionName)) | ||
{ | ||
await PolicyService.SubscribeAsync(user, subscription); | ||
} | ||
else | ||
{ | ||
await PolicyService.UnsubscribeAsync(user, subscription); | ||
} | ||
} | ||
} | ||
|
||
TempData["Message"] = $"Updated policies for {users.Count()} users."; | ||
|
||
return RedirectToAction("Index"); | ||
} | ||
|
||
private static string[] GetUsernamesFromQuery(string query) | ||
{ | ||
return query.Split(',', '\r', '\n') | ||
.Select(username => username.Trim()) | ||
.Where(username => !string.IsNullOrEmpty(username)).ToArray(); | ||
} | ||
|
||
private IEnumerable<User> FindUsers(string[] usernames) | ||
{ | ||
return EntitiesContext.Users | ||
.Where(u => usernames.Any(name => u.Username.Equals(name, StringComparison.OrdinalIgnoreCase))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This properly becomes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Evaluated SQL-side, with similar query...
|
||
.ToList(); | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
src/NuGetGallery/Areas/Admin/ViewModels/SecurityPolicyViewModel.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,28 @@ | ||
// 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.Collections.Generic; | ||
|
||
namespace NuGetGallery.Areas.Admin.ViewModels | ||
{ | ||
/// <summary> | ||
/// View model for the security policies admin view. | ||
/// </summary> | ||
public class SecurityPolicyViewModel | ||
{ | ||
/// <summary> | ||
/// Users search query. | ||
/// </summary> | ||
public string UsersQuery { get; set; } | ||
|
||
/// <summary> | ||
/// Available security policy groups. | ||
/// </summary> | ||
public IEnumerable<string> SubscriptionNames { get; set; } | ||
|
||
/// <summary> | ||
/// User subscription requests, in JSON format. | ||
/// </summary> | ||
public IEnumerable<string> UserSubscriptions { get; set; } | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/NuGetGallery/Areas/Admin/ViewModels/UserSecurityPolicySearchResult.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,23 @@ | ||
// 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.Collections.Generic; | ||
|
||
namespace NuGetGallery.Areas.Admin.ViewModels | ||
{ | ||
/// <summary> | ||
/// User search results for the security policies admin view. | ||
/// </summary> | ||
public class UserSecurityPolicySearchResult | ||
{ | ||
/// <summary> | ||
/// Found users, with security policy subscriptions they are subscribed to. | ||
/// </summary> | ||
public IEnumerable<UserSecurityPolicySubscriptions> Users { get; set; } | ||
|
||
/// <summary> | ||
/// Usernames not found in the database. | ||
/// </summary> | ||
public IEnumerable<string> UsersNotFound { get; set; } | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/NuGetGallery/Areas/Admin/ViewModels/UserSecurityPolicySubscriptions.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,22 @@ | ||
// 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.Collections.Generic; | ||
|
||
namespace NuGetGallery.Areas.Admin.ViewModels | ||
{ | ||
/// <summary> | ||
/// Security policy group subscriptions for a user. | ||
/// </summary> | ||
public class UserSecurityPolicySubscriptions | ||
{ | ||
public int UserId { get; set; } | ||
|
||
public string Username { get; set; } | ||
|
||
/// <summary> | ||
/// Dictionary of security policy subscriptions, and whether user is subscribed. | ||
/// </summary> | ||
public IDictionary<string, bool> Subscriptions { get; set; } | ||
} | ||
} |
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IEquatable should override GetHashCode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done