mirror of https://github.com/zulip/zulip.git
support: Add option to delete user from /activity/support.
This commit is contained in:
parent
386d87635e
commit
632e856240
|
@ -702,3 +702,26 @@ class TestSupportEndpoint(ZulipTestCase):
|
||||||
result = self.client_post("/activity/support", {"realm_id": f"{lear_realm.id}"})
|
result = self.client_post("/activity/support", {"realm_id": f"{lear_realm.id}"})
|
||||||
self.assert_json_error(result, "Invalid parameters")
|
self.assert_json_error(result, "Invalid parameters")
|
||||||
m.assert_not_called()
|
m.assert_not_called()
|
||||||
|
|
||||||
|
def test_delete_user(self) -> None:
|
||||||
|
cordelia = self.example_user("cordelia")
|
||||||
|
hamlet = self.example_user("hamlet")
|
||||||
|
hamlet_email = hamlet.delivery_email
|
||||||
|
realm = get_realm("zulip")
|
||||||
|
self.login_user(cordelia)
|
||||||
|
|
||||||
|
result = self.client_post(
|
||||||
|
"/activity/support", {"realm_id": f"{realm.id}", "delete_user_by_id": hamlet.id}
|
||||||
|
)
|
||||||
|
self.assertEqual(result.status_code, 302)
|
||||||
|
self.assertEqual(result["Location"], "/login/")
|
||||||
|
|
||||||
|
self.login("iago")
|
||||||
|
|
||||||
|
with mock.patch("analytics.views.support.do_delete_user_preserving_messages") as m:
|
||||||
|
result = self.client_post(
|
||||||
|
"/activity/support",
|
||||||
|
{"realm_id": f"{realm.id}", "delete_user_by_id": hamlet.id},
|
||||||
|
)
|
||||||
|
m.assert_called_once_with(hamlet)
|
||||||
|
self.assert_in_success_response([f"{hamlet_email} in zulip deleted"], result)
|
||||||
|
|
|
@ -26,6 +26,7 @@ from zerver.actions.realm_settings import (
|
||||||
do_scrub_realm,
|
do_scrub_realm,
|
||||||
do_send_realm_reactivation_email,
|
do_send_realm_reactivation_email,
|
||||||
)
|
)
|
||||||
|
from zerver.actions.users import do_delete_user_preserving_messages
|
||||||
from zerver.decorator import require_server_admin
|
from zerver.decorator import require_server_admin
|
||||||
from zerver.forms import check_subdomain_available
|
from zerver.forms import check_subdomain_available
|
||||||
from zerver.lib.exceptions import JsonableError
|
from zerver.lib.exceptions import JsonableError
|
||||||
|
@ -42,6 +43,7 @@ from zerver.models import (
|
||||||
UserProfile,
|
UserProfile,
|
||||||
get_org_type_display_name,
|
get_org_type_display_name,
|
||||||
get_realm,
|
get_realm,
|
||||||
|
get_user_profile_by_id,
|
||||||
)
|
)
|
||||||
from zerver.views.invite import get_invitee_emails_set
|
from zerver.views.invite import get_invitee_emails_set
|
||||||
|
|
||||||
|
@ -166,6 +168,7 @@ def support(
|
||||||
default=None, str_validator=check_string_in(VALID_MODIFY_PLAN_METHODS)
|
default=None, str_validator=check_string_in(VALID_MODIFY_PLAN_METHODS)
|
||||||
),
|
),
|
||||||
scrub_realm: bool = REQ(default=False, json_validator=check_bool),
|
scrub_realm: bool = REQ(default=False, json_validator=check_bool),
|
||||||
|
delete_user_by_id: Optional[int] = REQ(default=None, converter=to_non_negative_int),
|
||||||
query: Optional[str] = REQ("q", default=None),
|
query: Optional[str] = REQ("q", default=None),
|
||||||
org_type: Optional[int] = REQ(default=None, converter=to_non_negative_int),
|
org_type: Optional[int] = REQ(default=None, converter=to_non_negative_int),
|
||||||
) -> HttpResponse:
|
) -> HttpResponse:
|
||||||
|
@ -276,6 +279,12 @@ def support(
|
||||||
elif scrub_realm:
|
elif scrub_realm:
|
||||||
do_scrub_realm(realm, acting_user=acting_user)
|
do_scrub_realm(realm, acting_user=acting_user)
|
||||||
context["success_message"] = f"{realm.string_id} scrubbed."
|
context["success_message"] = f"{realm.string_id} scrubbed."
|
||||||
|
elif delete_user_by_id:
|
||||||
|
user_profile_for_deletion = get_user_profile_by_id(delete_user_by_id)
|
||||||
|
user_email = user_profile_for_deletion.delivery_email
|
||||||
|
assert user_profile_for_deletion.realm == realm
|
||||||
|
do_delete_user_preserving_messages(user_profile_for_deletion)
|
||||||
|
context["success_message"] = f"{user_email} in {realm.subdomain} deleted."
|
||||||
|
|
||||||
if query:
|
if query:
|
||||||
key_words = get_invitee_emails_set(query)
|
key_words = get_invitee_emails_set(query)
|
||||||
|
|
|
@ -41,6 +41,12 @@
|
||||||
<b>Date joined</b>: {{ user.date_joined|timesince }} ago<br />
|
<b>Date joined</b>: {{ user.date_joined|timesince }} ago<br />
|
||||||
<b>Is active</b>: {{ user.is_active }}<br />
|
<b>Is active</b>: {{ user.is_active }}<br />
|
||||||
<b>Role</b>: {{ user.get_role_name() }}<br />
|
<b>Role</b>: {{ user.get_role_name() }}<br />
|
||||||
|
<form method="POST" class="delete-user-form">
|
||||||
|
{{ csrf_input }}
|
||||||
|
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||||
|
<input type="hidden" name="delete_user_by_id" value="{{ user.id }}" />
|
||||||
|
<button data-email="{{ user.delivery_email }}" data-string-id="{{ realm.string_id }}" class="btn btn-danger small delete-user-button">Delete user (danger)</button>
|
||||||
|
</form>
|
||||||
<hr />
|
<hr />
|
||||||
<div>
|
<div>
|
||||||
{% include "analytics/realm_details.html" %}
|
{% include "analytics/realm_details.html" %}
|
||||||
|
|
|
@ -18,6 +18,31 @@ $(() => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("body").on("click", ".delete-user-button", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const message =
|
||||||
|
"Confirm the email of the user you want to delete.\n\n WARNING! This action is irreversible!";
|
||||||
|
const actual_email = $(this).attr("data-email");
|
||||||
|
// eslint-disable-next-line no-alert
|
||||||
|
const confirmed_email = window.prompt(message);
|
||||||
|
if (confirmed_email === actual_email) {
|
||||||
|
const actual_string_id = $(this).attr("data-string-id");
|
||||||
|
// eslint-disable-next-line no-alert
|
||||||
|
const confirmed_string_id = window.prompt(
|
||||||
|
"Now provide string_id of the realm to confirm.",
|
||||||
|
);
|
||||||
|
if (confirmed_string_id === actual_string_id) {
|
||||||
|
this.form.submit();
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line no-alert
|
||||||
|
window.alert("The string_id you entered is not correct. Aborted.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line no-alert
|
||||||
|
window.alert("The email you entered is not correct. Aborted.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("a.copy-button").on("click", function () {
|
$("a.copy-button").on("click", function () {
|
||||||
common.copy_data_attribute_value($(this), "copytext");
|
common.copy_data_attribute_value($(this), "copytext");
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue