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 @@ -103,7 +103,7 @@ class TestMyAccountAuthTokens(TestContro response = self.app.post( route_path('my_account_auth_tokens_delete'), - {'del_auth_token': keys[0].api_key, 'csrf_token': self.csrf_token}) + {'del_auth_token': keys[0].user_api_key_id, 'csrf_token': self.csrf_token}) assert_session_flash(response, 'Auth token successfully deleted') user = User.get(user_id) diff --git a/rhodecode/apps/my_account/views.py b/rhodecode/apps/my_account/views.py --- a/rhodecode/apps/my_account/views.py +++ b/rhodecode/apps/my_account/views.py @@ -28,6 +28,7 @@ from pyramid.view import view_config from rhodecode.apps._base import BaseAppView from rhodecode import forms from rhodecode.lib import helpers as h +from rhodecode.lib import audit_logger from rhodecode.lib.ext_json import json from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired from rhodecode.lib.channelstream import channelstream_request, \ @@ -35,7 +36,7 @@ from rhodecode.lib.channelstream import from rhodecode.lib.utils2 import safe_int, md5 from rhodecode.model.auth_token import AuthTokenModel from rhodecode.model.db import ( - Repository, PullRequest, UserEmailMap, User, UserFollowing, joinedload) + Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload) from rhodecode.model.meta import Session from rhodecode.model.scm import RepoList from rhodecode.model.user import UserModel @@ -178,7 +179,13 @@ class MyAccountView(BaseAppView): token = AuthTokenModel().create( c.user.user_id, description, lifetime, role) + token_data = token.get_api_data() + self.maybe_attach_token_scope(token) + audit_logger.store( + action='user.edit.token.add', + action_data={'data': {'token': token_data}}, + user=self._rhodecode_user, ) Session().commit() h.flash(_("Auth token successfully created"), category='success') @@ -196,7 +203,14 @@ class MyAccountView(BaseAppView): del_auth_token = self.request.POST.get('del_auth_token') if del_auth_token: + token = UserApiKeys.get_or_404(del_auth_token, pyramid_exc=True) + token_data = token.get_api_data() + AuthTokenModel().delete(del_auth_token, c.user.user_id) + audit_logger.store( + action='user.edit.token.delete', + action_data={'data': {'token': token_data}}, + user=self._rhodecode_user,) Session().commit() h.flash(_("Auth token successfully deleted"), category='success') @@ -230,6 +244,11 @@ class MyAccountView(BaseAppView): try: UserModel().add_extra_email(c.user.user_id, email) + audit_logger.store( + action='user.edit.email.add', + action_data={'data': {'email': email}}, + user=self._rhodecode_user,) + Session().commit() h.flash(_("Added new email address `%s` for user account") % email, category='success') @@ -253,9 +272,12 @@ class MyAccountView(BaseAppView): del_email_id = self.request.POST.get('del_email_id') if del_email_id: - - UserModel().delete_extra_email( - c.user.user_id, del_email_id) + email = UserEmailMap.get_or_404(del_email_id, pyramid_exc=True).email + UserModel().delete_extra_email(c.user.user_id, del_email_id) + audit_logger.store( + action='user.edit.email.delete', + action_data={'data': {'email': email}}, + user=self._rhodecode_user,) Session().commit() h.flash(_("Email successfully deleted"), category='success') diff --git a/rhodecode/model/auth_token.py b/rhodecode/model/auth_token.py --- a/rhodecode/model/auth_token.py +++ b/rhodecode/model/auth_token.py @@ -59,20 +59,20 @@ class AuthTokenModel(BaseModel): return new_auth_token - def delete(self, api_key, user=None): + def delete(self, auth_token_id, user=None): """ Deletes given api_key, if user is set it also filters the object for deletion by given user. """ - api_key = UserApiKeys.query().filter(UserApiKeys.api_key == api_key) + auth_token = UserApiKeys.query().filter( + UserApiKeys.user_api_key_id == auth_token_id) if user: user = self._get_user(user) - api_key = api_key.filter(UserApiKeys.user_id == user.user_id) - - api_key = api_key.scalar() + auth_token = auth_token.filter(UserApiKeys.user_id == user.user_id) + auth_token = auth_token.scalar() try: - Session().delete(api_key) + Session().delete(auth_token) except Exception: log.error(traceback.format_exc()) raise diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -1018,6 +1018,14 @@ class UserApiKeys(Base, BaseModel): } return data + def get_api_data(self, include_secrets=False): + data = self.__json__() + if include_secrets: + return data + else: + data['auth_token'] = self.token_obfuscated + return data + @property def expired(self): if self.expires == -1: @@ -1049,6 +1057,11 @@ class UserApiKeys(Base, BaseModel): def scope_humanized(self): return self._get_scope() + @property + def token_obfuscated(self): + if self.api_key: + return self.api_key[:4] + "****" + class UserEmailMap(Base, BaseModel): __tablename__ = 'user_email_map' 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 @@ -43,9 +43,9 @@