Skip to content

Commit

Permalink
Limit updating the user email address to three times per hour.
Browse files Browse the repository at this point in the history
  • Loading branch information
niemyjski committed Feb 3, 2016
1 parent de27bf7 commit 4b4c519
Showing 1 changed file with 14 additions and 4 deletions.
18 changes: 14 additions & 4 deletions Source/Api/Controllers/UserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,22 @@
using Exceptionless.Core.Mail;
using Exceptionless.Core.Repositories;
using Exceptionless.Core.Models;
using Exceptionless.DateTimeExtensions;
using FluentValidation;
using Foundatio.Caching;
using Foundatio.Logging;

namespace Exceptionless.Api.Controllers {
[RoutePrefix(API_PREFIX + "/users")]
[Authorize(Roles = AuthorizationRoles.User)]
public class UserController : RepositoryApiController<IUserRepository, User, ViewUser, User, UpdateUser> {
private readonly IOrganizationRepository _organizationRepository;
private readonly ICacheClient _cacheClient;
private readonly IMailer _mailer;

public UserController(IUserRepository userRepository, IOrganizationRepository organizationRepository, IMailer mailer) : base(userRepository) {
public UserController(IUserRepository userRepository, IOrganizationRepository organizationRepository, ICacheClient cacheClient, IMailer mailer) : base(userRepository) {
_organizationRepository = organizationRepository;
_cacheClient = new ScopedCacheClient(cacheClient, "user");
_mailer = mailer;
}

Expand Down Expand Up @@ -117,12 +121,18 @@ public async Task<IHttpActionResult> UpdateEmailAddressAsync(string id, string e
return NotFound();

email = email.ToLower();
if (!await IsEmailAddressAvailableInternalAsync(email))
return BadRequest("A user with this email address already exists.");

if (String.Equals(ExceptionlessUser.EmailAddress, email, StringComparison.OrdinalIgnoreCase))
return Ok(new UpdateEmailAddressResult { IsVerified = user.IsEmailAddressVerified });

// Only allow 3 email address updates per hour period by a single user.
string updateEmailAddressAttemptsCacheKey = $"{ExceptionlessUser.Id}:attempts";
long attempts = await _cacheClient.IncrementAsync(updateEmailAddressAttemptsCacheKey, 1, DateTime.UtcNow.Ceiling(TimeSpan.FromHours(1)));
if (attempts > 3)
return BadRequest("Update email address rate limit reached. Please try updating later.");

if (!await IsEmailAddressAvailableInternalAsync(email))
return BadRequest("A user with this email address already exists.");

user.ResetPasswordResetToken();
user.EmailAddress = email;
user.IsEmailAddressVerified = user.OAuthAccounts.Count(oa => String.Equals(oa.EmailAddress(), email, StringComparison.OrdinalIgnoreCase)) > 0;
Expand Down

0 comments on commit 4b4c519

Please sign in to comment.