Users & Groups Migration

Export using a script:

""" To run this file:
    $ bin/instance run export_users.py
"""

import os
import json

site = app.Plone

os.mkdir('99')
counter = 99000

uf = site.acl_users
users = uf.source_users.getUsers()

exported_users = {"_acl_users": dict()}

for user in users:
    user_data = {
        'email': user.getProperty('email'),
        'roles': user.getRoles(),
    }
    exported_users['_acl_users'][user._id] = user_data

f = open(os.path.join('99', str(counter) + '.json'), 'wb')
json.dump(exported_users, f, indent=4)
counter += 1
f.close()

groups = dict(uf.source_groups._groups)
exported_groups = {"_acl_groups": dict()}
for group in groups:
    # Loop over each group grabbing members
    members = uf.source_groups._group_principal_map[group].keys()
    roles = uf.getGroupByName(group)._roles
    group_info = {
        'title': groups[group]['title'],
        'description': groups[group]['description'],
        'members': members,
        'roles': roles,
    }
    exported_groups['_acl_groups'][group] = group_info

f = open(os.path.join('99', str(counter) + '.json'), 'wb')
json.dump(exported_groups, f, indent=4)
counter += 1
f.close()

The import can be done as blueprints, which is the code below. But it would be better off as an upgrade step.

@provider(ISectionBlueprint)
@implementer(ISection)
class ImportUsers(object):
    """ Import users that had been exported
        with the custom export script
    """

    def __init__(self, transmogrifier, name, options, previous):
        self.previous = previous

    def __iter__(self):
        for item in self.previous:
            if '_acl_users' not in item:
                yield item
                continue

            for person in item['_acl_users']:
                user = api.user.get(username=person)
                data = item['_acl_users'][person]
                roles = data['roles']
                # remove these roles, they cannot be granted
                if 'Authenticated' in data['roles']:
                    roles.remove('Authenticated')
                if 'Anonymous' in data['roles']:
                    roles.remove('Anonymous')
                if not data['email']:
                    data['email'] = 'user@site.com'

                if user:
                    api.user.grant_roles(username=person, roles=roles)
                    continue
                try:
                    user = api.user.create(username=person,
                                           email=data['email'])
                    api.user.grant_roles(username=person, roles=roles)
                except ValueError as e:
                    logger.warn("Import User '{0}' threw an error: {1}".format(
                        person, e))
            yield item

@provider(ISectionBlueprint)
@implementer(ISection)
class Groups(object):
    """ Import groups that had been exported
        with the custom export script
    """

    def __init__(self, transmogrifier, name, options, previous):
        self.transmogrifier = transmogrifier
        self.name = name
        self.options = options
        self.previous = previous
        self.context = transmogrifier.context

        if 'acl_groups-key' in options:
            groupskeys = options['acl_groups-key'].splitlines()
        else:
            groupskeys = defaultKeys(
                options['blueprint'], name, 'acl_groups')
        self.groupskey = Matcher(*groupskeys)

    def __iter__(self):
        for item in self.previous:
            groupskey = self.groupskey(*item.keys())[0]

            if not groupskey:
                yield item
                continue

            group_tool = api.portal.get_tool(name='portal_groups')
            if '_acl_groups' not in item:
                yield item
                continue
            for group in item['_acl_groups']:
                acl_group = api.group.get(groupname=group)
                props = item['_acl_groups'][group]
                if not acl_group:
                    acl_group = api.group.create(
                        groupname=group,
                        title=props['title'],
                        description=props['description'],
                        roles=props['roles'],
                    )
                else:
                    group_tool.editGroup(
                        group,
                        roles=props['roles'],
                        title=props['title'],
                        description=props['description'],
                    )
                for member in props['members']:
                    acl_group.addMember(member)

            yield item