From 066b3ed8f042701a0a5cbd394021f9f37b4dc7af Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Tue, 2 Sep 2014 14:26:35 -0400 Subject: [PATCH] Add client side handling of user login throttling --- static/directives/signin-form.html | 29 +++++++++++++++---------- static/js/app.js | 35 +++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/static/directives/signin-form.html b/static/directives/signin-form.html index f56b8f8db..d8f822968 100644 --- a/static/directives/signin-form.html +++ b/static/directives/signin-form.html @@ -4,18 +4,25 @@ placeholder="Username or E-mail Address" ng-model="user.username" autofocus> - - - - - OR - - - Sign In with GitHub - - +
+ Too many attempts have been made to login. Please try again in {{ tryAgainSoon }} seconds. +
+ + + + + + + + Sign In with GitHub + + +
Invalid username or password.
diff --git a/static/js/app.js b/static/js/app.js index f5c612c5f..5fb21205b 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -2245,7 +2245,10 @@ quayApp.directive('signinForm', function () { 'signInStarted': '&signInStarted', 'signedIn': '&signedIn' }, - controller: function($scope, $location, $timeout, ApiService, KeyService, UserService, CookieService, Features, Config) { + controller: function($scope, $location, $timeout, $interval, ApiService, KeyService, UserService, CookieService, Features, Config) { + $scope.tryAgainSoon = 0; + $scope.tryAgainInterval = null; + $scope.showGithub = function() { if (!Features.GITHUB_LOGIN) { return; } @@ -2275,7 +2278,15 @@ quayApp.directive('signinForm', function () { } }; + $scope.$on('$destroy', function() { + if ($scope.tryAgainInterval) { + $interval.cancel($scope.tryAgainInterval); + } + }); + $scope.signin = function() { + if ($scope.tryAgainSoon > 0) { return; } + $scope.markStarted(); ApiService.signinUser($scope.user).then(function() { @@ -2298,8 +2309,26 @@ quayApp.directive('signinForm', function () { $location.path($scope.redirectUrl ? $scope.redirectUrl : '/'); }, 500); }, function(result) { - $scope.needsEmailVerification = result.data.needsEmailVerification; - $scope.invalidCredentials = result.data.invalidCredentials; + if (result.status == 429 /* try again later */) { + $scope.tryAgainSoon = result.headers('Retry-After'); + + // Cancel any existing interval. + if ($scope.tryAgainInterval) { + $interval.cancel($scope.tryAgainInterval); + } + + // Setup a new interval. + $scope.tryAgainInterval = $interval(function() { + $scope.tryAgainSoon--; + if ($scope.tryAgainSoon <= 0) { + $scope.tryAgainInterval = null; + $scope.tryAgainSoon = 0; + } + }, 1000, $scope.tryAgainSoon); + } else { + $scope.needsEmailVerification = result.data.needsEmailVerification; + $scope.invalidCredentials = result.data.invalidCredentials; + } }); }; }