diff --git a/kallithea/config/routing.py b/kallithea/config/routing.py
--- a/kallithea/config/routing.py
+++ b/kallithea/config/routing.py
@@ -358,6 +358,13 @@ def make_map(config):
m.connect("my_account_api_keys_delete", "/my_account/api_keys/delete",
action="my_account_api_keys_delete", conditions=dict(method=["POST"]))
+ m.connect("my_account_ssh_keys", "/my_account/ssh_keys",
+ action="my_account_ssh_keys", conditions=dict(method=["GET"]))
+ m.connect("my_account_ssh_keys", "/my_account/ssh_keys",
+ action="my_account_ssh_keys_add", conditions=dict(method=["POST"]))
+ m.connect("my_account_ssh_keys_delete", "/my_account/ssh_keys/delete",
+ action="my_account_ssh_keys_delete", conditions=dict(method=["POST"]))
+
# ADMIN GIST
with rmap.submapper(path_prefix=ADMIN_PREFIX,
controller='admin/gists') as m:
diff --git a/kallithea/controllers/admin/my_account.py b/kallithea/controllers/admin/my_account.py
--- a/kallithea/controllers/admin/my_account.py
+++ b/kallithea/controllers/admin/my_account.py
@@ -39,13 +39,14 @@ from kallithea.config.routing import url
from kallithea.lib import helpers as h
from kallithea.lib import auth_modules
from kallithea.lib.auth import LoginRequired, AuthUser
-from kallithea.lib.base import BaseController, render
+from kallithea.lib.base import BaseController, render, IfSshEnabled
from kallithea.lib.utils2 import generate_api_key, safe_int
from kallithea.model.db import Repository, UserEmailMap, User, UserFollowing
from kallithea.model.forms import UserForm, PasswordChangeForm
from kallithea.model.user import UserModel
from kallithea.model.repo import RepoModel
from kallithea.model.api_key import ApiKeyModel
+from kallithea.model.ssh_key import SshKeyModel
from kallithea.model.meta import Session
log = logging.getLogger(__name__)
@@ -259,3 +260,28 @@ class MyAccountController(BaseController
h.flash(_("API key successfully deleted"), category='success')
raise HTTPFound(location=url('my_account_api_keys'))
+
+ @IfSshEnabled
+ def my_account_ssh_keys(self):
+ c.active = 'ssh_keys'
+ self.__load_data()
+ c.user_ssh_keys = SshKeyModel().get_ssh_keys(request.authuser.user_id)
+ return render('admin/my_account/my_account.html')
+
+ @IfSshEnabled
+ def my_account_ssh_keys_add(self):
+ description = request.POST.get('description')
+ public_key = request.POST.get('public_key')
+ new_ssh_key = SshKeyModel().create(request.authuser.user_id,
+ description, public_key)
+ Session().commit()
+ h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
+ raise HTTPFound(location=url('my_account_ssh_keys'))
+
+ @IfSshEnabled
+ def my_account_ssh_keys_delete(self):
+ public_key = request.POST.get('del_public_key')
+ SshKeyModel().delete(public_key, request.authuser.user_id)
+ Session().commit()
+ h.flash(_("SSH key successfully deleted"), category='success')
+ raise HTTPFound(location=url('my_account_ssh_keys'))
diff --git a/kallithea/templates/admin/my_account/my_account.html b/kallithea/templates/admin/my_account/my_account.html
--- a/kallithea/templates/admin/my_account/my_account.html
+++ b/kallithea/templates/admin/my_account/my_account.html
@@ -25,6 +25,9 @@
${_('Profile')}
${_('Email Addresses')}
${_('Password')}
+ %if c.ssh_enabled:
+ ${_('SSH Keys')}
+ %endif
${_('API Keys')}
${_('Owned Repositories')}
${_('Watched Repositories')}
diff --git a/kallithea/templates/admin/my_account/my_account_ssh_keys.html b/kallithea/templates/admin/my_account/my_account_ssh_keys.html
new file mode 100644
--- /dev/null
+++ b/kallithea/templates/admin/my_account/my_account_ssh_keys.html
@@ -0,0 +1,63 @@
+
+ %if c.user_ssh_keys:
+
+ | ${_('Fingerprint')} |
+ ${_('Description')} |
+ ${_('Action')} |
+
+ %for ssh_key in c.user_ssh_keys:
+
+ |
+ ${ssh_key.fingerprint}
+ |
+
+ ${ssh_key.description}
+ |
+
+ ${h.form(url('my_account_ssh_keys_delete'))}
+ ${h.hidden('del_public_key', ssh_key.public_key)}
+
+ ${h.end_form()}
+ |
+
+ %endfor
+ %else:
+
+ |
+ ${_('No SSH keys have been added')}
+ |
+
+ %endif
+
+
+
+ ${h.form(url('my_account_ssh_keys'))}
+
+ ${h.end_form()}
+
diff --git a/kallithea/tests/functional/test_my_account.py b/kallithea/tests/functional/test_my_account.py
--- a/kallithea/tests/functional/test_my_account.py
+++ b/kallithea/tests/functional/test_my_account.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from kallithea.model.db import User, UserFollowing, Repository, UserApiKeys
+from kallithea.model.db import User, UserFollowing, Repository, UserApiKeys, UserSshKeys
from kallithea.tests.base import *
from kallithea.tests.fixture import Fixture
from kallithea.lib import helpers as h
@@ -249,3 +249,47 @@ class TestMyAccountController(TestContro
self.checkSessionFlash(response, 'API key successfully reset')
response = response.follow()
response.mustcontain(no=[api_key])
+
+ def test_my_account_add_ssh_key(self):
+ description = u'something'
+ public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
+ fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+
+ self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS)
+ response = self.app.post(url('my_account_ssh_keys'),
+ {'description': description,
+ 'public_key': public_key,
+ '_authentication_token': self.authentication_token()})
+ self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint)
+
+ response = response.follow()
+ response.mustcontain(fingerprint)
+ user_id = response.session['authuser']['user_id']
+ ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one()
+ assert ssh_key.fingerprint == fingerprint
+ assert ssh_key.description == description
+ Session().delete(ssh_key)
+ Session().commit()
+
+ def test_my_account_remove_ssh_key(self):
+ description = u''
+ public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost'
+ fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8'
+
+ self.log_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS)
+ response = self.app.post(url('my_account_ssh_keys'),
+ {'description': description,
+ 'public_key': public_key,
+ '_authentication_token': self.authentication_token()})
+ self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint)
+ response.follow()
+ user_id = response.session['authuser']['user_id']
+ ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one()
+ assert ssh_key.description == description
+
+ response = self.app.post(url('my_account_ssh_keys_delete'),
+ {'del_public_key': ssh_key.public_key,
+ '_authentication_token': self.authentication_token()})
+ self.checkSessionFlash(response, 'SSH key successfully deleted')
+ keys = UserSshKeys.query().all()
+ assert 0 == len(keys)