| # 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() |