Orgs: allow users to leave an organization
This commit is contained in:
parent
0445c3bd86
commit
be12bd7d99
@ -104,16 +104,18 @@ class OrganizationPatchHandler(patch_handler.AbstractPatchHandler):
|
||||
The calling user must be admin of the organization.
|
||||
"""
|
||||
|
||||
self._assert_is_admin(org_id)
|
||||
|
||||
# Do some basic validation.
|
||||
email = patch.get('email') or None
|
||||
user_id = patch.get('user_id')
|
||||
|
||||
user_oid = str2id(user_id) if user_id else None
|
||||
|
||||
log.info('User %s uses PATCH to remove user from organization %s',
|
||||
current_user().user_id, org_id)
|
||||
# Users require admin rights on the org, except when removing themselves.
|
||||
current_user_id = current_user().user_id
|
||||
if user_oid is None or user_oid != current_user_id:
|
||||
self._assert_is_admin(org_id)
|
||||
|
||||
log.info('User %s uses PATCH to remove user %s from organization %s',
|
||||
current_user_id, user_oid, org_id)
|
||||
|
||||
org_doc = current_app.org_manager.remove_user(org_id, user_id=user_oid, email=email)
|
||||
return jsonify(org_doc)
|
||||
|
@ -115,7 +115,7 @@
|
||||
| {% endif %}
|
||||
span.sharing-users-extra {{ member['username'] }}
|
||||
.sharing-users-action
|
||||
| {% if can_edit %}
|
||||
| {% if can_edit or current_user.objectid == member['_id'] %}
|
||||
| {% if current_user.objectid == member['_id'] %}
|
||||
button.user-remove(title="Leave as member of this organization")
|
||||
i.pi-trash
|
||||
@ -180,28 +180,6 @@
|
||||
|
||||
| {% if can_edit %}
|
||||
script.
|
||||
|
||||
function patchOrganization(patch) {
|
||||
if (typeof patch == 'undefined') {
|
||||
throw 'patchOrganization(undefined) called';
|
||||
}
|
||||
|
||||
if (console) console.log('patchOrganization', patch);
|
||||
|
||||
var promise = $.ajax({
|
||||
url: '/api/organizations/{{ organization._id }}',
|
||||
method: 'PATCH',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(patch),
|
||||
})
|
||||
.fail(function(err) {
|
||||
if (console) console.log('Error patching: ', err);
|
||||
})
|
||||
;
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#user-select').userSearch(
|
||||
'{{config.ALGOLIA_USER}}',
|
||||
@ -232,13 +210,6 @@ script.
|
||||
setAdmin(hit.objectID, hit.full_name);
|
||||
}
|
||||
);
|
||||
|
||||
$('body').off('click', '.user-remove'); // remove previous handlers.
|
||||
$('body').on('click', '.user-remove', function(e) {
|
||||
var user_id = $(this).closest('*[data-user-id]').data('user-id');
|
||||
var user_email = $(this).closest('*[data-user-email]').data('user-email');
|
||||
removeUser(user_id, user_email);
|
||||
});
|
||||
});
|
||||
|
||||
function addUser(userId) {
|
||||
@ -264,31 +235,6 @@ script.
|
||||
});
|
||||
};
|
||||
|
||||
function removeUser(user_id, email) {
|
||||
if (typeof user_id == 'undefined' && typeof email == 'undefined') {
|
||||
throw "removeUser(undefined, undefined) called";
|
||||
}
|
||||
var organization_id = '{{ organization._id }}';
|
||||
var patch = {op: 'remove-user'};
|
||||
|
||||
if (typeof user_id !== 'undefined') {
|
||||
patch.user_id = user_id;
|
||||
}
|
||||
if (typeof email !== 'undefined') {
|
||||
patch.email = String(email);
|
||||
}
|
||||
|
||||
patchOrganization(patch)
|
||||
.done(function() {
|
||||
$("ul.sharing-users-list").find("[data-user-id='" + user_id + "']").remove();
|
||||
item_open('{{ organization._id }}', false);
|
||||
toastr.success('User removed from this organization');
|
||||
}).fail(function (data) {
|
||||
var msg = xhrErrorResponseMessage(data);
|
||||
toastr.error('Error removing user: ' + msg);
|
||||
});
|
||||
}
|
||||
|
||||
function setAdmin(user_id, full_name) {
|
||||
if (!user_id || user_id.length == 0) {
|
||||
toastr.error('Please select a user from the list');
|
||||
@ -382,4 +328,66 @@ script.
|
||||
}
|
||||
|
||||
| {% endif %}
|
||||
script.
|
||||
$(document).ready(function() {
|
||||
$('body').off('click', '.user-remove'); // remove previous handlers.
|
||||
$('body').on('click', '.user-remove', function(e) {
|
||||
var user_id = $(this).closest('*[data-user-id]').data('user-id');
|
||||
var user_email = $(this).closest('*[data-user-email]').data('user-email');
|
||||
removeUser(user_id, user_email);
|
||||
});
|
||||
});
|
||||
|
||||
function patchOrganization(patch) {
|
||||
if (typeof patch == 'undefined') {
|
||||
throw 'patchOrganization(undefined) called';
|
||||
}
|
||||
|
||||
if (console) console.log('patchOrganization', patch);
|
||||
|
||||
var promise = $.ajax({
|
||||
url: '/api/organizations/{{ organization._id }}',
|
||||
method: 'PATCH',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify(patch),
|
||||
})
|
||||
.fail(function(err) {
|
||||
if (console) console.log('Error patching: ', err);
|
||||
})
|
||||
;
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function removeUser(user_id, email) {
|
||||
if (typeof user_id == 'undefined' && typeof email == 'undefined') {
|
||||
throw "removeUser(undefined, undefined) called";
|
||||
}
|
||||
var organization_id = '{{ organization._id }}';
|
||||
var patch = {op: 'remove-user'};
|
||||
|
||||
if (typeof user_id !== 'undefined') {
|
||||
patch.user_id = user_id;
|
||||
}
|
||||
if (typeof email !== 'undefined') {
|
||||
patch.email = String(email);
|
||||
}
|
||||
|
||||
patchOrganization(patch)
|
||||
.done(function() {
|
||||
$("ul.sharing-users-list").find("[data-user-id='" + user_id + "']").remove();
|
||||
if ('{{ current_user.user_id }}' == user_id) {
|
||||
// User removed self, so we cannot open this organization again.
|
||||
$('#organization-{{ organization._id}}').remove();
|
||||
toastr.success('You left the organization.')
|
||||
} else {
|
||||
item_open('{{ organization._id }}', false);
|
||||
toastr.success('User removed from this organization');
|
||||
}
|
||||
}).fail(function (data) {
|
||||
var msg = xhrErrorResponseMessage(data);
|
||||
toastr.error('Error removing user: ' + msg);
|
||||
});
|
||||
}
|
||||
|
||||
| {% endblock %}
|
||||
|
@ -331,6 +331,32 @@ class OrganizationPatchTest(AbstractPillarTest):
|
||||
self.assertEqual([], db_org['members'])
|
||||
self.assertEqual(['member2@example.com'], db_org['unknown_members'])
|
||||
|
||||
def test_remove_self(self):
|
||||
self.enter_app_context()
|
||||
om = self.app.org_manager
|
||||
|
||||
admin_uid = self.create_user(24 * 'a', token='admin-token')
|
||||
member_uid = self.create_user(24 * 'b', email='member1@example.com', token='member-token')
|
||||
org_doc = om.create_new_org('Хакеры', admin_uid, 25)
|
||||
org_id = org_doc['_id']
|
||||
|
||||
om.assign_users(org_id, ['member1@example.com'])
|
||||
|
||||
# Try the PATCH to remove self.
|
||||
resp = self.patch(f'/api/organizations/{org_id}',
|
||||
json={
|
||||
'op': 'remove-user',
|
||||
'user_id': str(member_uid),
|
||||
},
|
||||
auth_token='member-token')
|
||||
new_org_doc = resp.get_json()
|
||||
|
||||
db = self.app.db('organizations')
|
||||
db_org = db.find_one(org_id)
|
||||
|
||||
self.assertEqual([], db_org['members'])
|
||||
self.assertEqual([], new_org_doc['members'])
|
||||
|
||||
def test_edit_from_web(self):
|
||||
self.enter_app_context()
|
||||
om = self.app.org_manager
|
||||
|
Loading…
x
Reference in New Issue
Block a user