Add ability to detach external login services

This commit is contained in:
Joseph Schorr 2014-09-15 12:01:02 -04:00
parent e8ad01cb41
commit 913b3e472f
5 changed files with 62 additions and 1 deletions

View file

@ -1830,6 +1830,16 @@ def get_active_users():
def get_active_user_count():
return get_active_users().count()
def detach_external_login(user, service_name):
try:
service = LoginService.get(name = service_name)
except LoginService.DoesNotExist:
return
FederatedLogin.delete().where(FederatedLogin.user == user,
FederatedLogin.service == service).execute()
def delete_user(user):
user.delete_instance(recursive=True, delete_nullable=True)

View file

@ -408,6 +408,19 @@ class Signout(ApiResource):
return {'success': True}
@resource('/v1/detachexternal/<servicename>')
@internal_only
class DetachExternal(ApiResource):
""" Resource for detaching an external login. """
@require_user_admin
@nickname('detachExternalLogin')
def post(self, servicename):
""" Request that the current user be detached from the external login service. """
model.detach_external_login(get_authenticated_user(), servicename)
return {'success': True}
@resource("/v1/recovery")
@internal_only
class Recovery(ApiResource):

View file

@ -1781,6 +1781,18 @@ function UserAdminCtrl($scope, $timeout, $location, ApiService, PlanService, Use
UIService.showFormError('#changePasswordForm', result);
});
};
$scope.detachExternalLogin = function(kind) {
var params = {
'servicename': kind
};
ApiService.detachExternalLogin(null, params).then(function() {
$scope.hasGithubLogin = false;
$scope.hasGoogleLogin = false;
UserService.load();
}, ApiService.errorDisplay('Count not detach service'));
};
}
function ImageViewCtrl($scope, $routeParams, $rootScope, $timeout, ApiService, ImageMetadataService) {

View file

@ -177,10 +177,14 @@
<div ng-show="hasGithubLogin && githubLogin" class="lead col-md-8">
<i class="fa fa-github fa-lg" style="margin-right: 6px;" data-title="GitHub" bs-tooltip="tooltip.title"></i>
<b><a href="https://github.com/{{githubLogin}}" target="_blank">{{githubLogin}}</a></b>
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
perform-delete="detachExternalLogin('github')"></span>
</div>
<div ng-show="hasGithubLogin && !githubLogin" class="lead col-md-8">
<i class="fa fa-github fa-lg" style="margin-right: 6px;" data-title="GitHub" bs-tooltip="tooltip.title"></i>
Account attached to Github Account
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
perform-delete="detachExternalLogin('github')"></span>
</div>
<div ng-show="!hasGithubLogin" class="col-md-4">
<span class="external-login-button" provider="github" action="attach"></span>
@ -197,10 +201,14 @@
<div ng-show="hasGoogleLogin && googleLogin" class="lead col-md-8">
<i class="fa fa-google fa-lg" style="margin-right: 6px;" data-title="Google" bs-tooltip="tooltip.title"></i>
<b>{{ googleLogin }}</b>
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
perform-delete="detachExternalLogin('google')"></span>
</div>
<div ng-show="hasGoogleLogin && !googleLogin" class="lead col-md-8">
<i class="fa fa-google fa-lg" style="margin-right: 6px;" data-title="Google" bs-tooltip="tooltip.title"></i>
Account attached to Google Account
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
perform-delete="detachExternalLogin('google')"></span>
</div>
<div ng-show="!hasGoogleLogin" class="col-md-4">
<span class="external-login-button" provider="google" action="attach"></span>

View file

@ -24,7 +24,7 @@ from endpoints.api.repoemail import RepositoryAuthorizedEmail
from endpoints.api.repositorynotification import RepositoryNotification, RepositoryNotificationList
from endpoints.api.user import (PrivateRepositories, ConvertToOrganization, Recovery, Signout,
Signin, User, UserAuthorizationList, UserAuthorization, UserNotification,
VerifyUser)
VerifyUser, DetachExternal)
from endpoints.api.repotoken import RepositoryToken, RepositoryTokenList
from endpoints.api.prototype import PermissionPrototype, PermissionPrototypeList
from endpoints.api.logs import UserLogs, OrgLogs, RepositoryLogs
@ -435,6 +435,24 @@ class TestSignin(ApiTestCase):
self._run_test('POST', 403, 'devtable', {u'username': 'E9RY', u'password': 'LQ0N'})
class TestDetachExternal(ApiTestCase):
def setUp(self):
ApiTestCase.setUp(self)
self._set_url(DetachExternal, servicename='someservice')
def test_post_anonymous(self):
self._run_test('POST', 401, None, {})
def test_post_freshuser(self):
self._run_test('POST', 200, 'freshuser', {})
def test_post_reader(self):
self._run_test('POST', 200, 'reader', {})
def test_post_devtable(self):
self._run_test('POST', 200, 'devtable', {})
class TestVerifyUser(ApiTestCase):
def setUp(self):
ApiTestCase.setUp(self)