WebKit Bugzilla
Attachment 368853 Details for
Bug 197537
: Add a tool to block spammer accounts
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
proposed patch
BlockSpammers.txt (text/plain), 11.68 KB, created by
Alexey Proskuryakov
on 2019-05-02 17:46:16 PDT
(
hide
)
Description:
proposed patch
Filename:
MIME Type:
Creator:
Alexey Proskuryakov
Created:
2019-05-02 17:46:16 PDT
Size:
11.68 KB
patch
obsolete
>Index: Tools/ChangeLog >=================================================================== >--- Tools/ChangeLog (revision 244896) >+++ Tools/ChangeLog (working copy) >@@ -1,3 +1,31 @@ >+2019-05-02 Alexey Proskuryakov <ap@apple.com> >+ >+ Add a tool to block spammer accounts >+ https://bugs.webkit.org/show_bug.cgi?id=197537 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Usage: block-spammers email1 email2 ... >+ >+ The tool finds and hides all bugs and comments from this account. Before any work >+ is done, these bugs and comments are displayed for confirmation. >+ >+ * Scripts/block-spammers: Added. >+ (get_bugzilla_token): >+ (invalidate_bugzilla_token): >+ (get_user_info): >+ (get_user_info_self): >+ (can_use_this_tool): >+ (disable_user): >+ (get_bugs_created_by_user): >+ (get_bugs_commented_on_by_user): >+ (get_comments): >+ (hide_bug): >+ (hide_comments): >+ (ask_yes_no): >+ (sanitized_string): >+ (main): >+ > 2019-05-02 Christopher Reid <chris.reid@sony.com> > > [CMake] Add support for LTO builds >Index: Tools/Scripts/block-spammers >=================================================================== >--- Tools/Scripts/block-spammers (nonexistent) >+++ Tools/Scripts/block-spammers (working copy) >@@ -0,0 +1,232 @@ >+#!/usr/bin/env python >+ >+# Copyright (C) 2019 Apple Inc. All rights reserved. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# 3. Neither the name of Apple Inc. ("Apple") nor the names of >+# its contributors may be used to endorse or promote products derived >+# from this software without specific prior written permission. >+# >+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY >+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED >+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE >+# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY >+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES >+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; >+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND >+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+import argparse >+import atexit >+import re >+import requests >+import subprocess >+import sys >+from dateutil.parser import parse >+ >+bugzilla_self_user_id = None >+bugzilla_token = None >+ >+def get_bugzilla_token(): >+ security = subprocess.Popen(['/usr/bin/security', 'find-internet-password', '-gs', 'bugs.webkit.org'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) >+ security.wait() >+ if security.returncode: >+ raise Exception('Could not get bugs.webkit.org credentials from Keychain, exit code ' + str(security.returncode)) >+ for line in security.stdout: >+ m = re.search('^ "acct"<blob>="(.+)"$', line) >+ if m: >+ account = m.group(1) >+ continue >+ m = re.search('^password: "(.+)"$', line) >+ if m: >+ password = m.group(1) >+ if not account or not password: >+ raise Exception('Could not parse security tool output to get bugs.webkit.org credentials') >+ >+ response = requests.get('https://bugs.webkit.org/rest/login', params={'login': account, 'password': password}).json() >+ global bugzilla_token >+ global bugzilla_self_user_id >+ bugzilla_token = response['token'] >+ bugzilla_self_user_id = response['id'] >+ atexit.register(invalidate_bugzilla_token) >+ >+ >+def invalidate_bugzilla_token(): >+ requests.get('https://bugs.webkit.org/rest/logout?' + bugzilla_token) >+ >+ >+def get_user_info(id): >+ response = requests.get('https://bugs.webkit.org/rest/user/' + id, >+ params={'include_disabled': True, 'token': bugzilla_token}).json() >+ if len(response['users']) != 1: >+ raise Exception('Unexpected number of accounts found for ' + id + ': ' + str(len(response['users']))) >+ return response['users'][0] >+ >+ >+def get_user_info_self(): >+ global bugzilla_self_user_id >+ return get_user_info(str(bugzilla_self_user_id)) >+ >+ >+def can_use_this_tool(): >+ my_groups = [x['name'] for x in get_user_info_self()['groups']] >+ return 'admin' in my_groups or ('editbugs' in my_groups and 'editusers' in my_groups and 'Spam-Masters' in my_groups and 'Security-Sensitive' in my_groups) >+ >+ >+def disable_user(user_id, reason): >+ response = requests.put('https://bugs.webkit.org/rest/user/' + str(user_id), >+ json={'email_enabled': False, 'login_denied_text': reason}, >+ params = {'email_enabled': False, 'login_denied_text': reason, 'token': bugzilla_token}) >+ response.raise_for_status() >+ >+ >+def get_bugs_created_by_user(id): >+ response = requests.get('https://bugs.webkit.org/rest/bug', >+ params={'product': ['WebKit', 'Security'], 'email1': id, 'emailreporter1': '1', 'emailtype1': 'equals', >+ 'include_fields': 'id,summary,product', 'token': bugzilla_token}) >+ return response.json()['bugs'] >+ >+ >+def get_bugs_commented_on_by_user(id): >+ response = requests.get('https://bugs.webkit.org/rest/bug', >+ params={'product': ['WebKit', 'Security'], 'email1': id, 'emaillongdesc1': '1', 'emailtype1': 'equals', >+ 'include_fields': 'id,summary,product', 'token': bugzilla_token}) >+ return response.json()['bugs'] >+ >+ >+def get_comments(bug_id): >+ response = requests.get('https://bugs.webkit.org/rest/bug/' + str(bug_id) + '/comment', params={'token': bugzilla_token}) >+ return response.json()['bugs'][str(bug_id)]["comments"] >+ >+ >+def hide_bug(bug_id): >+ response = requests.put('https://bugs.webkit.org/rest/bug/' + str(bug_id), >+ json={'product': 'Spam', 'component': 'Spam', 'version': 'unspecified', 'is_creator_accessible': False, 'is_cc_accessible': False}, >+ params = {'token': bugzilla_token}) >+ if not response: >+ print '!!! Failed to move bug ' + str(bug_id) + ': ' + response.text >+ >+ >+def hide_comments(bug_id, comment_ids): >+ response = requests.put('https://bugs.webkit.org/rest/bug/' + str(bug_id), >+ json={'comment_is_private': {str(id): True for id in comment_ids}}, >+ params={'token': bugzilla_token}) >+ if not response: >+ print '!!! Failed to hide comments for bug' + str(bug_id) + ': ' + response.text >+ for comment_id in comment_ids: >+ response = requests.put('https://bugs.webkit.org/rest/bug/comment/' + str(comment_id) + '/tags', >+ json={'comment_id': comment_id, 'add': ['spam']}, >+ params={'token': bugzilla_token}) >+ if not response: >+ print '!!! Failed to mark comment with spam tag: ' + response.text >+ >+ >+def ask_yes_no(question, default='yes'): >+ if default is None: >+ prompt_string = ' [y/n] ' >+ elif default == 'yes': >+ prompt_string = ' [Y/n] ' >+ elif default == 'no': >+ prompt_string = ' [y/N] ' >+ >+ answers= {'yes': True, 'y': True, 'ye': True, 'no': False, 'n': False} >+ while True: >+ sys.stdout.write(question + prompt_string) >+ response = raw_input().lower() >+ if default is not None and response == '': >+ return answers[default] >+ elif response in answers: >+ return answers[response] >+ >+ >+def sanitized_string(string): >+ return string.encode('utf-8').translate(None, '\x1B') >+ >+def main(): >+ parser = argparse.ArgumentParser(description='Block Bugzilla spammers, and hide their comments.') >+ parser.add_argument('accounts', nargs='+', help='accounts to block') >+ args = parser.parse_args() >+ >+ global bugzilla_token >+ global bugzilla_self_user_id >+ get_bugzilla_token() >+ >+ if not can_use_this_tool(): >+ print 'You need to be a Bugzilla admin to use this tool.' >+ exit(1) >+ >+ print 'Fetching account activity...' >+ >+ users_to_disable = [] >+ for account_id in args.accounts: >+ user_info = get_user_info(account_id) >+ users_to_disable.append(user_info) >+ user_info['bugs_created'] = get_bugs_created_by_user(account_id) >+ created_bug_ids = [y['id'] for y in user_info['bugs_created']] >+ user_info['bugs_commented'] = [x for x in get_bugs_commented_on_by_user(account_id) if x['id'] not in created_bug_ids] >+ for bug in user_info['bugs_commented']: >+ bug['comments'] = get_comments(bug['id']) >+ >+ for user in users_to_disable: >+ print sanitized_string(user['real_name']) + ' <' + user['name'] + '>' >+ if not user['can_login']: >+ print '*** already disabled ***' >+ if user['bugs_created']: >+ print 'Created ' + str(len(user['bugs_created'])) + ' bug(s):' >+ for bug in user['bugs_created']: >+ print 'https://bugs.webkit.org/show_bug.cgi?id=' + str(bug['id']) + ' ' + sanitized_string(bug['summary']) >+ if user['bugs_commented']: >+ print 'Commented on ' + str(len(user['bugs_commented'])) + ' bug(s):' >+ for bug in user['bugs_commented']: >+ print 'https://bugs.webkit.org/show_bug.cgi?id=' + str(bug['id']) + ' ' + sanitized_string(bug['summary']) >+ for comment in bug['comments']: >+ if comment['creator'] == user['name']: >+ print 'Comment ' + str(comment['count']) + ', ' + str(parse(comment['creation_time'])) + ': ' + sanitized_string(comment['text']) >+ print >+ >+ if not ask_yes_no("Block all these accounts, and hide their bugs and comments?"): >+ print "*** Exiting, no work performed ***" >+ exit(0) >+ >+ # Block all of the users first, so that they don't receive e-mail notifications about further actions. >+ for user in users_to_disable: >+ if not user['can_login']: >+ print 'User ' + str(user['name']) + ' is already disabled, skipping' >+ continue >+ print 'Disabling user ' + str(user['name']) >+ disable_user(user['id'], 'spam') >+ >+ for user in users_to_disable: >+ for bug in user['bugs_created']: >+ if bug['product'] == 'Spam': >+ print 'Bug ' + str(bug['id']) + ' is already in the Spam product, skipping' >+ continue >+ print 'Moving bug ' + str(bug['id']) + ' to the Spam product' >+ hide_bug(bug['id']) >+ for bug in user['bugs_commented']: >+ comments_to_hide = [] >+ for comment in bug['comments']: >+ if comment['creator'] != user['name']: >+ continue >+ if comment['is_private']: >+ print 'Comment ' + str(comment['count']) + ' on bug ' + str(bug['id']) + ' is already private, skipping' >+ continue >+ assert(comment['bug_id'] == bug['id']) >+ comments_to_hide.append(comment['id']) >+ if comments_to_hide: >+ print 'Hiding comment(s) from user ' + str(user['name']) + ' on bug ' + str(bug['id']) >+ hide_comments(bug['id'], comments_to_hide) >+ >+ >+if __name__ == "__main__": >+ main() > >Property changes on: Tools/Scripts/block-spammers >___________________________________________________________________ >Added: svn:executable >## -0,0 +1 ## >+* >\ No newline at end of property
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
darin
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 197537
: 368853