<jupyter_start><jupyter_text>Configure Target UsersIn this notebook, we add users to the delivery org and invite them to groups. Users will be able to find the invites to the new groups on the 'Groups' tab or in their notifications.  Getting Started1. Find the group IDs for the featured group and for any groups in the project org you will be adding delivery org users to.2. Set up the csv file of users. This csv should have columns for email, firstname, lastname, username, password, role, level, and groups. The groups column should contain group IDs that are separated by commas. There is a sample user csv in the Sample Config folder, and there is more information about formatting [`here`](https://learn.arcgis.com/en/projects/set-up-an-arcgis-enterprise-portal/lessons/add-members-to-the-organization.htm) in steps 4 & 5. Make sure that the User Roles you choose are able to be added to groups in other organizations! The default 'Viewer' role is not able to be added to groups outside of the organization.3. Change the variables in cell 1. Example variables:    - TARGET_URL = "https://esrienergy.maps.arcgis.com"    - TARGET_USERNAME = "portaladmin"    - GROUP_IDS = ["a7903db4086641b98570bce5856a6364", "4d7ff4f81d6340428ef290b7de801204"]    - FEATURED_GROUP_ID = "4f4fcac023dc430294cea226231ab448"4. Run the notebook cell by cell.    - In code cell 4, you will need to enter the passwords for the delivery organizations when prompted    - In code cell 6, the script will print out the users that were added to the delivery org and the groups they were added to5. At the end, your delivery org should have all the users in the csv file added and each should get an invitation in their Organization Account for each group listed for them. Once they accept it, they will be shown in the group members in the Project Organization as well. The delivery org will also be customized.<jupyter_code># Global Variables Set by User **change these values before running script**

# URL of the portal that will be customized and have users added
TARGET_URL = "https://pdo-scripts.maps.arcgis.com"

# Delivery username for log-on (needs to be admin)
TARGET_USERNAME = "target_username"

# project groups to share with *ALL* delivery users
GROUP_IDS = ["5e831faa6e574e46ae2e019d0e897a4f"]

# featured group to display on delivery home page #aec-test-group
FEATURED_GROUP_ID = "5e831faa6e574e46ae2e019d0e897a4f"

# import libraries
from arcgis.gis import GIS
from arcgis.gis import Group
from arcgis.gis import UserManager
import os
import csv
# get UI component filepaths
USERS = os.path.join(FOLDER, USERS_FILENAME)
USER_FIELDS = ["Email", "First Name", "Last Name", "Username", "Password", "Role", "User Type", "groups"]
# connect to delivery org
print("Connecting to {} with username {}...".format(TARGET_URL, TARGET_USERNAME))
delivery = GIS(TARGET_URL, TARGET_USERNAME)
# Creation of functions to be used later
def optional_args_handler(key, user, default=None):
    """Sets optional user creation arguments appropriately"""
    try:
        var = None
        if key in user:
            var = user[key]
        else:
            if default:
                var = default
        return var
    except Exception as e:
        print("Optional args handler failed with args {}, {}, and {}: {}".format(key, user, default, e))

def add_user(user, target, groups=[]):
    """Add user to the gis and to specified groups
    * Abstraction for creating from dict such as with csv

    args:
    user -- a dictionary containing user fields, see fields:
        http://esri.github.io/arcgis-python-api/apidoc/html/arcgis.gis.toc.html#arcgis.gis.UserManager.create
    target -- the delivery org, where users are added
    groups -- (optional) destination groups, compliments those in dict
    """
    try:
        print("INFO: Creating user {}".format(user["Username"]))
        role = optional_args_handler('Role', user, 'viewer') # default is viewer
        user_type = optional_args_handler('User Type', user, 'viewer') # default is viewer
        
        # create array of groups for user
        user_groups = []
        for grp in groups:
            user_groups.append(grp)

        group_str = user.pop('groups', None)
        if group_str:
            group_list = group_str.split(",")
            for g in group_list:
                try:
                    group_search = Group(target, g)
                    if group_search.title:
                        user_groups.append(group_search)
                except Exception as e:
                    print("ERR: Could not find group id {}".format(g))
                    continue
        print("User will be invited to join: {}".format([g.title for g in user_groups]))
        
        result = target.users.create(username=user['Username'], password=<PASSWORD>['Password'], firstname=user['First Name'], 
                                  lastname=user['Last Name'], email=user['Email'], role=role, user_type=user_type)

        # create users returns None if it was unsuccessful
        if not result:
            print("Did not create user: Check username {}".format(user['Username']))
            return

        # Invite user to groups
        print("Inviting to groups")
        for g in user_groups:
            try:
                res = target.groups.get(g.groupid).invite_users([user['Username']])
                if res == True:
                    print("Invited user {} to group {}".format(user['Username'], g.title))
                else: # res == False
                    print("Failed to invite user {} to group {}: {}".format(user['Username'], g.title, res))
            except Exception as e:
                print("ERR: Could not add user {} to group {}: {}".format(user['Username'], g, e))
                continue
        return result
    except Exception as e:
        print("ERR: Could not create User {}: Add User encountered error {}".format(user['Username'], e))

def add_users_csv(csv_file, target, groups=None):
    """Add users from csv to gis

    args:
    csv_file -- path to csv with users to create
    target -- delivery organization where users are added
    groups -- (optional) destination groups, compliments those in csv (default [])
    """
    try:
        results = []
        with open(csv_file, 'r') as users_csv:
            users = csv.DictReader(users_csv, fieldnames=USER_FIELDS)
            next(users, None) # skip the header
            for user in users:
                result = add_user(user, target, groups=groups)
                results.append(result)
        return results
    except Exception as e:
        print("Add users csv failed with args {}, {}, and {}: {}".format(csv_file, target, groups, e))
# fetch groups where *ALL* users will be added
share_groups = tuple(Group(delivery, g) for g in GROUP_IDS)
print(share_groups)

# add users to the delivery org and invite them to groups in target org
add_users_csv(USERS, delivery, groups=share_groups)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09142857142857143, 'fraction_numerical': 0.016285714285714285, 'mean_word_length': 2.9287317620650954, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '517663', 'license': 'Apache-2.0', 'n_tokens_mistral': 2012, 'n_tokens_neox': 1898, 'n_words': 756, 'path': 'agol-to-agol-notebooks/Configure_Target_Users.ipynb', 'repo_name': 'Esri/project-delivery-scripts', 'size': '6994'}