Skip to content

Commit

Permalink
Implement unbanning user(s) functionality in admin/cinder webhook act…
Browse files Browse the repository at this point in the history
…ion (#21472)

* Implement unbanning user(s) functionality in admin/cinder webhook action
  • Loading branch information
diox committed Nov 21, 2023
1 parent 6182109 commit 4005602
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 154 deletions.
9 changes: 9 additions & 0 deletions src/olympia/abuse/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,17 @@ def test_ban_user(self):
self.cinder_report.abuse_report.update(user=user, guid=None)
action = CinderActionBanUser(self.cinder_report)
action.process()
user.reload()
self.assertCloseToNow(user.banned)

def test_approve_user(self):
user = user_factory(banned=self.days_ago(1), deleted=True)
self.cinder_report.abuse_report.update(user=user, guid=None)
action = CinderActionApproveAppealOverride(self.cinder_report)
action.process()
user.reload()
assert not user.banned

def test_disable_addon(self):
addon = addon_factory()
self.cinder_report.abuse_report.update(guid=addon.guid)
Expand Down
6 changes: 4 additions & 2 deletions src/olympia/abuse/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class CinderActionBanUser(CinderAction):
def process(self):
if user := self.abuse_report.user:
log_create(amo.LOG.ADMIN_USER_BANNED, user)
UserProfile.ban_and_disable_related_content_bulk([user], move_files=True)
UserProfile.objects.filter(pk=user.pk).ban_and_disable_related_content()
self.notify_reporter()
self.notify_targets([user])

Expand Down Expand Up @@ -112,7 +112,9 @@ def process(self):
self.notify_targets(target.authors.all())

elif isinstance(target, UserProfile) and target.banned:
# TODO: un-ban the user
UserProfile.objects.filter(
pk=target.pk
).unban_and_reenable_related_content()
self.notify_targets([target])

elif isinstance(target, Collection) and target.deleted:
Expand Down
7 changes: 7 additions & 0 deletions src/olympia/constants/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,13 @@ class ADMIN_USER_CONTENT_RESTORED(_LOG):
admin_event = True


class ADMIN_USER_UNBAN(_LOG):
id = 187
format = _('User {user} unbanned.')
keep = True
admin_event = True


LOGS = [x for x in vars().values() if isclass(x) and issubclass(x, _LOG) and x != _LOG]
# Make sure there's no duplicate IDs.
assert len(LOGS) == len({log.id for log in LOGS})
Expand Down
53 changes: 42 additions & 11 deletions src/olympia/users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,12 @@ class UserAdmin(AMOModelAdmin):
),
)

actions = ['ban_action', 'reset_api_key_action', 'reset_session_action']
actions = [
'ban_action',
'unban_action',
'reset_api_key_action',
'reset_session_action',
]

def get_urls(self):
def wrap(view):
Expand All @@ -193,6 +198,11 @@ def wrapper(*args, **kwargs):
wrap(self.ban_view),
name='users_userprofile_ban',
),
re_path(
r'^(?P<object_id>.+)/unban/$',
wrap(self.unban_view),
name='users_userprofile_unban',
),
re_path(
r'^(?P<object_id>.+)/reset_api_key/$',
wrap(self.reset_api_key_view),
Expand All @@ -214,9 +224,10 @@ def wrapper(*args, **kwargs):
def get_actions(self, request):
actions = super().get_actions(request)
if not acl.action_allowed_for(request.user, amo.permissions.USERS_EDIT):
# You need Users:Edit to be able to ban users and reset their api
# key confirmation.
# You need Users:Edit to be able to (un)ban users and reset their
# api key confirmation/session.
actions.pop('ban_action')
actions.pop('unban_action')
actions.pop('reset_api_key_action')
actions.pop('reset_session_action')
return actions
Expand Down Expand Up @@ -271,14 +282,31 @@ def ban_view(self, request, object_id, extra_context=None):
if not acl.action_allowed_for(request.user, amo.permissions.USERS_EDIT):
return HttpResponseForbidden()

ActivityLog.create(amo.LOG.ADMIN_USER_BANNED, obj)
UserProfile.ban_and_disable_related_content_bulk([obj], move_files=True)
self.model.objects.filter(pk=obj.pk).ban_and_disable_related_content()
kw = {'user': force_str(obj)}
self.message_user(request, 'The user "%(user)s" has been banned.' % kw)
return HttpResponseRedirect(
reverse('admin:users_userprofile_change', args=(obj.pk,))
)

def unban_view(self, request, object_id, extra_context=None):
if request.method != 'POST':
return HttpResponseNotAllowed(['POST'])

obj = self.get_object(request, unquote(object_id))
if obj is None:
raise Http404()

if not acl.action_allowed_for(request.user, amo.permissions.USERS_EDIT):
return HttpResponseForbidden()

self.model.objects.filter(pk=obj.pk).unban_and_reenable_related_content()
kw = {'user': force_str(obj)}
self.message_user(request, 'The user "%(user)s" has been unbanned.' % kw)
return HttpResponseRedirect(
reverse('admin:users_userprofile_change', args=(obj.pk,))
)

def reset_api_key_view(self, request, object_id, extra_context=None):
if request.method != 'POST':
return HttpResponseNotAllowed(['POST'])
Expand Down Expand Up @@ -336,16 +364,19 @@ def delete_picture_view(self, request, object_id, extra_context=None):
)

def ban_action(self, request, qs):
users = []
UserProfile.ban_and_disable_related_content_bulk(qs)
for obj in qs:
ActivityLog.create(amo.LOG.ADMIN_USER_BANNED, obj)
users.append(force_str(obj))
kw = {'users': ', '.join(users)}
qs.ban_and_disable_related_content()
kw = {'users': ', '.join(str(user) for user in qs)}
self.message_user(request, 'The users "%(users)s" have been banned.' % kw)

ban_action.short_description = 'Ban selected users'

def unban_action(self, request, qs):
qs.unban_and_reenable_related_content()
kw = {'users': ', '.join(str(user) for user in qs)}
self.message_user(request, 'The users "%(users)s" have been unbanned.' % kw)

unban_action.short_description = 'Unban selected users'

def reset_session_action(self, request, qs):
users = []
qs.update(auth_id=None) # A new value will be generated at next login.
Expand Down

0 comments on commit 4005602

Please sign in to comment.