Child: [bea16d] (diff)

Download this file

scrub-allura-data.py    130 lines (112 with data), 4.9 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import logging
import sys
from ming.orm import ThreadLocalORMSession
import mock
from pylons import c, g
from allura import model as M
from forgediscussion import model as DM
from forgetracker import model as TM
from allura.lib import utils
log = logging.getLogger(__name__)
def public(obj, project=None):
if not project:
project = obj
role_anon = M.ProjectRole.by_name(name='*anonymous', project=project)
if not role_anon:
log.info('Missing *anonymous role for project "%s"' %
project.shortname)
return False
read = M.ACE.allow(role_anon._id, 'read')
return read in obj.acl
def scrub_project(p, options):
log.info('Scrubbing project "%s"' % p.shortname)
preamble = options.preamble
if not public(p):
log.info('%s project "%s"' % (preamble, p.shortname))
if not options.dry_run:
p.delete()
return
for ac in p.app_configs:
ac.project = p
c.app = p.app_instance(ac)
mount_point = ac.options.get('mount_point')
tool_name = ac.tool_name.lower()
if tool_name in ('admin', 'search', 'profile'):
continue
if not public(ac, project=p):
log.info('%s tool %s/%s on project "%s"' % (
preamble, tool_name, mount_point, p.shortname))
if not options.dry_run:
p.uninstall_app(mount_point)
continue
q = dict(app_config_id=ac._id)
ace = dict(access='DENY', permission='*', role_id=None)
q['acl'] = {'$in': [ace]}
counter = 0
if tool_name == 'tickets':
if ac.options.get('TicketMonitoringEmail'):
log.info('%s options.TicketMonitoringEmail from the %s/%s '
'tool on project "%s"' % (preamble, tool_name,
mount_point, p.shortname))
if not options.dry_run:
ac.options['TicketMonitoringEmail'] = None
for tickets in utils.chunked_find(TM.Ticket, q):
for t in tickets:
counter += 1
if not options.dry_run:
t.discussion_thread.delete()
t.delete()
ThreadLocalORMSession.flush_all()
ThreadLocalORMSession.close_all()
if counter > 0:
log.info('%s %s tickets from the %s/%s tool on '
'project "%s"' % (preamble, counter, tool_name,
mount_point, p.shortname))
elif tool_name == 'discussion':
for forums in utils.chunked_find(DM.Forum, q):
for f in forums:
counter += 1
if not options.dry_run:
f.delete()
if counter > 0:
log.info('%s %s forums from the %s/%s tool on '
'project "%s"' % (preamble, counter, tool_name,
mount_point, p.shortname))
def main(options):
log.addHandler(logging.StreamHandler(sys.stdout))
log.setLevel(getattr(logging, options.log_level.upper()))
g.solr = mock.Mock()
preamble = options.dry_run and "Would delete" or "Deleting"
options.preamble = preamble
for nbhd in M.Neighborhood.query.find():
q = {'neighborhood_id': nbhd._id}
for projects in utils.chunked_find(M.Project, q):
for p in projects:
scrub_project(p, options)
ThreadLocalORMSession.flush_all()
ThreadLocalORMSession.close_all()
log.info('%s %s EmailAddress documents' %
(preamble, M.EmailAddress.query.find().count()))
log.info('%s email addresses from %s User documents' %
(preamble, M.User.query.find().count()))
log.info('%s monitoring_email addresses from %s Forum documents' %
(preamble, DM.Forum.query.find({"monitoring_email":
{"$nin": [None, ""]}}).count()))
if not options.dry_run:
M.EmailAddress.query.remove()
M.User.query.update({}, {"$set": {"email_addresses": []}}, multi=True)
DM.Forum.query.update({"monitoring_email": {"$nin": [None, ""]}},
{"$set": {"monitoring_email": None}}, multi=True)
return 0
def parse_options():
import argparse
parser = argparse.ArgumentParser(
description='Removes private data from the Allura MongoDB.')
parser.add_argument('--dry-run', dest='dry_run', default=False,
action='store_true',
help='Run in test mode (no updates will be applied).')
parser.add_argument('--log', dest='log_level', default='INFO',
help='Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL).')
return parser.parse_args()
if __name__ == '__main__':
sys.exit(main(parse_options()))