Skip to content

Commit

Permalink
Merge pull request #5898 from NuGet/dev
Browse files Browse the repository at this point in the history
Dev to Master
  • Loading branch information
cristinamanum authored May 8, 2018
2 parents 5f03c7d + 487bfd8 commit e2318e4
Show file tree
Hide file tree
Showing 33 changed files with 382 additions and 198 deletions.
4 changes: 3 additions & 1 deletion src/NuGetGallery.Core/Auditing/AuditedUserAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public enum AuditedUserAction
TransformOrganization,
AddOrganizationMember,
RemoveOrganizationMember,
UpdateOrganizationMember
UpdateOrganizationMember,
EnabledMultiFactorAuthentication,
DisabledMultiFactorAuthentication
}
}
2 changes: 1 addition & 1 deletion src/NuGetGallery.Core/Services/CoreMessageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public void SendValidationTakingTooLongNotice(Package package, string packageUrl
mailMessage.Body = body;
mailMessage.From = CoreConfiguration.GalleryNoReplyAddress;

AddAllOwnersToMailMessage(package.PackageRegistration, mailMessage);
AddOwnersSubscribedToPackagePushedNotification(package.PackageRegistration, mailMessage);

if (mailMessage.To.Any())
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"isUIEnabledByDefault": false,
"alwaysEnabledForDomains": [
],
"alwaysEnabledForEmailAddresses": [
]
}
1 change: 1 addition & 0 deletions src/NuGetGallery/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public static class ContentNames
public static readonly string PrivacyPolicy = "Privacy-Policy";
public static readonly string Team = "Team";
public static readonly string LoginDiscontinuationConfiguration = "Login-Discontinuation-Configuration";
public static readonly string CertificatesConfiguration = "Certificates-Configuration";
}

public static class StatisticsDimensions
Expand Down
11 changes: 9 additions & 2 deletions src/NuGetGallery/Controllers/AccountsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public class ViewMessages

public ICertificateService CertificateService { get; }

public IContentObjectService ContentObjectService { get; }

public AccountsController(
AuthenticationService authenticationService,
ICuratedFeedService curatedFeedService,
Expand All @@ -51,7 +53,8 @@ public AccountsController(
IUserService userService,
ITelemetryService telemetryService,
ISecurityPolicyService securityPolicyService,
ICertificateService certificateService)
ICertificateService certificateService,
IContentObjectService contentObjectService)
{
AuthenticationService = authenticationService ?? throw new ArgumentNullException(nameof(authenticationService));
CuratedFeedService = curatedFeedService ?? throw new ArgumentNullException(nameof(curatedFeedService));
Expand All @@ -61,6 +64,7 @@ public AccountsController(
TelemetryService = telemetryService ?? throw new ArgumentNullException(nameof(telemetryService));
SecurityPolicyService = securityPolicyService ?? throw new ArgumentNullException(nameof(securityPolicyService));
CertificateService = certificateService ?? throw new ArgumentNullException(nameof(certificateService));
ContentObjectService = contentObjectService ?? throw new ArgumentNullException(nameof(contentObjectService));
}

public abstract string AccountAction { get; }
Expand Down Expand Up @@ -332,9 +336,12 @@ protected virtual void UpdateAccountViewModel(TUser account, TAccountViewModel m
model.Account = account;
model.AccountName = account.Username;

var currentUser = GetCurrentUser();

model.CanManage = ActionsRequiringPermissions.ManageAccount.CheckPermissions(
GetCurrentUser(), account) == PermissionsCheckResult.Allowed;
currentUser, account) == PermissionsCheckResult.Allowed;

model.IsCertificatesUIEnabled = ContentObjectService.CertificatesConfiguration?.IsUIEnabledForUser(currentUser) ?? false;
model.WasMultiFactorAuthenticated = User.WasMultiFactorAuthenticated();

model.CuratedFeeds = CuratedFeedService
Expand Down
6 changes: 4 additions & 2 deletions src/NuGetGallery/Controllers/OrganizationsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ public OrganizationsController(
ISecurityPolicyService securityPolicyService,
ICertificateService certificateService,
IPackageService packageService,
IDeleteAccountService deleteAccountService)
IDeleteAccountService deleteAccountService,
IContentObjectService contentObjectService)
: base(
authService,
curatedFeedService,
Expand All @@ -37,7 +38,8 @@ public OrganizationsController(
userService,
telemetryService,
securityPolicyService,
certificateService)
certificateService,
contentObjectService)
{
DeleteAccountService = deleteAccountService;
}
Expand Down
6 changes: 5 additions & 1 deletion src/NuGetGallery/Controllers/PackagesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ public partial class PackagesController
private readonly IReadMeService _readMeService;
private readonly IValidationService _validationService;
private readonly IPackageOwnershipManagementService _packageOwnershipManagementService;
private readonly IContentObjectService _contentObjectService;

public PackagesController(
IPackageService packageService,
Expand All @@ -106,7 +107,8 @@ public PackagesController(
IPackageUploadService packageUploadService,
IReadMeService readMeService,
IValidationService validationService,
IPackageOwnershipManagementService packageOwnershipManagementService)
IPackageOwnershipManagementService packageOwnershipManagementService,
IContentObjectService contentObjectService)
{
_packageService = packageService;
_uploadFileService = uploadFileService;
Expand All @@ -129,6 +131,7 @@ public PackagesController(
_readMeService = readMeService;
_validationService = validationService;
_packageOwnershipManagementService = packageOwnershipManagementService;
_contentObjectService = contentObjectService;
}

[HttpGet]
Expand Down Expand Up @@ -463,6 +466,7 @@ public virtual async Task<ActionResult> DisplayPackage(string id, string version

model.ValidatingTooLong = _validationService.IsValidatingTooLong(package);
model.ValidationIssues = _validationService.GetLatestValidationIssues(package);
model.IsCertificatesUIEnabled = _contentObjectService.CertificatesConfiguration?.IsUIEnabledForUser(currentUser) ?? false;

model.ReadMeHtml = await _readMeService.GetReadMeHtmlAsync(package);

Expand Down
9 changes: 6 additions & 3 deletions src/NuGetGallery/Controllers/UsersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public UsersController(
ISupportRequestService supportRequestService,
ITelemetryService telemetryService,
ISecurityPolicyService securityPolicyService,
ICertificateService certificateService)
ICertificateService certificateService,
IContentObjectService contentObjectService)
: base(
authService,
feedsQuery,
Expand All @@ -50,7 +51,8 @@ public UsersController(
userService,
telemetryService,
securityPolicyService,
certificateService)
certificateService,
contentObjectService)
{
_packageOwnerRequestService = packageOwnerRequestService ?? throw new ArgumentNullException(nameof(packageOwnerRequestService));
_config = config ?? throw new ArgumentNullException(nameof(config));
Expand Down Expand Up @@ -479,7 +481,8 @@ public virtual ActionResult Packages()
UnlistedPackages = unlistedPackages,
OwnerRequests = ownerRequests,
ReservedNamespaces = reservedPrefixes,
WasMultiFactorAuthenticated = User.WasMultiFactorAuthenticated()
WasMultiFactorAuthenticated = User.WasMultiFactorAuthenticated(),
IsCertificatesUIEnabled = ContentObjectService.CertificatesConfiguration?.IsUIEnabledForUser(currentUser) ?? false
};
return View(model);
}
Expand Down
3 changes: 3 additions & 0 deletions src/NuGetGallery/NuGetGallery.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -862,12 +862,14 @@
<Compile Include="Services\ActionRequiringReservedNamespacePermissions.cs" />
<Compile Include="Services\ActionsRequiringPermissions.cs" />
<Compile Include="Services\AsynchronousPackageValidationInitiator.cs" />
<Compile Include="Services\CertificatesConfiguration.cs" />
<Compile Include="Services\CertificateService.cs" />
<Compile Include="Services\CertificateValidator.cs" />
<Compile Include="Services\CloudBlobFileStorageService.cs" />
<Compile Include="Services\DeleteAccountService.cs" />
<Compile Include="Services\IActionRequiringEntityPermissions.cs" />
<Compile Include="Services\ICertificateService.cs" />
<Compile Include="Services\ICertificatesConfiguration.cs" />
<Compile Include="Services\ICertificateValidator.cs" />
<Compile Include="Services\IDeleteAccountService.cs" />
<Compile Include="Services\IFileStorageService.cs" />
Expand Down Expand Up @@ -2018,6 +2020,7 @@
<Content Include="Areas\Admin\Views\LockPackage\Index.cshtml" />
<Content Include="App_Data\Files\Content\Login-Discontinuation-Configuration.json" />
<Content Include="Areas\Admin\Views\DeleteAccount\_DeleteUserAccountForm.cshtml" />
<Content Include="App_Data\Files\Content\Certificates-Configuration.json" />
<None Include="Scripts\jquery-1.11.0.intellisense.js" />
<Content Include="Scripts\jquery-1.11.0.js" />
<Content Include="Scripts\jquery-1.11.0.min.js" />
Expand Down
59 changes: 59 additions & 0 deletions src/NuGetGallery/Services/CertificatesConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// 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 Newtonsoft.Json;

namespace NuGetGallery.Services
{
public sealed class CertificatesConfiguration : ICertificatesConfiguration
{
public bool IsUIEnabledByDefault { get; }
public HashSet<string> AlwaysEnabledForEmailAddresses { get; }
public HashSet<string> AlwaysEnabledForDomains { get; }

public CertificatesConfiguration()
: this(isUIEnabledByDefault: false,
alwaysEnabledForDomains: Enumerable.Empty<string>(),
alwaysEnabledForEmailAddresses: Enumerable.Empty<string>())
{
}

[JsonConstructor]
public CertificatesConfiguration(
bool isUIEnabledByDefault,
IEnumerable<string> alwaysEnabledForDomains,
IEnumerable<string> alwaysEnabledForEmailAddresses)
{
if (alwaysEnabledForDomains == null)
{
throw new ArgumentNullException(nameof(alwaysEnabledForDomains));
}

if (alwaysEnabledForEmailAddresses == null)
{
throw new ArgumentNullException(nameof(alwaysEnabledForEmailAddresses));
}

IsUIEnabledByDefault = isUIEnabledByDefault;
AlwaysEnabledForDomains = new HashSet<string>(alwaysEnabledForDomains, StringComparer.OrdinalIgnoreCase);
AlwaysEnabledForEmailAddresses = new HashSet<string>(alwaysEnabledForEmailAddresses, StringComparer.OrdinalIgnoreCase);
}

public bool IsUIEnabledForUser(User user)
{
if (user == null)
{
return false;
}

var email = user.ToMailAddress();

return IsUIEnabledByDefault ||
AlwaysEnabledForDomains.Contains(email.Host) ||
AlwaysEnabledForEmailAddresses.Contains(email.Address);
}
}
}
8 changes: 7 additions & 1 deletion src/NuGetGallery/Services/ContentObjectService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NuGetGallery.Services;

namespace NuGetGallery
{
Expand All @@ -19,15 +19,21 @@ public ContentObjectService(IContentService contentService)
_contentService = contentService;

LoginDiscontinuationConfiguration = new LoginDiscontinuationConfiguration();
CertificatesConfiguration = new CertificatesConfiguration();
}

public ILoginDiscontinuationConfiguration LoginDiscontinuationConfiguration { get; set; }
public ICertificatesConfiguration CertificatesConfiguration { get; set; }

public async Task Refresh()
{
LoginDiscontinuationConfiguration =
await Refresh<LoginDiscontinuationConfiguration>(Constants.ContentNames.LoginDiscontinuationConfiguration) ??
new LoginDiscontinuationConfiguration();

CertificatesConfiguration =
await Refresh<CertificatesConfiguration>(Constants.ContentNames.CertificatesConfiguration) ??
new CertificatesConfiguration();
}

private async Task<T> Refresh<T>(string contentName)
Expand Down
10 changes: 10 additions & 0 deletions src/NuGetGallery/Services/ICertificatesConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// 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.Services
{
public interface ICertificatesConfiguration
{
bool IsUIEnabledForUser(User user);
}
}
4 changes: 3 additions & 1 deletion src/NuGetGallery/Services/IContentObjectService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading.Tasks;
using NuGetGallery.Services;

namespace NuGetGallery
{
public interface IContentObjectService
{
ILoginDiscontinuationConfiguration LoginDiscontinuationConfiguration { get; }
ICertificatesConfiguration CertificatesConfiguration { get; }

Task Refresh();
}
}
}
1 change: 0 additions & 1 deletion src/NuGetGallery/Services/IMessageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public interface IMessageService
void SendCredentialAddedNotice(User user, CredentialViewModel addedCredentialViewModel);
void SendContactSupportEmail(ContactSupportRequest request);
void SendPackageAddedNotice(Package package, string packageUrl, string packageSupportUrl, string emailSettingsUrl);
void SendPackageUploadedNotice(Package package, string packageUrl, string packageSupportUrl, string emailSettingsUrl);
void SendAccountDeleteNotice(User user);
void SendPackageDeletedNotice(Package package, string packageUrl, string packageSupportUrl);
void SendSigninAssistanceEmail(MailAddress emailAddress, IEnumerable<Credential> credentials);
Expand Down
10 changes: 5 additions & 5 deletions src/NuGetGallery/Services/LoginDiscontinuationConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ namespace NuGetGallery
{
public class LoginDiscontinuationConfiguration : ILoginDiscontinuationConfiguration
{
internal HashSet<string> DiscontinuedForEmailAddresses { get; }
internal HashSet<string> DiscontinuedForDomains { get; }
internal HashSet<string> ExceptionsForEmailAddresses { get; }
internal HashSet<string> ForceTransformationToOrganizationForEmailAddresses { get; }
internal HashSet<OrganizationTenantPair> EnabledOrganizationAadTenants { get; }
public HashSet<string> DiscontinuedForEmailAddresses { get; }
public HashSet<string> DiscontinuedForDomains { get; }
public HashSet<string> ExceptionsForEmailAddresses { get; }
public HashSet<string> ForceTransformationToOrganizationForEmailAddresses { get; }
public HashSet<OrganizationTenantPair> EnabledOrganizationAadTenants { get; }

public LoginDiscontinuationConfiguration()
: this(Enumerable.Empty<string>(),
Expand Down
28 changes: 0 additions & 28 deletions src/NuGetGallery/Services/MessageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -636,34 +636,6 @@ private void SendSupportMessage(User user, string body, string subject)
}
}

public void SendPackageUploadedNotice(Package package, string packageUrl, string packageSupportUrl, string emailSettingsUrl)
{
string subject = $"[{Config.GalleryOwner.DisplayName}] Package uploaded - {package.PackageRegistration.Id} {package.Version}";
string body = $@"The package [{package.PackageRegistration.Id} {package.Version}]({packageUrl}) was recently uploaded to {Config.GalleryOwner.DisplayName} by {package.User.Username}. If this was not intended, please [contact support]({packageSupportUrl}).
Note: This package has not been published yet. It will appear in search results and will be available for install/restore after both validation and indexing are complete. Package validation and indexing may take up to an hour.
-----------------------------------------------
<em style=""font-size: 0.8em;"">
To stop receiving emails as an owner of this package, sign in to the {Config.GalleryOwner.DisplayName} and
[change your email notification settings]({emailSettingsUrl}).
</em>";

using (var mailMessage = new MailMessage())
{
mailMessage.Subject = subject;
mailMessage.Body = body;
mailMessage.From = Config.GalleryNoReplyAddress;

AddOwnersSubscribedToPackagePushedNotification(package.PackageRegistration, mailMessage);

if (mailMessage.To.Any())
{
SendMessage(mailMessage);
}
}
}

public void SendAccountDeleteNotice(User user)
{
string body = @"We received a request to delete your account {0}. If you did not initiate this request, please contact the {1} team immediately.
Expand Down
2 changes: 2 additions & 0 deletions src/NuGetGallery/Services/UserService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,8 @@ public async Task CancelChangeEmailAddress(User user)

public virtual async Task ChangeMultiFactorAuthentication(User user, bool enableMultiFactor)
{
await Auditing.SaveAuditRecordAsync(new UserAuditRecord(user, enableMultiFactor ? AuditedUserAction.EnabledMultiFactorAuthentication : AuditedUserAction.DisabledMultiFactorAuthentication));

user.EnableMultiFactorAuthentication = enableMultiFactor;
await UserRepository.CommitChangesAsync();

Expand Down
2 changes: 2 additions & 0 deletions src/NuGetGallery/ViewModels/AccountViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public abstract class AccountViewModel<T> : AccountViewModel where T : User
{
public T Account { get; set; }

public bool IsCertificatesUIEnabled { get; set; }

public override User User => Account;
}

Expand Down
Loading

0 comments on commit e2318e4

Please sign in to comment.