diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py
--- a/rhodecode/apps/admin/__init__.py
+++ b/rhodecode/apps/admin/__init__.py
@@ -302,6 +302,10 @@ def admin_routes(config):
pattern='/users/{user_id:\d+}/edit/auth_tokens',
user_route=True)
config.add_route(
+ name='edit_user_auth_tokens_view',
+ pattern='/users/{user_id:\d+}/edit/auth_tokens/view',
+ user_route=True)
+ config.add_route(
name='edit_user_auth_tokens_add',
pattern='/users/{user_id:\d+}/edit/auth_tokens/new',
user_route=True)
diff --git a/rhodecode/apps/admin/tests/test_admin_users.py b/rhodecode/apps/admin/tests/test_admin_users.py
--- a/rhodecode/apps/admin/tests/test_admin_users.py
+++ b/rhodecode/apps/admin/tests/test_admin_users.py
@@ -143,7 +143,7 @@ class TestAdminUsersView(TestController)
response = self.app.get(
route_path('edit_user_auth_tokens', user_id=user_id))
for token in auth_tokens:
- response.mustcontain(token)
+ response.mustcontain(token[:4])
response.mustcontain('never')
@pytest.mark.parametrize("desc, lifetime", [
@@ -165,7 +165,7 @@ class TestAdminUsersView(TestController)
response = response.follow()
user = User.get(user_id)
for auth_token in user.auth_tokens:
- response.mustcontain(auth_token)
+ response.mustcontain(auth_token[:4])
def test_delete_auth_token(self, user_util):
self.log_user()
diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py
--- a/rhodecode/apps/admin/views/users.py
+++ b/rhodecode/apps/admin/views/users.py
@@ -804,6 +804,25 @@ class UsersView(UserAppView):
c.role_vcs = AuthTokenModel.cls.ROLE_VCS
return self._get_template_context(c)
+ @LoginRequired()
+ @HasPermissionAllDecorator('hg.admin')
+ @view_config(
+ route_name='edit_user_auth_tokens_view', request_method='POST',
+ renderer='json_ext', xhr=True)
+ def auth_tokens_view(self):
+ _ = self.request.translate
+ c = self.load_default_context()
+ c.user = self.db_user
+
+ auth_token_id = self.request.POST.get('auth_token_id')
+
+ if auth_token_id:
+ token = UserApiKeys.get_or_404(auth_token_id)
+
+ return {
+ 'auth_token': token.api_key
+ }
+
def maybe_attach_token_scope(self, token):
# implemented in EE edition
pass
diff --git a/rhodecode/apps/my_account/__init__.py b/rhodecode/apps/my_account/__init__.py
--- a/rhodecode/apps/my_account/__init__.py
+++ b/rhodecode/apps/my_account/__init__.py
@@ -50,6 +50,9 @@ def includeme(config):
name='my_account_auth_tokens',
pattern=ADMIN_PREFIX + '/my_account/auth_tokens')
config.add_route(
+ name='my_account_auth_tokens_view',
+ pattern=ADMIN_PREFIX + '/my_account/auth_tokens/view')
+ config.add_route(
name='my_account_auth_tokens_add',
pattern=ADMIN_PREFIX + '/my_account/auth_tokens/new')
config.add_route(
diff --git a/rhodecode/apps/my_account/tests/test_my_account_auth_tokens.py b/rhodecode/apps/my_account/tests/test_my_account_auth_tokens.py
--- a/rhodecode/apps/my_account/tests/test_my_account_auth_tokens.py
+++ b/rhodecode/apps/my_account/tests/test_my_account_auth_tokens.py
@@ -49,7 +49,7 @@ class TestMyAccountAuthTokens(TestContro
user = User.get(usr['user_id'])
response = self.app.get(route_path('my_account_auth_tokens'))
for token in user.auth_tokens:
- response.mustcontain(token)
+ response.mustcontain(token[:4])
response.mustcontain('never')
def test_my_account_add_auth_tokens_wrong_csrf(self, user_util):
@@ -79,7 +79,7 @@ class TestMyAccountAuthTokens(TestContro
response = response.follow()
user = User.get(user_id)
for auth_token in user.auth_tokens:
- response.mustcontain(auth_token)
+ response.mustcontain(auth_token[:4])
def test_my_account_delete_auth_token(self, user_util):
user = user_util.create_user(password='qweqwe')
diff --git a/rhodecode/apps/my_account/views/my_account.py b/rhodecode/apps/my_account/views/my_account.py
--- a/rhodecode/apps/my_account/views/my_account.py
+++ b/rhodecode/apps/my_account/views/my_account.py
@@ -25,7 +25,7 @@ import string
import formencode
import formencode.htmlfill
import peppercorn
-from pyramid.httpexceptions import HTTPFound
+from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from pyramid.view import view_config
from rhodecode.apps._base import BaseAppView, DataGridAppView
@@ -164,6 +164,27 @@ class MyAccountView(BaseAppView, DataGri
c.role_vcs = AuthTokenModel.cls.ROLE_VCS
return self._get_template_context(c)
+ @LoginRequired()
+ @NotAnonymous()
+ @CSRFRequired()
+ @view_config(
+ route_name='my_account_auth_tokens_view', request_method='POST', xhr=True,
+ renderer='json_ext')
+ def my_account_auth_tokens_view(self):
+ _ = self.request.translate
+ c = self.load_default_context()
+
+ auth_token_id = self.request.POST.get('auth_token_id')
+
+ if auth_token_id:
+ token = UserApiKeys.get_or_404(auth_token_id)
+ if token.user.user_id != c.user.user_id:
+ raise HTTPNotFound()
+
+ return {
+ 'auth_token': token.api_key
+ }
+
def maybe_attach_token_scope(self, token):
# implemented in EE edition
pass
diff --git a/rhodecode/public/css/tables.less b/rhodecode/public/css/tables.less
--- a/rhodecode/public/css/tables.less
+++ b/rhodecode/public/css/tables.less
@@ -352,7 +352,7 @@ table.dataTable {
margin-bottom: @padding;
table.rctable td:first-child {
- width: 340px;
+ width: 120px;
}
}
diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js
--- a/rhodecode/public/js/rhodecode/routes.js
+++ b/rhodecode/public/js/rhodecode/routes.js
@@ -111,6 +111,7 @@ function registerRCRoutes() {
pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']);
+ pyroutes.register('edit_user_auth_tokens_view', '/_admin/users/%(user_id)s/edit/auth_tokens/view', ['user_id']);
pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
@@ -312,6 +313,7 @@ function registerRCRoutes() {
pyroutes.register('my_account_update', '/_admin/my_account/update', []);
pyroutes.register('my_account_password', '/_admin/my_account/password', []);
pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
+ pyroutes.register('my_account_auth_tokens_view', '/_admin/my_account/auth_tokens/view', []);
pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
diff --git a/rhodecode/public/js/src/rhodecode/users.js b/rhodecode/public/js/src/rhodecode/users.js
--- a/rhodecode/public/js/src/rhodecode/users.js
+++ b/rhodecode/public/js/src/rhodecode/users.js
@@ -47,3 +47,72 @@ var UsersAutoComplete = function(input_i
lookupFilter: autocompleteFilterResult
});
};
+
+var _showAuthToken = function (authTokenId, showUrl) {
+
+ Swal.fire({
+ title: _gettext('Show this authentication token?'),
+ showCancelButton: true,
+ confirmButtonColor: '#84a5d2',
+ cancelButtonColor: '#e85e4d',
+ showClass: {
+ popup: 'swal2-noanimation',
+ backdrop: 'swal2-noanimation'
+ },
+ hideClass: {
+ popup: '',
+ backdrop: ''
+ },
+ confirmButtonText: _gettext('Show'),
+ showLoaderOnConfirm: true,
+ allowOutsideClick: function () {
+ !Swal.isLoading()
+ },
+ preConfirm: function () {
+
+ var postData = {
+ 'auth_token_id': authTokenId,
+ 'csrf_token': CSRF_TOKEN
+ };
+ return new Promise(function (resolve, reject) {
+ $.ajax({
+ type: 'POST',
+ data: postData,
+ url: showUrl,
+ headers: {'X-PARTIAL-XHR': true}
+ })
+ .done(function (data) {
+ resolve(data);
+ })
+ .fail(function (jqXHR, textStatus, errorThrown) {
+ //reject("Failed to fetch Authentication Token")
+ var message = formatErrorMessage(jqXHR, textStatus, errorThrown)
+ Swal.showValidationMessage('Request failed: {0}'.format(message)
+ )
+ });
+ })
+ }
+
+ })
+ .then(function (result) {
+ if (result.value) {
+ var tmpl = ('{0}
' +
+ '');
+
+ Swal.fire({
+ title: _gettext('Authentication Token'),
+ html: tmpl.format(result.value.auth_token, result.value.auth_token),
+ confirmButtonColor: '#84a5d2',
+ cancelButtonColor: '#e85e4d',
+ showClass: {
+ popup: 'swal2-noanimation',
+ backdrop: 'swal2-noanimation'
+ },
+ hideClass: {
+ popup: '',
+ backdrop: ''
+ },
+ })
+ }
+ })
+}
\ No newline at end of file
diff --git a/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako b/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako
--- a/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako
+++ b/rhodecode/templates/admin/my_account/my_account_auth_tokens.mako
@@ -1,4 +1,10 @@