blob: cb63c6b5373f57eb9055474253da3dcaa693e55a [file] [log] [blame]
# 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()