Skip to content
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

Fix Support link #9276

Merged
merged 5 commits into from
Oct 12, 2022
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions src/AccountDeleter/Configuration/GalleryConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,6 @@ public string SiteRoot
public int? MaxIoThreads { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string InternalMicrosoftTenantKey { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string AdminSenderUser { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string SupportEmailSiteRoot { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
}
6 changes: 3 additions & 3 deletions src/AccountDeleter/Providers/AccountDeleteUrlHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace NuGetGallery.AccountDeleter
{
public class AccountDeleteUrlHelper : IUrlHelper
{
public string ConfirmPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl)
public string ConfirmPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl, bool supportEmail)
{
throw new NotImplementedException();
}
Expand All @@ -17,12 +17,12 @@ public string ManagePackageOwnership(string id, bool relativeUrl)
throw new NotImplementedException();
}

public string Package(string id, string version, bool relativeUrl)
public string Package(string id, string version, bool relativeUrl, bool supportEmail)
{
throw new NotImplementedException();
}

public string RejectPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl)
public string RejectPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl, bool supportEmail)
{
throw new NotImplementedException();
}
Expand Down
1 change: 1 addition & 0 deletions src/GalleryTools/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

<!-- Used for testing locally. -->
<add key="Gallery.SiteRoot" value="http://localhost"/>
<add key="Gallery.SupportEmailSiteRoot" value="http://localhost"/>
<add key="Gallery.FileStorageDirectory" value="..\..\..\NuGetGallery\App_Data\Files"/>
<add key="Gallery.LuceneIndexLocation" value="Temp"/>
<add key="Gallery.IsHosted" value="false"/>
Expand Down
5 changes: 5 additions & 0 deletions src/NuGetGallery.Services/Configuration/AppConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ public class AppConfiguration : IAppConfiguration
/// </summary>
public string SiteRoot { get; set; }

/// <summary>
/// Gets the protocol-independent support email site root
/// </summary>
public string SupportEmailSiteRoot { get; set; }

/// <summary>
/// Private key for verifying recaptcha user response.
/// </summary>
Expand Down
37 changes: 37 additions & 0 deletions src/NuGetGallery.Services/Configuration/ConfigurationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ConfigurationService : IGalleryConfigurationService, IConfiguration

private readonly Lazy<string> _httpSiteRootThunk;
private readonly Lazy<string> _httpsSiteRootThunk;
private readonly Lazy<string> _httpsEmailSupportSiteRootThunk;
private readonly Lazy<IAppConfiguration> _lazyAppConfiguration;
private readonly Lazy<FeatureConfiguration> _lazyFeatureConfiguration;
private readonly Lazy<IServiceBusConfiguration> _lazyServiceBusConfiguration;
Expand Down Expand Up @@ -59,6 +60,7 @@ public ConfigurationService()
{
_httpSiteRootThunk = new Lazy<string>(GetHttpSiteRoot);
_httpsSiteRootThunk = new Lazy<string>(GetHttpsSiteRoot);
_httpsEmailSupportSiteRootThunk = new Lazy<string>(GetHttpsSupportEmailSiteRoot);

_lazyAppConfiguration = new Lazy<IAppConfiguration>(() => ResolveSettings().Result);
_lazyFeatureConfiguration = new Lazy<FeatureConfiguration>(() => ResolveFeatures().Result);
Expand Down Expand Up @@ -89,6 +91,15 @@ public string GetSiteRoot(bool useHttps)
return useHttps ? _httpsSiteRootThunk.Value : _httpSiteRootThunk.Value;
}

/// <summary>
/// Gets the support email site root using the specified protocol
/// </summary>
/// <returns></returns>
public string GetSupportEmailSiteRoot()
{
return _httpsEmailSupportSiteRootThunk.Value;
}

public Task<T> Get<T>() where T : NuGet.Services.Configuration.Configuration, new()
{
// Get the prefix specified by the ConfigurationKeyPrefixAttribute on the class if it exists.
Expand Down Expand Up @@ -242,5 +253,31 @@ private string GetHttpsSiteRoot()

return "https://" + siteRoot.Substring(7);
}

private string GetHttpsSupportEmailSiteRoot()
{
var siteRoot = Current.SupportEmailSiteRoot;

if (siteRoot == null)
{
// No SiteRoot configured in settings.
// Fallback to detected site root.
lyndaidaii marked this conversation as resolved.
Show resolved Hide resolved
var request = GetCurrentRequest();
siteRoot = request.Url.GetLeftPart(UriPartial.Authority) + '/';
}

if (!siteRoot.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
&& !siteRoot.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException("The configured site root must start with either http:// or https://.");
}

if (siteRoot.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
{
siteRoot = "https://" + siteRoot.Substring(7);
}

return siteRoot;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ public interface IAppConfiguration : IMessageServiceConfiguration
/// </summary>
string SiteRoot { get; set; }

/// <summary>
/// Gets the protocol-independent support email site root
/// </summary>
string SupportEmailSiteRoot { get; set; }

/// <summary>
/// Private key for verifying recaptcha user response.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public interface IGalleryConfigurationService
/// <param name="useHttps">If true, the root will be returned in HTTPS form, otherwise, HTTP.</param>
string GetSiteRoot(bool useHttps);

/// <summary>
/// Gets the support email site root using the specified protocol
/// </summary>
string GetSupportEmailSiteRoot();

/// <summary>
/// Populate the properties of <param name="instance"></param> from configuration.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public async Task AddPackageOwnerWithMessagesAsync(PackageRegistration packageRe
{
await AddPackageOwnerAsync(packageRegistration, user, commitChanges: true);

var packageUrl = _urlHelper.Package(packageRegistration.Id, version: null, relativeUrl: false);
var packageUrl = _urlHelper.Package(packageRegistration.Id, version: null, relativeUrl: false, supportEmail: true);

// Accumulate the tasks so that they are sent in parallel and as many messages as possible are sent even if
// one fails (i.e. throws an exception).
Expand Down Expand Up @@ -155,7 +155,7 @@ public async Task<PackageOwnerRequest> AddPackageOwnershipRequestWithMessagesAsy

var encodedMessage = HttpUtility.HtmlEncode(message ?? string.Empty);

var packageUrl = _urlHelper.Package(packageRegistration.Id, version: null, relativeUrl: false);
var packageUrl = _urlHelper.Package(packageRegistration.Id, version: null, relativeUrl: false, supportEmail: true);

var ownerRequest = await AddPackageOwnershipRequestAsync(
packageRegistration, requestingOwner, newOwner);
Expand All @@ -164,13 +164,15 @@ public async Task<PackageOwnerRequest> AddPackageOwnershipRequestWithMessagesAsy
packageRegistration.Id,
newOwner.Username,
ownerRequest.ConfirmationCode,
relativeUrl: false);
relativeUrl: false,
supportEmail: true);

var rejectionUrl = _urlHelper.RejectPendingOwnershipRequest(
packageRegistration.Id,
newOwner.Username,
ownerRequest.ConfirmationCode,
relativeUrl: false);
relativeUrl: false,
supportEmail: true);

var manageUrl = _urlHelper.ManagePackageOwnership(
packageRegistration.Id,
Expand Down
9 changes: 6 additions & 3 deletions src/NuGetGallery.Services/Providers/IUrlHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public interface IUrlHelper
/// <param name="id">The package ID to link to.</param>
/// <param name="version">The specific package version to link to. Can be null.</param>
/// <param name="relativeUrl">True to return a relative URL, false to return an absolute URL.</param>
/// <param name="supportEmail">True to return a supportEmail root site URL, false to return an root site URL.</param>
/// <returns>The relative or absolute URL as a string.</returns>
string Package(string id, string version, bool relativeUrl);
string Package(string id, string version, bool relativeUrl, bool supportEmail);

/// <summary>
/// Produces a URL to the package ownership request confirmation page.
Expand All @@ -27,8 +28,9 @@ public interface IUrlHelper
/// <param name="username">The username of the ownership request recipient (new owner).</param>
/// <param name="confirmationCode">The confirmation code (secret) associated with the request.</param>
/// <param name="relativeUrl">True to return a relative URL, false to return an absolute URL.</param>
/// <param name="supportEmail">True to return a supportEmail root site URL, false to return an root site URL.</param>
/// <returns>The relative or absolute URL as a string.</returns>
string ConfirmPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl);
string ConfirmPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl, bool supportEmail);

/// <summary>
/// Produces a URL to the package ownership request rejection page.
Expand All @@ -37,8 +39,9 @@ public interface IUrlHelper
/// <param name="username">The username of the ownership request recipient (new owner).</param>
/// <param name="confirmationCode">The confirmation code (secret) associated with the request.</param>
/// <param name="relativeUrl">True to return a relative URL, false to return an absolute URL.</param>
/// <param name="supportEmail">True to return a supportEmail root site URL, false to return an root site URL.</param>
/// <returns>The relative or absolute URL as a string.</returns>
string RejectPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl);
string RejectPendingOwnershipRequest(string id, string username, string confirmationCode, bool relativeUrl, bool supportEmail);

/// <summary>
/// Produces a URL to manage the ownership of an existing package.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ public async Task<ActionResult> Revoke(RevokeApiKeysRequest revokeApiKeysRequest
credential: apiKeyCredential,
leakedUrl: apiKeyInfo.LeakedUrl,
revocationSource: apiKeyInfo.RevocationSource,
manageApiKeyUrl: Url.ManageMyApiKeys(relativeUrl: false),
contactUrl: Url.Contact(relativeUrl: false));
manageApiKeyUrl: Url.ManageMyApiKeys(relativeUrl: false, supportEmail: true),
contactUrl: Url.Contact(relativeUrl: false, supportEmail: true));
await _messageService.SendMessageAsync(credentialRevokedMessage);

await _authenticationService.RevokeApiKeyCredential(apiKeyCredential, revocationSourceKey, commitChanges: false);
Expand Down
3 changes: 2 additions & 1 deletion src/NuGetGallery/Controllers/AuthenticationController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,8 @@ public virtual async Task<ActionResult> Register(LogOnViewModel model, string re
Url.ConfirmEmail(
user.User.Username,
user.User.EmailConfirmationToken,
relativeUrl: false));
relativeUrl: false,
supportEmail: true));

await _messageService.SendMessageAsync(message);
}
Expand Down
6 changes: 3 additions & 3 deletions src/NuGetGallery/Controllers/OrganizationsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ public async Task<JsonResult> AddMember(string accountName, string memberName, b
request.NewMember,
currentUser,
request.IsAdmin,
profileUrl: Url.User(account, relativeUrl: false),
confirmationUrl: Url.AcceptOrganizationMembershipRequest(request, relativeUrl: false),
rejectionUrl: Url.RejectOrganizationMembershipRequest(request, relativeUrl: false));
profileUrl: Url.User(account, relativeUrl: false, supportEmail: true),
confirmationUrl: Url.AcceptOrganizationMembershipRequest(request, relativeUrl: false, supportEmail: true),
rejectionUrl: Url.RejectOrganizationMembershipRequest(request, relativeUrl: false, supportEmail: true));
await MessageService.SendMessageAsync(organizationMembershipRequestMessage);

var organizationMembershipRequestInitiatedMessage = new OrganizationMembershipRequestInitiatedMessage(
Expand Down
9 changes: 5 additions & 4 deletions src/NuGetGallery/Controllers/UsersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ public virtual async Task<ActionResult> TransformToOrganization(TransformAccount
_config,
accountToTransform,
adminUser,
profileUrl: Url.User(accountToTransform, relativeUrl: false),
confirmationUrl: Url.ConfirmTransformAccount(accountToTransform, relativeUrl: false),
rejectionUrl: Url.RejectTransformAccount(accountToTransform, relativeUrl: false));
profileUrl: Url.User(accountToTransform, relativeUrl: false, supportEmail: true),
confirmationUrl: Url.ConfirmTransformAccount(accountToTransform, relativeUrl: false, supportEmail: true),
rejectionUrl: Url.RejectTransformAccount(accountToTransform, relativeUrl: false, supportEmail: true));
await MessageService.SendMessageAsync(organizationTransformRequestMessage);

var organizationTransformInitiatedMessage = new OrganizationTransformInitiatedMessage(
Expand Down Expand Up @@ -1257,7 +1257,8 @@ private async Task<ActionResult> SendPasswordResetEmailAsync(User user, bool for
user.Username,
user.PasswordResetToken,
forgotPassword,
relativeUrl: false);
relativeUrl: false,
supportEmail: true);

var message = new PasswordResetInstructionsMessage(
MessageServiceConfiguration,
Expand Down
Loading