Show More
@@ -0,0 +1,63 b'' | |||
|
1 | <table class="table"> | |
|
2 | %if c.user_ssh_keys: | |
|
3 | <tr> | |
|
4 | <th>${_('Fingerprint')}</th> | |
|
5 | <th>${_('Description')}</th> | |
|
6 | <th>${_('Action')}</th> | |
|
7 | </tr> | |
|
8 | %for ssh_key in c.user_ssh_keys: | |
|
9 | <tr> | |
|
10 | <td> | |
|
11 | ${ssh_key.fingerprint} | |
|
12 | </td> | |
|
13 | <td> | |
|
14 | ${ssh_key.description} | |
|
15 | </td> | |
|
16 | <td> | |
|
17 | ${h.form(url('edit_user_ssh_keys_delete', id=c.user.user_id))} | |
|
18 | ${h.hidden('del_public_key', ssh_key.public_key)} | |
|
19 | <button class="btn btn-danger btn-xs" type="submit" | |
|
20 | onclick="return confirm('${_('Confirm to remove this SSH key: %s') % ssh_key.fingerprint}');"> | |
|
21 | <i class="icon-trashcan"></i> | |
|
22 | ${_('Remove')} | |
|
23 | </button> | |
|
24 | ${h.end_form()} | |
|
25 | </td> | |
|
26 | </tr> | |
|
27 | %endfor | |
|
28 | %else: | |
|
29 | <tr> | |
|
30 | <td> | |
|
31 | <div class="ip">${_('No SSH keys have been added')}</div> | |
|
32 | </td> | |
|
33 | </tr> | |
|
34 | %endif | |
|
35 | </table> | |
|
36 | ||
|
37 | <div> | |
|
38 | ${h.form(url('edit_user_ssh_keys', id=c.user.user_id))} | |
|
39 | <div class="form"> | |
|
40 | <div class="form-group"> | |
|
41 | <label class="control-label">${_('New SSH key')}</label> | |
|
42 | </div> | |
|
43 | <div class="form-group"> | |
|
44 | <label class="control-label" for="public_key">${_('Public key')}:</label> | |
|
45 | <div> | |
|
46 | ${h.textarea('public_key', '', class_='form-control', placeholder=_('Public key (contents of e.g. ~/.ssh/id_rsa.pub)'), cols=80, rows=5)} | |
|
47 | </div> | |
|
48 | </div> | |
|
49 | <div class="form-group"> | |
|
50 | <label class="control-label" for="description">${_('Description')}:</label> | |
|
51 | <div> | |
|
52 | ${h.text('description', class_='form-control', placeholder=_('Description'))} | |
|
53 | </div> | |
|
54 | </div> | |
|
55 | <div class="form-group"> | |
|
56 | <div class="buttons"> | |
|
57 | ${h.submit('save', _('Add'), class_="btn btn-default")} | |
|
58 | ${h.reset('reset', _('Reset'), class_="btn btn-default")} | |
|
59 | </div> | |
|
60 | </div> | |
|
61 | </div> | |
|
62 | ${h.end_form()} | |
|
63 | </div> |
@@ -97,6 +97,7 b' List of contributors to Kallithea projec' | |||
|
97 | 97 | Aparkar <aparkar@icloud.com> 2013 |
|
98 | 98 | Dennis Brakhane <brakhane@googlemail.com> 2013 |
|
99 | 99 | Grzegorz Rożniecki <xaerxess@gmail.com> 2013 |
|
100 | Ilya Beda <ir4y.ix@gmail.com> 2013 | |
|
100 | 101 | Jonathan Sternberg <jonathansternberg@gmail.com> 2013 |
|
101 | 102 | Leonardo Carneiro <leonardo@unity3d.com> 2013 |
|
102 | 103 | Magnus Ericmats <magnus.ericmats@gmail.com> 2013 |
@@ -183,6 +183,13 b' def make_map(config):' | |||
|
183 | 183 | m.connect("edit_user_api_keys_delete", "/users/{id}/edit/api_keys/delete", |
|
184 | 184 | action="delete_api_key", conditions=dict(method=["POST"])) |
|
185 | 185 | |
|
186 | m.connect("edit_user_ssh_keys", "/users/{id}/edit/ssh_keys", | |
|
187 | action="edit_ssh_keys", conditions=dict(method=["GET"])) | |
|
188 | m.connect("edit_user_ssh_keys", "/users/{id}/edit/ssh_keys", | |
|
189 | action="ssh_keys_add", conditions=dict(method=["POST"])) | |
|
190 | m.connect("edit_user_ssh_keys_delete", "/users/{id}/edit/ssh_keys/delete", | |
|
191 | action="ssh_keys_delete", conditions=dict(method=["POST"])) | |
|
192 | ||
|
186 | 193 | m.connect("edit_user_perms", "/users/{id}/edit/permissions", |
|
187 | 194 | action="edit_perms", conditions=dict(method=["GET"])) |
|
188 | 195 | m.connect("edit_user_perms_update", "/users/{id}/edit/permissions", |
@@ -43,9 +43,9 b' from kallithea.lib import helpers as h' | |||
|
43 | 43 | from kallithea.lib.auth import LoginRequired, HasPermissionAnyDecorator, \ |
|
44 | 44 | AuthUser |
|
45 | 45 | from kallithea.lib import auth_modules |
|
46 | from kallithea.lib.base import BaseController, render | |
|
46 | from kallithea.lib.base import BaseController, render, IfSshEnabled | |
|
47 | 47 | from kallithea.model.api_key import ApiKeyModel |
|
48 | ||
|
48 | from kallithea.model.ssh_key import SshKeyModel | |
|
49 | 49 | from kallithea.model.db import User, UserEmailMap, UserIpMap, UserToPerm |
|
50 | 50 | from kallithea.model.forms import UserForm, CustomDefaultPermissionsForm |
|
51 | 51 | from kallithea.model.user import UserModel |
@@ -429,3 +429,37 b' class UsersController(BaseController):' | |||
|
429 | 429 | if 'default_user' in request.POST: |
|
430 | 430 | raise HTTPFound(location=url('admin_permissions_ips')) |
|
431 | 431 | raise HTTPFound(location=url('edit_user_ips', id=id)) |
|
432 | ||
|
433 | @IfSshEnabled | |
|
434 | def edit_ssh_keys(self, id): | |
|
435 | c.user = self._get_user_or_raise_if_default(id) | |
|
436 | c.active = 'ssh_keys' | |
|
437 | c.user_ssh_keys = SshKeyModel().get_ssh_keys(c.user.user_id) | |
|
438 | defaults = c.user.get_dict() | |
|
439 | return htmlfill.render( | |
|
440 | render('admin/users/user_edit.html'), | |
|
441 | defaults=defaults, | |
|
442 | encoding="UTF-8", | |
|
443 | force_defaults=False) | |
|
444 | ||
|
445 | @IfSshEnabled | |
|
446 | def ssh_keys_add(self, id): | |
|
447 | c.user = self._get_user_or_raise_if_default(id) | |
|
448 | ||
|
449 | description = request.POST.get('description') | |
|
450 | public_key = request.POST.get('public_key') | |
|
451 | new_ssh_key = SshKeyModel().create(c.user.user_id, | |
|
452 | description, public_key) | |
|
453 | Session().commit() | |
|
454 | h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success') | |
|
455 | raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id)) | |
|
456 | ||
|
457 | @IfSshEnabled | |
|
458 | def ssh_keys_delete(self, id): | |
|
459 | c.user = self._get_user_or_raise_if_default(id) | |
|
460 | ||
|
461 | public_key = request.POST.get('del_public_key') | |
|
462 | SshKeyModel().delete(public_key, c.user.user_id) | |
|
463 | Session().commit() | |
|
464 | h.flash(_("SSH key successfully deleted"), category='success') | |
|
465 | raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id)) |
@@ -121,6 +121,7 b'' | |||
|
121 | 121 | <li>Copyright © 2012–2013, xpol</li> |
|
122 | 122 | <li>Copyright © 2013, Dennis Brakhane</li> |
|
123 | 123 | <li>Copyright © 2013, Grzegorz Rożniecki</li> |
|
124 | <li>Copyright © 2013, Ilya Beda</li> | |
|
124 | 125 | <li>Copyright © 2013, Jonathan Sternberg</li> |
|
125 | 126 | <li>Copyright © 2013, Leonardo Carneiro</li> |
|
126 | 127 | <li>Copyright © 2013, Magnus Ericmats</li> |
@@ -28,6 +28,9 b'' | |||
|
28 | 28 | <ul class="nav nav-pills nav-stacked"> |
|
29 | 29 | <li class="${'active' if c.active=='profile' else ''}"><a href="${h.url('edit_user', id=c.user.user_id)}">${_('Profile')}</a></li> |
|
30 | 30 | <li class="${'active' if c.active=='emails' else ''}"><a href="${h.url('edit_user_emails', id=c.user.user_id)}">${_('Emails')}</a></li> |
|
31 | %if c.ssh_enabled: | |
|
32 | <li class="${'active' if c.active=='ssh_keys' else ''}"><a href="${h.url('edit_user_ssh_keys', id=c.user.user_id)}">${_('SSH Keys')}</a></li> | |
|
33 | %endif | |
|
31 | 34 | <li class="${'active' if c.active=='api_keys' else ''}"><a href="${h.url('edit_user_api_keys', id=c.user.user_id)}">${_('API Keys')}</a></li> |
|
32 | 35 | <li class="${'active' if c.active=='ips' else ''}"><a href="${h.url('edit_user_ips', id=c.user.user_id)}">${_('IP Whitelist')}</a></li> |
|
33 | 36 | <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_advanced', id=c.user.user_id)}">${_('Advanced')}</a></li> |
@@ -18,7 +18,7 b' import pytest' | |||
|
18 | 18 | from kallithea.tests.base import * |
|
19 | 19 | from kallithea.tests.fixture import Fixture |
|
20 | 20 | from kallithea.controllers.admin.users import UsersController |
|
21 | from kallithea.model.db import User, Permission, UserIpMap, UserApiKeys, RepoGroup | |
|
21 | from kallithea.model.db import User, Permission, UserIpMap, UserApiKeys, RepoGroup, UserSshKeys | |
|
22 | 22 | from kallithea.lib.auth import check_password |
|
23 | 23 | from kallithea.model.user import UserModel |
|
24 | 24 | from kallithea.model import validators |
@@ -514,6 +514,54 b' class TestAdminUsersController(TestContr' | |||
|
514 | 514 | response = response.follow() |
|
515 | 515 | response.mustcontain(no=[api_key]) |
|
516 | 516 | |
|
517 | def test_add_ssh_key(self): | |
|
518 | description = u'something' | |
|
519 | public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost' | |
|
520 | fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8' | |
|
521 | ||
|
522 | self.log_user() | |
|
523 | user = User.get_by_username(TEST_USER_REGULAR_LOGIN) | |
|
524 | user_id = user.user_id | |
|
525 | ||
|
526 | response = self.app.post(url('edit_user_ssh_keys', id=user_id), | |
|
527 | {'description': description, | |
|
528 | 'public_key': public_key, | |
|
529 | '_authentication_token': self.authentication_token()}) | |
|
530 | self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint) | |
|
531 | ||
|
532 | response = response.follow() | |
|
533 | response.mustcontain(fingerprint) | |
|
534 | ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one() | |
|
535 | assert ssh_key.fingerprint == fingerprint | |
|
536 | assert ssh_key.description == description | |
|
537 | Session().delete(ssh_key) | |
|
538 | Session().commit() | |
|
539 | ||
|
540 | def test_remove_ssh_key(self): | |
|
541 | description = u'' | |
|
542 | public_key = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC6Ycnc2oUZHQnQwuqgZqTTdMDZD7ataf3JM7oG2Fw8JR6cdmz4QZLe5mfDwaFwG2pWHLRpVqzfrD/Pn3rIO++bgCJH5ydczrl1WScfryV1hYMJ/4EzLGM657J1/q5EI+b9SntKjf4ax+KP322L0TNQGbZUHLbfG2MwHMrYBQpHUQ== me@localhost' | |
|
543 | fingerprint = u'Ke3oUCNJM87P0jJTb3D+e3shjceP2CqMpQKVd75E9I8' | |
|
544 | ||
|
545 | self.log_user() | |
|
546 | user = User.get_by_username(TEST_USER_REGULAR_LOGIN) | |
|
547 | user_id = user.user_id | |
|
548 | ||
|
549 | response = self.app.post(url('edit_user_ssh_keys', id=user_id), | |
|
550 | {'description': description, | |
|
551 | 'public_key': public_key, | |
|
552 | '_authentication_token': self.authentication_token()}) | |
|
553 | self.checkSessionFlash(response, 'SSH key %s successfully added' % fingerprint) | |
|
554 | response.follow() | |
|
555 | ssh_key = UserSshKeys.query().filter(UserSshKeys.user_id == user_id).one() | |
|
556 | assert ssh_key.description == description | |
|
557 | ||
|
558 | response = self.app.post(url('edit_user_ssh_keys_delete', id=user_id), | |
|
559 | {'del_public_key': ssh_key.public_key, | |
|
560 | '_authentication_token': self.authentication_token()}) | |
|
561 | self.checkSessionFlash(response, 'SSH key successfully deleted') | |
|
562 | keys = UserSshKeys.query().all() | |
|
563 | assert 0 == len(keys) | |
|
564 | ||
|
517 | 565 | |
|
518 | 566 | class TestAdminUsersController_unittest(TestController): |
|
519 | 567 | """ Unit tests for the users controller """ |
General Comments 0
You need to be logged in to leave comments.
Login now