mirror of
https://github.com/getredash/redash.git
synced 2025-12-25 01:03:20 -05:00
Add regenerate function of user's API key (#3224)
* Add regenerate function of user's API Key * Update client/app/pages/users/show.js Co-Authored-By: kyoshidajp <claddvd@gmail.com> * Remove unused error message * Refactoring: Inline temp * Update client/app/pages/users/show.js Co-Authored-By: kyoshidajp <claddvd@gmail.com> * Change action event of regenerate user API key
This commit is contained in:
committed by
Arik Fraimovich
parent
b91d4bdcaf
commit
b3643ffbb7
@@ -43,6 +43,9 @@
|
||||
<label class="control-label">API Key</label>
|
||||
<input type="text" class="form-control" value="{{user.api_key}}" size="44" readonly/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-default" ng-click="regenerateUserApiKey(user)" ng-disabled="disableRegenerateApiKeyButton">Regenerate</button>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import './settings.less';
|
||||
|
||||
function UserCtrl(
|
||||
$scope, $routeParams, $http, $location, toastr,
|
||||
clientConfig, currentUser, User,
|
||||
clientConfig, currentUser, User, AlertDialog,
|
||||
) {
|
||||
$scope.userId = $routeParams.userId;
|
||||
$scope.currentUser = currentUser;
|
||||
@@ -122,6 +122,34 @@ function UserCtrl(
|
||||
$scope.disableUser = (user) => {
|
||||
User.disableUser(user);
|
||||
};
|
||||
|
||||
$scope.regenerateUserApiKey = (user) => {
|
||||
const doRegenerate = () => {
|
||||
$scope.disableRegenerateApiKeyButton = true;
|
||||
$http
|
||||
.post(`api/users/${$scope.user.id}/regenerate_api_key`)
|
||||
.success((data) => {
|
||||
toastr.success('The API Key has been updated.');
|
||||
user.api_key = data.api_key;
|
||||
$scope.disableRegenerateApiKeyButton = false;
|
||||
})
|
||||
.error((response) => {
|
||||
const message =
|
||||
response.message
|
||||
? response.message
|
||||
: `Failed regenerating API Key: ${response.statusText}`;
|
||||
|
||||
toastr.error(message);
|
||||
$scope.disableRegenerateApiKeyButton = false;
|
||||
});
|
||||
};
|
||||
|
||||
const title = 'Regenerate API Key';
|
||||
const message = 'Are you sure you want to regenerate?';
|
||||
|
||||
AlertDialog.open(title, message, { class: 'btn-warning', title: 'Regenerate' })
|
||||
.then(doRegenerate);
|
||||
};
|
||||
}
|
||||
|
||||
export default function init(ngModule) {
|
||||
|
||||
@@ -11,7 +11,7 @@ from redash.handlers.data_sources import DataSourceTypeListResource, DataSourceL
|
||||
from redash.handlers.events import EventsResource
|
||||
from redash.handlers.queries import QueryForkResource, QueryRefreshResource, QueryListResource, QueryRecentResource, QuerySearchResource, QueryResource, MyQueriesResource
|
||||
from redash.handlers.query_results import QueryResultListResource, QueryResultResource, JobResource
|
||||
from redash.handlers.users import UserResource, UserListResource, UserInviteResource, UserResetPasswordResource, UserDisableResource
|
||||
from redash.handlers.users import UserResource, UserListResource, UserInviteResource, UserResetPasswordResource, UserDisableResource, UserRegenerateApiKeyResource
|
||||
from redash.handlers.visualizations import VisualizationListResource
|
||||
from redash.handlers.visualizations import VisualizationResource
|
||||
from redash.handlers.widgets import WidgetResource, WidgetListResource
|
||||
@@ -101,6 +101,9 @@ api.add_org_resource(UserListResource, '/api/users', endpoint='users')
|
||||
api.add_org_resource(UserResource, '/api/users/<user_id>', endpoint='user')
|
||||
api.add_org_resource(UserInviteResource, '/api/users/<user_id>/invite', endpoint='user_invite')
|
||||
api.add_org_resource(UserResetPasswordResource, '/api/users/<user_id>/reset_password', endpoint='user_reset_password')
|
||||
api.add_org_resource(UserRegenerateApiKeyResource,
|
||||
'/api/users/<user_id>/regenerate_api_key',
|
||||
endpoint='user_regenerate_api_key')
|
||||
api.add_org_resource(UserDisableResource, '/api/users/<user_id>/disable', endpoint='user_disable')
|
||||
|
||||
api.add_org_resource(VisualizationListResource, '/api/visualizations', endpoint='visualizations')
|
||||
|
||||
@@ -149,6 +149,26 @@ class UserResetPasswordResource(BaseResource):
|
||||
}
|
||||
|
||||
|
||||
class UserRegenerateApiKeyResource(BaseResource):
|
||||
def post(self, user_id):
|
||||
user = models.User.get_by_id_and_org(user_id, self.current_org)
|
||||
if user.is_disabled:
|
||||
abort(404, message='Not found')
|
||||
if not is_admin_or_owner(user_id):
|
||||
abort(403)
|
||||
|
||||
user.regenerate_api_key()
|
||||
models.db.session.commit()
|
||||
|
||||
self.record_event({
|
||||
'action': 'regnerate_api_key',
|
||||
'object_id': user.id,
|
||||
'object_type': 'user'
|
||||
})
|
||||
|
||||
return user.to_dict(with_api_key=True)
|
||||
|
||||
|
||||
class UserResource(BaseResource):
|
||||
def get(self, user_id):
|
||||
require_permission_or_owner('list_users', user_id)
|
||||
|
||||
@@ -122,6 +122,9 @@ class User(TimestampMixin, db.Model, BelongsToOrgMixin, UserMixin, PermissionsCh
|
||||
def enable(self):
|
||||
self.disabled_at = None
|
||||
|
||||
def regenerate_api_key(self):
|
||||
self.api_key = generate_token(40)
|
||||
|
||||
def to_dict(self, with_api_key=False):
|
||||
profile_image_url = self.profile_image_url
|
||||
if self.is_disabled:
|
||||
|
||||
@@ -328,3 +328,47 @@ class TestUserDisable(BaseTestCase):
|
||||
rv = self.make_request('post', '/api/users/{}/reset_password'.format(user.id), user=admin_user)
|
||||
self.assertEqual(rv.status_code, 404)
|
||||
send_password_reset_email_mock.assert_not_called()
|
||||
|
||||
|
||||
class TestUserRegenerateApiKey(BaseTestCase):
|
||||
def test_non_admin_cannot_regenerate_other_user_api_key(self):
|
||||
admin_user = self.factory.create_admin()
|
||||
other_user = self.factory.create_user()
|
||||
orig_api_key = other_user.api_key
|
||||
|
||||
rv = self.make_request('post', "/api/users/{}/regenerate_api_key".format(other_user.id), user=admin_user)
|
||||
self.assertEqual(rv.status_code, 200)
|
||||
|
||||
other_user = models.User.query.get(other_user.id)
|
||||
self.assertNotEquals(orig_api_key, other_user.api_key)
|
||||
|
||||
def test_admin_can_regenerate_other_user_api_key(self):
|
||||
user1 = self.factory.create_user()
|
||||
user2 = self.factory.create_user()
|
||||
orig_user2_api_key = user2.api_key
|
||||
|
||||
rv = self.make_request('post', "/api/users/{}/regenerate_api_key".format(user2.id), user=user1)
|
||||
self.assertEqual(rv.status_code, 403)
|
||||
|
||||
user = models.User.query.get(user2.id)
|
||||
self.assertEquals(orig_user2_api_key, user.api_key)
|
||||
|
||||
def test_admin_can_regenerate_api_key_myself(self):
|
||||
admin_user = self.factory.create_admin()
|
||||
orig_api_key = admin_user.api_key
|
||||
|
||||
rv = self.make_request('post', "/api/users/{}/regenerate_api_key".format(admin_user.id), user=admin_user)
|
||||
self.assertEqual(rv.status_code, 200)
|
||||
|
||||
user = models.User.query.get(admin_user.id)
|
||||
self.assertNotEquals(orig_api_key, user.api_key)
|
||||
|
||||
def test_user_can_regenerate_api_key_myself(self):
|
||||
user = self.factory.create_user()
|
||||
orig_api_key = user.api_key
|
||||
|
||||
rv = self.make_request('post', "/api/users/{}/regenerate_api_key".format(user.id), user=user)
|
||||
self.assertEqual(rv.status_code, 200)
|
||||
|
||||
user = models.User.query.get(user.id)
|
||||
self.assertNotEquals(orig_api_key, user.api_key)
|
||||
|
||||
@@ -62,6 +62,17 @@ class TestUserSearch(BaseTestCase):
|
||||
assert user in User.search(User.all(user.org), term=u'א')
|
||||
|
||||
|
||||
class TestUserRegenerateApiKey(BaseTestCase):
|
||||
def test_regenerate_api_key(self):
|
||||
user = self.factory.user
|
||||
before_api_key = user.api_key
|
||||
user.regenerate_api_key()
|
||||
|
||||
# check committed by research
|
||||
user = User.query.get(user.id)
|
||||
self.assertNotEquals(user.api_key, before_api_key)
|
||||
|
||||
|
||||
class TestUserDetail(BaseTestCase):
|
||||
# def setUp(self):
|
||||
# super(TestUserDetail, self).setUp()
|
||||
@@ -94,4 +105,4 @@ class TestUserDetail(BaseTestCase):
|
||||
|
||||
user_reloaded = User.query.filter(User.id==user.id).first()
|
||||
self.assertIn('active_at', user_reloaded.details)
|
||||
self.assertEqual(user_reloaded.active_at, timestamp)
|
||||
self.assertEqual(user_reloaded.active_at, timestamp)
|
||||
|
||||
Reference in New Issue
Block a user