Skip to content

Commit

Permalink
Fix Support link (#9276)
Browse files Browse the repository at this point in the history
* fix broken support link
  • Loading branch information
lyndaidaii authored Oct 12, 2022
1 parent 0e42bd0 commit 387363d
Show file tree
Hide file tree
Showing 21 changed files with 225 additions and 93 deletions.
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
56 changes: 43 additions & 13 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 @@ -209,19 +220,7 @@ private string GetHttpSiteRoot()
{
var siteRoot = Current.SiteRoot;

if (siteRoot == null)
{
// No SiteRoot configured in settings.
// Fallback to detected site root.
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://.");
}
CheckValidSiteRoot(siteRoot);

if (siteRoot.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
Expand All @@ -242,5 +241,36 @@ private string GetHttpsSiteRoot()

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

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

CheckValidSiteRoot(siteRoot);

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

return siteRoot;
}

private void CheckValidSiteRoot(string siteRoot)
{
if (siteRoot == null)
{
// No SiteRoot configured in settings.
// Fallback to detected site root.
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://.");
}
}
}
}
5 changes: 5 additions & 0 deletions src/NuGetGallery.Services/Configuration/IAppConfiguration.cs
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
4 changes: 2 additions & 2 deletions src/NuGetGallery/Areas/Admin/Controllers/ApiKeysController.cs
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

0 comments on commit 387363d

Please sign in to comment.