[#8336] Remove dead code root_page_name.setter, and very old migrations up to one that used that setter
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index f0f2030..ed1043a 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -150,17 +150,6 @@
page_name = self.default_root_page_name
return page_name
- @root_page_name.setter
- def root_page_name(self, new_root_page_name):
- globals = WM.Globals.query.get(app_config_id=self.config._id)
- if globals is not None:
- globals.root = new_root_page_name
- elif new_root_page_name != self.default_root_page_name:
- globals = WM.Globals(
- app_config_id=self.config._id, root=new_root_page_name)
- if globals is not None:
- session(globals).flush(globals)
-
def default_root_page_text(self):
return """Welcome to your wiki!
diff --git a/scripts/migrations/000-fix-tracker-fields.py b/scripts/migrations/000-fix-tracker-fields.py
deleted file mode 100644
index 072aeb9..0000000
--- a/scripts/migrations/000-fix-tracker-fields.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import logging
-
-from tg import tmpl_context as c
-
-from ming.orm import session
-
-from allura import model as M
-from forgetracker import model as TM
-
-log = logging.getLogger(__name__)
-
-
-def main():
- test = sys.argv[-1] == 'test'
- projects = M.Project.query.find().all()
- log.info('Fixing tracker fields')
- for p in projects:
- if p.parent_id:
- continue
- c.project = p
- q = TM.Globals.query.find()
- if not q.count():
- continue
- for g in q:
- if g.open_status_names:
- continue
- if g.status_names is None:
- old_names = ['open', 'closed']
- else:
- old_names = g.status_names.split() or ['open', 'closed']
- if g.open_status_names is None:
- g.open_status_names = ' '.join(
- name for name in old_names if name != 'closed')
- if g.closed_status_names is None:
- g.closed_status_names = 'closed'
- if test:
- log.info('... would fix tracker(s) in %s', p.shortname)
- else:
- log.info('... fixing tracker(s) in %s', p.shortname)
- session(g).flush()
- session(g).clear()
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/001-restore-labels.py b/scripts/migrations/001-restore-labels.py
deleted file mode 100644
index 2e33da7..0000000
--- a/scripts/migrations/001-restore-labels.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import json
-import logging
-
-from tg import tmpl_context as c
-
-from ming.orm import session, MappedClass
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-
-def main():
- test = sys.argv[-1] == 'test'
- projects = M.Project.query.find().all()
- log.info('Restoring labels on projects')
- for p in projects:
- restore_labels(p, test)
- if not test:
- session(p).flush()
- log.info('Restoring labels on artifacts')
- for p in projects:
- if p.parent_id:
- continue
- c.project = p
- for name, cls in MappedClass._registry.iteritems():
- if not issubclass(cls, M.Artifact):
- continue
- if session(cls) is None:
- continue
- for a in cls.query.find():
- restore_labels(a, test)
- if not test:
- M.artifact_orm_session.flush()
- M.artifact_orm_session.clear()
-
-
-def restore_labels(obj, test=True):
- if not obj.labels:
- return
- labels = obj.labels
- while True:
- if not labels or labels[0] != '[':
- return
- lbllen = map(len, labels)
- if max(lbllen) != 1:
- return
- if min(lbllen) != 1:
- return
- s = ''.join(labels)
- s = s.replace("u'", "'")
- s = s.replace('u"', '"')
- jobj = '{"obj":' + s.replace("'", '"') + '}'
- try:
- new_labels = json.loads(jobj)['obj']
- except ValueError:
- # some weird problem with json decoding, just erase the labels
- new_labels = []
- if not isinstance(new_labels, list):
- return
- for lbl in new_labels:
- if not isinstance(lbl, basestring):
- return
- log.info('%s: %s => %s', obj.__class__, labels, new_labels)
- labels = new_labels
- if not test:
- log.info('...actually restoring labels')
- obj.labels = new_labels
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/002-fix-tracker-thread-subjects.py b/scripts/migrations/002-fix-tracker-thread-subjects.py
deleted file mode 100644
index df42446..0000000
--- a/scripts/migrations/002-fix-tracker-thread-subjects.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import logging
-
-from tg import tmpl_context as c
-
-from ming.orm import session
-
-from allura import model as M
-from forgetracker import model as TM
-
-log = logging.getLogger(__name__)
-
-
-def main():
- test = sys.argv[-1] == 'test'
- all_projects = M.Project.query.find().all()
- log.info('Fixing tracker thread subjects')
- for project in all_projects:
- if project.parent_id:
- continue
- c.project = project
- # will find all tickets for all trackers in this project
- all_tickets = TM.Ticket.query.find()
- if not all_tickets.count():
- continue
- for ticket in all_tickets:
- thread = ticket.get_discussion_thread()
- thread.subject = ''
- if test:
- log.info('... would fix ticket threads in %s', project.shortname)
- else:
- log.info('... fixing ticket threads in %s', project.shortname)
- session(project).flush()
- session(project).clear()
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/003-migrate_project_roles.py b/scripts/migrations/003-migrate_project_roles.py
deleted file mode 100644
index 32bcc57..0000000
--- a/scripts/migrations/003-migrate_project_roles.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-'''Merge all the OldProjectRole collections in into a ProjectRole collection.
-'''
-import logging
-
-from ming.orm import session, state
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-log.info('Moving project roles in database %s to main DB',
- M.Project.database_uri())
-for opr in M.OldProjectRole.query.find():
- pr = M.ProjectRole(**state(opr).document)
-session(opr).clear()
-session(pr).flush()
-session(pr).clear()
diff --git a/scripts/migrations/004-make-attachments-polymorphic.py b/scripts/migrations/004-make-attachments-polymorphic.py
deleted file mode 100644
index e6133ec..0000000
--- a/scripts/migrations/004-make-attachments-polymorphic.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import logging
-
-from ming.orm import ThreadLocalORMSession
-from allura import model as M
-from forgetracker import model as TM
-from forgewiki import model as WM
-from forgediscussion import model as DM
-
-log = logging.getLogger(__name__)
-
-
-def main():
- db = M.project_doc_session.db
- log.info('=== Making attachments in %s polymorphic ===', db)
- log.info('Fixing %d discussions', M.Discussion.query.find().count())
- for d in M.Discussion.query.find():
- for a in M.DiscussionAttachment.query.find(dict(
- discussion_id=d._id)):
- log.info('%s: %s', d.url(), a.filename)
- log.info('Fixing %d forums', DM.Forum.query.find().count())
- for d in DM.Forum.query.find():
- for a in DM.ForumAttachment.query.find(dict(
- discussion_id=d._id)):
- log.info('%s: %s', d.url(), a.filename)
- log.info('Fixing %d tickets', TM.Ticket.query.find().count())
- for t in TM.Ticket.query.find():
- for a in TM.TicketAttachment.query.find(dict(
- artifact_id=t._id)):
- log.info('%s: %s', t.url(), a.filename)
- log.info('Fixing %d wikis', WM.Page.query.find().count())
- for p in WM.Page.query.find():
- for a in WM.WikiAttachment.query.find(dict(
- artifact_id=p._id)):
- log.info('%s: %s', p.url(), a.filename)
- ThreadLocalORMSession.flush_all()
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/005-remove_duplicate_ticket_notifications.py b/scripts/migrations/005-remove_duplicate_ticket_notifications.py
deleted file mode 100644
index 716c604..0000000
--- a/scripts/migrations/005-remove_duplicate_ticket_notifications.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import logging
-import re
-from itertools import groupby
-
-import pymongo
-from ming.orm import ThreadLocalORMSession
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-# Given a list of subscriptions, try to find one with a proper artifact_url, and delete the rest
-# If none of them have artifact_urls, delete them all
-
-
-def trim_subs(subs, test):
- prime = False
-
- print "Found %d '%s' subs with for user '%s'" % (len(subs), subs[0].artifact_title, str(subs[0].user_id))
- for sub in subs:
- if sub.artifact_url and not prime:
- prime = True
- print " Keeping good subscription with a URL of '%s'" % sub.artifact_url
- else:
- if not sub.artifact_url:
- print " Found subscription with no artifact URL, deleting."
- else:
- print " Subscription has URL, but is a duplicate, deleting."
- if not test:
- sub.delete()
-
-
-def main():
- test = sys.argv[-1] == 'test'
- title = re.compile('Ticket .*')
- all_subscriptions = M.Mailbox.query.find(dict(artifact_title=title, type='direct')).sort(
- [('artifact_title', pymongo.ASCENDING), ('user_id', pymongo.DESCENDING)]).all()
- log.info('Fixing duplicate tracker subscriptions')
-
- for (key, group) in groupby(
- all_subscriptions,
- key=lambda sub: (sub.artifact_title, sub.user_id)):
- group = list(group)
- if group:
- trim_subs(group, test)
- if not test:
- ThreadLocalORMSession.flush_all()
-
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/006-migrate-artifact-refs.py b/scripts/migrations/006-migrate-artifact-refs.py
deleted file mode 100644
index aeae677..0000000
--- a/scripts/migrations/006-migrate-artifact-refs.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import logging
-from cPickle import loads
-
-from allura import model as M
-
-log = logging.getLogger('allura.migrate-artifact-refs')
-
-# Threads have artifact references that must be migrated to the new system
-
-
-def main():
- test = sys.argv[-1] == 'test'
- log.info('Fixing artifact references in threads')
- db = M.project_doc_session.db
- for thread in db.thread.find():
- ref = thread.pop('artifact_reference', None)
- if ref is None:
- continue
- Artifact = loads(ref['artifact_type'])
- artifact = Artifact.query.get(_id=ref['artifact_id'])
- M.ArtifactReference.from_artifact(artifact)
- thread['ref_id'] = artifact.index_id()
- if not test:
- db.thread.save(thread)
- log.info('saving thread %s', thread['_id'])
- else:
- log.info('would save thread %s', thread['_id'])
- M.artifact_orm_session.clear()
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/007-update-acls.py b/scripts/migrations/007-update-acls.py
deleted file mode 100644
index 1cc8f3b..0000000
--- a/scripts/migrations/007-update-acls.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import logging
-from optparse import OptionParser
-from pprint import pformat
-
-import bson
-from tg import tmpl_context as c
-from ming.base import Object
-
-from allura import model as M
-from allura.command.show_models import dfs, build_model_inheritance_graph
-
-log = logging.getLogger('update-acls')
-
-options = None
-optparser = OptionParser(
- usage='allurapaste script <ini file> -- %prog [options] [neighborhood1...]')
-optparser.add_option('-t', '--test', dest='test', action='store_true')
-
-main_db = M.main_doc_session.db
-c_neighborhood = main_db.neighborhood
-c_project = main_db.project
-c_user = main_db.user
-c_project_role = main_db.project_role
-c.project = Object(
- database_uri=M.Project.database_uri())
-
-project_db = M.project_doc_session.db
-c_app_config = project_db.config
-
-
-def main():
- global options
- options, neighborhoods = optparser.parse_args()
- if neighborhoods:
- log.info('Updating neighborhoods: %s', neighborhoods)
- q_neighborhoods = list(
- c_neighborhood.find(dict(name={'$in': neighborhoods})))
- neighborhood_ids = [n['_id'] for n in q_neighborhoods]
- q_projects = list(
- c_project.find(dict(neighborhood_id={'$in': neighborhood_ids})))
- project_ids = list(p['_id'] for p in q_projects)
- q_app_config = list(
- c_app_config.find(dict(project_id={'$in': project_ids})))
- log.info('... %d neighborhoods', len(q_neighborhoods))
- log.info('... %d projects', len(q_projects))
- log.info('... %d app configs', len(q_app_config))
- else:
- q_neighborhoods = c_neighborhood.find()
- q_projects = c_project.find()
- q_app_config = c_app_config.find()
- log.info('Updating all neighborhoods')
- # Update project acls
- log.info('====================================')
- log.info('Update project ACLs')
- for p in q_projects:
- update_project_acl(p)
- if not options.test:
- c_project.save(p)
- # Update neighborhood acls
- log.info('====================================')
- log.info('Update neighborhood ACLs')
- for n in q_neighborhoods:
- p = c_project.find(dict(
- neighborhood_id=n['_id'], shortname='--init--')).next()
- update_neighborhood_acl(n, p)
- if not options.test:
- c_neighborhood.save(n)
- c_project.save(p)
- graph = build_model_inheritance_graph()
- # Update app config acls
- log.info('====================================')
- log.info('Update appconfig ACLs')
- for ac in q_app_config:
- simple_acl_update(ac, 'app_config')
- if not options.test:
- c_app_config.save(ac)
- # Update artifact acls
- log.info('====================================')
- log.info('Update artifact ACLs for %s', ac['_id'])
- for _, a_cls in dfs(M.Artifact, graph):
- c_artifact = project_db[a_cls.__mongometa__.name]
- for a in c_artifact.find(dict(app_config_id=ac['_id'])):
- empty_acl = a['acl'] == []
- simple_acl_update(a, a_cls.__mongometa__.name)
- if not options.test and not empty_acl:
- c_artifact.save(a)
-
-
-def update_project_acl(project_doc):
- '''Convert the old dict-style ACL to a list of ALLOW ACEs. Also move the
- security,tool,delete perms to 'admin'
- '''
- if not isinstance(project_doc['acl'], dict):
- log.warning('Project %s is already updated', project_doc['shortname'])
- return
- perm_map = dict(
- read='read',
- create='create',
- update='update',
- security='admin',
- tool='admin',
- delete='admin')
- new_acl = []
- for perm, role_ids in sorted(project_doc['acl'].iteritems()):
- perm = perm_map[perm]
- for rid in role_ids:
- if c_project_role.find(dict(_id=rid)).count() == 0:
- continue
- _grant(new_acl, perm, rid)
- if options.test:
- log.info('--- update %s\n%s\n%s\n---',
- project_doc['shortname'],
- pformat(_format_acd(project_doc['acl'])),
- pformat(map(_format_ace, new_acl)))
- project_doc['acl'] = new_acl
-
-
-def update_neighborhood_acl(neighborhood_doc, init_doc):
- '''Convert nbhd admins users to --init-- project admins'''
- if options.test:
- log.info('Update nbhd %s', neighborhood_doc['name'])
- if 'acl' not in neighborhood_doc:
- log.warning('Neighborhood %s already updated',
- neighborhood_doc['name'])
- return
- p = Object(init_doc)
- p.root_project = p
- r_anon = _project_role(init_doc['_id'], '*anonymous')
- r_auth = _project_role(init_doc['_id'], '*authenticated')
- r_admin = _project_role(init_doc['_id'], 'Admin')
- acl = neighborhood_doc['acl']
- new_acl = list(init_doc['acl'])
- assert acl['read'] == [None] # nbhd should be public
- for uid in acl['admin'] + acl['moderate']:
- u = c_user.find(dict(_id=uid)).next()
- if options.test:
- log.info('... grant nbhd admin to: %s', u['username'])
- continue
- role = _project_role(init_doc['_id'], user_id=uid)
- if r_admin['_id'] not in role['roles']:
- role['roles'].append(r_admin['_id'])
- c_project_role.save(role)
- _grant(new_acl, 'read', r_anon['_id'])
- _grant(new_acl, 'admin', r_admin['_id'])
- _grant(new_acl, 'register', r_admin['_id'])
- if acl['create'] == []:
- if options.test:
- log.info('grant register to auth')
- _grant(new_acl, 'register', r_auth['_id'])
- del neighborhood_doc['acl']
- if options.test:
- log.info('--- new init acl:\n%s\n%s\n---',
- pformat(_format_acd(init_doc['acl'])),
- pformat(map(_format_ace, new_acl)))
- init_doc['acl'] = new_acl
-
-
-def _project_role(project_id, name=None, user_id=None):
- doc = dict(project_id=project_id)
- if name:
- doc['name'] = name
- else:
- doc['user_id'] = user_id
- for role in c_project_role.find(doc):
- return role
- assert name is None
- doc.update(
- _id=bson.ObjectId(),
- roles=[])
- c_project_role.save(doc)
- return doc
-
-
-def simple_acl_update(doc, collection_name):
- '''Update dict-style to list-style ACL'''
- if not isinstance(doc['acl'], dict):
- log.warning('Already upgraded %s: %s', collection_name, doc)
- return
-
- new_acl = []
- for perm, role_ids in sorted(doc['acl'].iteritems()):
- for rid in role_ids:
- _grant(new_acl, perm, rid)
- if options.test and doc['acl']:
- log.info('--- update %s %s\n%s\n%s\n---',
- collection_name, doc['_id'],
- pformat(_format_acd(doc['acl'])),
- pformat(map(_format_ace, new_acl)))
- doc['acl'] = new_acl
-
-
-def _grant(acl, permission, role_id):
- ace = dict(
- access='ALLOW',
- permission=permission,
- role_id=role_id)
- if ace not in acl:
- acl.append(ace)
-
-
-def _format_ace(ace):
- if isinstance(ace, basestring):
- return ace
- return '(%s, %s, %s)' % (
- ace['access'], ace['permission'], _format_role(ace['role_id']))
-
-
-def _format_role(rid):
- for role in c_project_role.find(dict(_id=rid)):
- if role['name']:
- return role['name']
- if role['user_id']:
- u = c_user.find(_id=role['user_id']).next()
- return u['username']
- break
- return '--invalid--'
-
-
-def _format_acd(acd):
- return dict(
- (k, map(_format_role, v))
- for k, v in acd.iteritems())
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/008-remove-forumpost-subject.py b/scripts/migrations/008-remove-forumpost-subject.py
deleted file mode 100644
index af344d5..0000000
--- a/scripts/migrations/008-remove-forumpost-subject.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""
-Remove the subject FieldProperty from all ForumPost objects. [#2071]
-"""
-
-import logging
-import sys
-
-from allura import model as M
-
-log = logging.getLogger(__name__)
-
-c_forumpost = M.project_doc_session.db.forum_post
-
-
-def main():
- test = sys.argv[-1] == 'test'
-
- forum_posts = c_forumpost.find()
- for fp in forum_posts:
- try:
- s = fp['subject']
- if test:
- log.info('... would remove subject "%s" from %s', s, fp['_id'])
- else:
- log.info('... removing subject "%s" from %s', s, fp['_id'])
- del fp['subject']
- c_forumpost.save(fp)
- except KeyError:
- log.info('... no subject property on %s', fp['_id'])
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/009-set_landing_page.py b/scripts/migrations/009-set_landing_page.py
deleted file mode 100644
index 65ca7a1..0000000
--- a/scripts/migrations/009-set_landing_page.py
+++ /dev/null
@@ -1,140 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-from allura.model import Neighborhood
-from ming.orm import ThreadLocalORMSession
-
-
-homepage = """<style type="text/css">
-ul.ui-tab { display: none; }
-div.content {
- font-family: Helvetica;
-}
-div.content div.row > div.column {
- width: 100%
-}
-div.welcome { margin: 2em 0; }
-div.welcome p {
- display: block;
- position: relative;
- left: 8em;
- width: 80%;
-}
-div.welcome a {
- display: inline-block;
- font-weight: 600;
- color: white;
- margin-left: 1.5em;
- padding: 0.5em 1.5em 0.45em 1.5em;
- text-decoration: none;
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
- background: rgb(0,0,0);
- background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, to(rgb(0,0,0)), from(rgb(90,90,90)));
- background-image: -moz-linear-gradient(100% 100% 90deg, rgb(0,0,0), rgb(90,90,90) 100%);
- border: 1px solid black;
-}
-div.inner-row {
- display: block;
- position: relative;
- padding: 1em 1em 1em 10em;
-}
-div.inner-row + div.inner-row { padding-top: 4.8em; }
-div.tool {
- display: inline-block;
- position: relative;
- width: 30%;
- padding: 0 1em 3em 0;
-}
-div.tool img {
- position: absolute;
- left: -64px;
- top: 0;
-}
-div.tool h1, div.welcome {
- font-size:18px;
- font-weight: 300;
-}
-div.tool h1 {
- position: relative;
- top: -15px;
-}
-div.tool p {
- display: block;
- font-size: 13px;
- line-height: 18px;
- position: absolute;
- padding-right: 6em;
- top: 12px;
-}
-</style>
-<div class="welcome">
- <p>We provide the tools. You create great open source software.
- <a href="/p/add_project">Start Your Project</a>
- </p>
-</div>
-<div class="inner-row">
- <div class="tool">
- <img src="/nf/allura/images/wiki_48.png" alt=""/>
- <h1>Wikis</h1>
- <p>
- Documentation is key to your project and the wiki tool helps make it easy for anyone to contribute.
- </p>
- </div>
- <div class="tool">
- <img src="/nf/allura/images/code_48.png" alt=""/>
- <h1>Code</h1>
- <p>
- SVN, Git and Mercurial will help you keep track of your changes.
- </p>
- </div>
- <div class="tool">
- <img src="/nf/allura/images/tickets_48.png" alt=""/>
- <h1>Tickets</h1>
- <p>
- Bugs, enhancements, tasks, etc., will help you plan and manage your development.
- </p>
- </div>
-</div>
-<div class="inner-row">
- <div class="tool">
- <img src="/nf/allura/images/downloads_48.png" alt=""/>
- <h1>Downloads</h1>
- <p>
- Use the largest free, managed, global mirror network to distribute your files.
- </p>
- </div>
- <div class="tool">
- <img src="/nf/allura/images/stats_48.png" alt=""/>
- <h1>Stats</h1>
- <p>
- Follow the download trends that enable you to develop better software.
- </p>
- </div>
- <div class="tool">
- <img src="/nf/allura/images/forums_48.png" alt=""/>
- <h1>Forums</h1>
- <p>
- Collaborate with your community in your forums.
- </p>
- </div>
-</div>
-"""
-
-projects_neighborhood = Neighborhood.query.find(dict(name='Projects')).first()
-projects_neighborhood.homepage = homepage
-ThreadLocalORMSession.flush_all()
diff --git a/scripts/migrations/010-fix-home-permissions.py b/scripts/migrations/010-fix-home-permissions.py
deleted file mode 100644
index 1b669d5..0000000
--- a/scripts/migrations/010-fix-home-permissions.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import logging
-from collections import OrderedDict
-
-from tg import tmpl_context as c
-from ming.orm import session
-from bson import ObjectId
-
-from allura import model as M
-from allura.lib import utils
-from forgewiki.wiki_main import ForgeWikiApp
-
-log = logging.getLogger('fix-home-permissions')
-handler = logging.StreamHandler(sys.stdout)
-log.addHandler(handler)
-
-TEST = sys.argv[-1].lower() == 'test'
-
-
-def main():
-
- if TEST:
- log.info('Examining permissions for all Home Wikis')
- else:
- log.info('Fixing permissions for all Home Wikis')
-
- for some_projects in utils.chunked_find(M.Project, {'neighborhood_id': {
- '$nin': [ObjectId('4be2faf8898e33156f00003e'), # /u
- ObjectId('4dbf2563bfc09e6362000005')]}}): # /motorola
- for project in some_projects:
- c.project = project
- home_app = project.app_instance('home')
- if isinstance(home_app, ForgeWikiApp):
- log.info('Examining permissions in project "%s".' %
- project.shortname)
- root_project = project.root_project or project
- authenticated_role = project_role(
- root_project, '*authenticated')
- member_role = project_role(root_project, 'Member')
-
- # remove *authenticated create/update permissions
- new_acl = OrderedDict(
- ((ace.role_id, ace.access, ace.permission), ace)
- for ace in home_app.acl
- if not (
- ace.role_id == authenticated_role._id and ace.access == M.ACE.ALLOW and ace.permission in (
- 'create', 'edit', 'delete', 'unmoderated_post')
- )
- )
- if (member_role._id, M.ACE.ALLOW, 'update') in new_acl:
- del new_acl[(member_role._id, M.ACE.ALLOW, 'update')]
-
- # add member create/edit permissions
- new_acl[(member_role._id, M.ACE.ALLOW, 'create')
- ] = M.ACE.allow(member_role._id, 'create')
- new_acl[(member_role._id, M.ACE.ALLOW, 'edit')
- ] = M.ACE.allow(member_role._id, 'edit')
- new_acl[(member_role._id, M.ACE.ALLOW, 'unmoderated_post')] = M.ACE.allow(
- member_role._id, 'unmoderated_post')
-
- if TEST:
- log.info(
- '...would update acl for home app in project "%s".' %
- project.shortname)
- else:
- log.info('...updating acl for home app in project "%s".' %
- project.shortname)
- home_app.config.acl = map(dict, new_acl.values())
- session(home_app.config).flush()
-
-
-def project_role(project, name):
- role = M.ProjectRole.query.get(project_id=project._id, name=name)
- if role is None:
- role = M.ProjectRole(project_id=project._id, name=name)
- return role
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/011-fix-subroles.py b/scripts/migrations/011-fix-subroles.py
deleted file mode 100644
index cb63c6b..0000000
--- a/scripts/migrations/011-fix-subroles.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""
-For projects:
- * Admin role.roles should contain Developer, and Developer only
- * Developer role.roles should contain Member, and Member only
-
-For project.users:
- * user.project_role().roles, if it contains Admin, should not contain
- Developer or Member
- * user.project_role().roles, if it contains Developer, should not contain
- Member
-"""
-import sys
-import logging
-
-from ming.orm import session
-from ming.orm.ormsession import ThreadLocalORMSession
-
-from allura import model as M
-from allura.lib import utils
-
-log = logging.getLogger('fix-subroles')
-log.addHandler(logging.StreamHandler(sys.stdout))
-
-
-def main():
- test = sys.argv[-1] == 'test'
- num_projects_examined = 0
- log.info('Examining subroles in all non-user projects.')
- n_users = M.Neighborhood.query.get(name='Users')
- project_filter = dict(neighborhood_id={'$ne': n_users._id})
- for some_projects in utils.chunked_find(M.Project, project_filter):
- for project in some_projects:
- project_name = '%s.%s' % (
- project.neighborhood.name, project.shortname)
- project_roles = {}
- for parent, child in [('Admin', 'Developer'), ('Developer', 'Member')]:
- parent_role = M.ProjectRole.by_name(parent, project=project)
- child_role = M.ProjectRole.by_name(child, project=project)
- project_roles[parent] = parent_role
- project_roles[child] = child_role
- if not (parent_role and child_role):
- break
- if len(parent_role.roles) != 1 or parent_role.roles[0] != child_role._id:
- if test:
- log.info('Would reset %s subroles for project "%s".' %
- (parent, project_name))
- log.info('- Existing %s subrole(s): %s' %
- (parent, parent_role.roles))
- else:
- log.info('Resetting %s subroles for project "%s".' %
- (parent, project_name))
- parent_role.roles = [child_role._id]
- ThreadLocalORMSession.flush_all()
- if not (project_roles['Admin'] and project_roles['Developer']
- and project_roles['Member']):
- log.info(
- 'Skipping "%s": missing Admin, Developer, or Member roles' %
- project_name)
- continue
- for user in project.users():
- pr = user.project_role(project=project)
- if not pr.roles:
- continue
- for parent, children in [('Admin', ('Developer', 'Member')),
- ('Developer', ('Member',))]:
- if project_roles[parent]._id not in pr.roles:
- continue
- for role_name in children:
- extra_role = project_roles[role_name]
- if extra_role._id in pr.roles:
- if test:
- log.info('Would remove %s role from user "%s" in project "%s" (already has %s role).'
- % (role_name, user.username, project_name, parent))
- pr.roles.remove(extra_role._id)
- else:
- log.info('Removing %s role from user "%s" in project "%s" (already has %s role).'
- % (role_name, user.username, project_name, parent))
- pr.roles.remove(extra_role._id)
- ThreadLocalORMSession.flush_all()
- num_projects_examined += 1
- session(project).clear()
-
- log.info('%s projects examined.' % num_projects_examined)
-
-if __name__ == '__main__':
- main()
diff --git a/scripts/migrations/012-uninstall-home.py b/scripts/migrations/012-uninstall-home.py
deleted file mode 100644
index 9c5bd79..0000000
--- a/scripts/migrations/012-uninstall-home.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import sys
-import logging
-
-from tg import tmpl_context as c
-from ming.orm import session
-from bson import ObjectId
-from mock import Mock, patch
-
-from allura.lib import helpers as h
-from allura.lib import utils
-from allura import model as M
-from forgewiki import model as WM
-from allura.ext.project_home import ProjectHomeApp
-
-log = logging.getLogger('uninstall-home')
-log.addHandler(logging.StreamHandler(sys.stdout))
-
-
-def main():
- test = sys.argv[-1] == 'test'
- log.info('Removing "home" tools')
- affected_projects = 0
- possibly_orphaned_projects = 0
- solr_delete = Mock()
- notification_post = Mock()
- for some_projects in utils.chunked_find(M.Project, {'neighborhood_id': {
- '$ne': ObjectId("4be2faf8898e33156f00003e")}}):
- for project in some_projects:
- c.project = project
- old_home_app = project.app_instance('home')
- if isinstance(old_home_app, ProjectHomeApp):
-
- # would we actually be able to install a wiki?
- if M.ProjectRole.by_name('Admin') is None:
- log.warning('project %s may be orphaned' %
- project.shortname)
- possibly_orphaned_projects += 1
- continue
-
- affected_projects += 1
-
- # remove the existing home tool
- if test:
- log.info('would remove "home" tool from project ' +
- project.shortname)
- else:
- log.info('removing "home" tool from project ' +
- project.shortname)
- with patch('allura.app.g.solr.delete', solr_delete):
- project.uninstall_app('home')
-
- # ...and put a Wiki in its place (note we only create a Wiki if we deleted the old home)
- if test:
- log.info('would create Wiki "home" for project ' +
- project.shortname)
- else:
- log.info('creating Wiki "home" for project ' +
- project.shortname)
- home_title = project.homepage_title or 'Home'
- wiki_text = project.description or ''
- if wiki_text == 'You can edit this description in the admin page':
- wiki_text = 'You can edit this description'
-
- # re-number all the mounts so the new Wiki comes first
- mounts = project.ordered_mounts()
- with patch('forgewiki.model.wiki.Notification.post', notification_post):
- new_home_app = project.install_app(
- 'Wiki', 'home', 'Home')
- mounts = [{'ordinal': 0, 'ac': new_home_app.config}] + \
- mounts
- for i, mount in enumerate(mounts):
- if 'ac' in mount:
- mount['ac'].options['ordinal'] = i
- session(mount['ac']).flush()
- elif 'sub' in mount:
- mount['sub'].ordinal = i
- session(mount['sub']).flush()
-
- # make it look as much like the old home tool as possible
- new_home_app.config.options['show_left_bar'] = False
- new_home_app.config.options['show_discussion'] = False
-
- # now let's fix the home page itself
- log.info('updating home page to "%s"' % home_title)
- new_home_page = WM.Page.query.find(
- dict(app_config_id=new_home_app.config._id)).first()
- with h.push_config(c, app=new_home_app):
- if new_home_page is None:
- # weird: we didn't find the existing home page
- log.warning(
- 'hmmm, actually creating the home page ("%s") for project "%s" from scratch' %
- (home_title, project.shortname))
- new_home_page = WM.Page.upsert(home_title)
- new_home_page.viewable_by = ['all']
- new_home_page.title = home_title
- new_home_page.text = wiki_text
- with patch('forgewiki.model.wiki.Notification.post', notification_post):
- new_home_page.commit()
- assert new_home_page is not None
- assert new_home_page.title == home_title
- assert new_home_page.version == 2
-
- # if we changed the home page name, make sure the Wiki
- # knows that's the root page
- new_home_app.root_page_name = home_title
-
- session(project).flush()
- session(project).clear()
- if test:
- log.info('%s projects would be updated' % affected_projects)
- else:
- log.info('%s projects were updated' % affected_projects)
- if possibly_orphaned_projects:
- log.warning('%s possibly orphaned projects found' %
- possibly_orphaned_projects)
- if not test:
- assert solr_delete.call_count == affected_projects, solr_delete.call_count
- assert notification_post.call_count == 2 * \
- affected_projects, notification_post.call_count
-
-if __name__ == '__main__':
- main()