Orgs: allow setting org admin via web interface / PATCH request
This commit is contained in:
parent
a5d11ec31b
commit
f1edb901d1
@ -144,6 +144,22 @@ class OrgManager:
|
||||
|
||||
return org_doc
|
||||
|
||||
def assign_admin(self, org_id: bson.ObjectId, *, user_id: bson.ObjectId):
|
||||
"""Assigns a user as admin user for this organization."""
|
||||
|
||||
assert isinstance(org_id, bson.ObjectId)
|
||||
assert isinstance(user_id, bson.ObjectId)
|
||||
|
||||
org_coll = current_app.db('organizations')
|
||||
users_coll = current_app.db('users')
|
||||
|
||||
if users_coll.count({'_id': user_id}) == 0:
|
||||
raise ValueError('User not found')
|
||||
|
||||
self._log.info('Updating organization %s, setting admin user to %s', org_id, user_id)
|
||||
org_coll.update_one({'_id': org_id},
|
||||
{'$set': {'admin_uid': user_id}})
|
||||
|
||||
def remove_user(self,
|
||||
org_id: bson.ObjectId,
|
||||
*,
|
||||
|
@ -64,6 +64,26 @@ class OrganizationPatchHandler(patch_handler.AbstractPatchHandler):
|
||||
org_doc = current_app.org_manager.assign_single_user(org_id, user_id=user_oid)
|
||||
return jsonify(org_doc)
|
||||
|
||||
@authorization.require_login()
|
||||
def patch_assign_admin(self, org_id: bson.ObjectId, patch: dict):
|
||||
"""Assigns a single user by User ID as admin of the organization.
|
||||
|
||||
The calling user must be admin of the organization.
|
||||
"""
|
||||
|
||||
self._assert_is_admin(org_id)
|
||||
|
||||
# Do some basic validation.
|
||||
try:
|
||||
user_id = patch['user_id']
|
||||
except KeyError:
|
||||
raise wz_exceptions.BadRequest('No key "user_id" in patch.')
|
||||
|
||||
user_oid = str2id(user_id)
|
||||
log.info('User %s uses PATCH to set user %s as admin for organization %s',
|
||||
current_user().user_id, user_oid, org_id)
|
||||
current_app.org_manager.assign_admin(org_id, user_id=user_oid)
|
||||
|
||||
@authorization.require_login()
|
||||
def patch_remove_user(self, org_id: bson.ObjectId, patch: dict):
|
||||
"""Removes a user from an organization.
|
||||
|
@ -9,8 +9,7 @@ from pillar import current_app
|
||||
from pillar.api.utils import authorization, str2id, gravatar
|
||||
from pillar.web.system_util import pillar_api
|
||||
|
||||
|
||||
from pillarsdk import Organization
|
||||
from pillarsdk import Organization, User
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
blueprint = Blueprint('pillar.web.organizations', __name__, url_prefix='/organizations')
|
||||
@ -51,6 +50,8 @@ def view_embed(organization_id: str):
|
||||
member['avatar'] = gravatar(member.get('email'))
|
||||
member['_id'] = str(member['_id'])
|
||||
|
||||
admin_user = User.find(organization.admin_uid, api=api)
|
||||
|
||||
# Make sure it's never None
|
||||
organization.unknown_members = organization.unknown_members or []
|
||||
|
||||
@ -61,6 +62,7 @@ def view_embed(organization_id: str):
|
||||
|
||||
return render_template('organizations/view_embed.html',
|
||||
organization=organization,
|
||||
admin_user=admin_user,
|
||||
members=members,
|
||||
can_edit=can_edit,
|
||||
can_super_edit=can_super_edit,
|
||||
|
@ -39,6 +39,12 @@
|
||||
placeholder="Organization roles",
|
||||
value="{{ organization.org_roles | hide_none | sort | join(' ') }}")
|
||||
| {% endif %}
|
||||
.input-group
|
||||
input#admin-select.form-control(
|
||||
name='admin_user',
|
||||
type='text',
|
||||
placeholder='Administrator',
|
||||
value='{{ admin_user.full_name }}')
|
||||
.input-group
|
||||
button#item-save.btn.btn-default.btn-block(type='submit')
|
||||
i.pi-check
|
||||
@ -49,6 +55,7 @@
|
||||
p.item-description {{ organization.description | hide_none }}
|
||||
p.item-website {{ organization.website | hide_none }}
|
||||
p.item-location {{ organization.location | hide_none }}
|
||||
p.item-admin-user {{ admin_user.full_name }}
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
@ -201,6 +208,14 @@ script.
|
||||
}
|
||||
}
|
||||
);
|
||||
$('#admin-select').userSearch(
|
||||
'{{config.ALGOLIA_USER}}',
|
||||
'{{config.ALGOLIA_PUBLIC_KEY}}',
|
||||
'{{config.ALGOLIA_INDEX_USERS}}',
|
||||
function (event, hit, dataset) {
|
||||
setAdmin(hit.objectID);
|
||||
}
|
||||
);
|
||||
|
||||
function addUser(userId) {
|
||||
if (!userId || userId.length == 0) {
|
||||
@ -225,6 +240,25 @@ script.
|
||||
});
|
||||
};
|
||||
|
||||
function setAdmin(userId) {
|
||||
if (!userId || userId.length == 0) {
|
||||
toastr.error('Please select a user from the list');
|
||||
return;
|
||||
}
|
||||
patchOrganization({
|
||||
op: 'assign-admin',
|
||||
user_id: userId
|
||||
})
|
||||
.done(function (data) {
|
||||
window.location.reload();
|
||||
toastr.info('Updated admin user');
|
||||
})
|
||||
.fail(function (err) {
|
||||
var msg = xhrErrorResponseMessage(err);
|
||||
toastr.error('Could not add member: ' + msg);
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
| {% endif %}
|
||||
|
@ -357,6 +357,54 @@ class OrganizationPatchTest(AbstractPillarTest):
|
||||
self.assertEqual('Open Source animation studio', db_org['description'])
|
||||
self.assertEqual('https://blender.institute/', db_org['website'])
|
||||
|
||||
def test_assign_admin(self):
|
||||
self.enter_app_context()
|
||||
om = self.app.org_manager
|
||||
|
||||
admin_uid = self.create_user(24 * 'a', token='admin-token')
|
||||
new_admin_uid = self.create_user(24 * 'b', token='other-admin-token')
|
||||
|
||||
org_doc = om.create_new_org('Хакеры', admin_uid, 25)
|
||||
org_id = org_doc['_id']
|
||||
|
||||
# Try the PATCH to assign the other user as admin
|
||||
self.patch(f'/api/organizations/{org_id}',
|
||||
json={
|
||||
'op': 'assign-admin',
|
||||
'user_id': str(new_admin_uid),
|
||||
},
|
||||
auth_token='admin-token',
|
||||
expected_status=204)
|
||||
|
||||
db = self.app.db('organizations')
|
||||
db_org = db.find_one(org_id)
|
||||
|
||||
self.assertEqual(new_admin_uid, db_org['admin_uid'])
|
||||
|
||||
def test_assign_admin_as_nonadmin(self):
|
||||
self.enter_app_context()
|
||||
om = self.app.org_manager
|
||||
|
||||
admin_uid = self.create_user(24 * 'a', token='admin-token')
|
||||
new_admin_uid = self.create_user(24 * 'b', token='other-admin-token')
|
||||
|
||||
org_doc = om.create_new_org('Хакеры', admin_uid, 25)
|
||||
org_id = org_doc['_id']
|
||||
|
||||
# Try the PATCH to assign the other user as admin
|
||||
self.patch(f'/api/organizations/{org_id}',
|
||||
json={
|
||||
'op': 'assign-admin',
|
||||
'user_id': str(new_admin_uid),
|
||||
},
|
||||
auth_token='other-admin-token',
|
||||
expected_status=403)
|
||||
|
||||
db = self.app.db('organizations')
|
||||
db_org = db.find_one(org_id)
|
||||
|
||||
self.assertEqual(admin_uid, db_org['admin_uid'])
|
||||
|
||||
|
||||
class OrganizationResourceEveTest(AbstractPillarTest):
|
||||
"""Test GET/POST/PUT access to Organization resource"""
|
||||
|
Loading…
x
Reference in New Issue
Block a user