Skip To Content

Example: Create users and roles from two text files

This ArcGIS 10.8 documentation has been archived and is no longer updated. Content and links may be outdated. See the latest documentation.

There are various approaches for populating ArcGIS Server's built-in security store using the ArcGIS REST API. This particular script creates users and roles using two text files: one containing a list of users and the other containing a list of roles. With this script it's possible to assign a single user to multiple roles.

The input file containing the roles should be structured like this:

#Role|Description|Privilege
admins|Server Administrators|ADMINISTER
publishers|Service Publishers|PUBLISH
rangers|Park rangers|ACCESS
volunteers|Volunteer staff|ACCESS
visitors|Visitors|ACCESS

  • Role—A name for the role.
  • Description—A user-friendly description for the role.
  • Privilege—The ArcGIS Server role type that determines the level of privilege held by the role. There are three levels of privilege: ADMINISTER|PUBLISH|ACCESS. See Restricting access to ArcGIS Server to learn about these.

The input file containing the users should be structured like this:

#User|Password|EMail|FullName|Description|RolesThatTheUserBelongsTo
John|changeme|johndoe@esri.com|John Doe|Server admin|admins
Jane|changeme|janedoe@esri.com|Jane Doe|Server publisher|publishers,rangers
Amy|changeme|amy@esri.com|Amy Doe|Summer intern|volunteers
Bob|changeme|bob@esri.com|Bob Doe|Park visitor|visitors

  • User—The name for the user
  • Password—The password for the user
  • EMail—The e-mail address for the user
  • FullName—The full name or detailed name of the user
  • Description—A description of the user
  • RolesThatTheUserBelongsTo—A comma-delimited list of roles to which the user should be assigned

You can modify the script code to expect a different property set or set some of the above properties by default.

Below is the script body:

import json

import urllib,httplib

import sys

import getpass

import codecs

def main(argv=None):
    
    # Ask for admin user name and password
    
    username = raw_input("Enter user name: ")
    password = getpass.getpass("Enter password: ")
    
    # Ask for server name and the port
    serverName = raw_input("Enter server name: ")
    serverPort = raw_input("Enter server port: ")

    # Get a token and connect
    token = getToken(username, password, serverName, serverPort)
    
    if token == "":
        sys.exit(1)
    
    # Input file that contains the role information
    rolesFile = raw_input("Path to pipe-delimited text file containing roles: ")
    
    # Input file that contains the user information
    usersFile = raw_input("Path to pipe-delimited text file containing users: ")

    # Dictionaries to store user and role information
    roles = {}
    rolePrivileges = {}

    users = {}   
    userRoles = {}

    # Loop through the roles file and create the roles 
    # Add the user information to a dictionary
    num = 0 
    for roleRow in readlinesFromInputFile(rolesFile):
        roles["role" + str(num)] = {"rolename":roleRow[0],"description":roleRow[1]}
        rolePrivileges["rolePrivilege" + str(num)] = {"rolename":roleRow[0], "privilege":roleRow[2]}
        num +=1

    # Read the user's file
    num = 0
    for userRow in readlinesFromInputFile(usersFile):
        # Add the user information to a dictionary
        users["user" + str(num)] = {"username":userRow[0],"password":userRow[1],"email":userRow[2], "fullname":userRow[3],"description":userRow[4].rstrip()}
        userRoles["userRole"+str(num)] = {"username" : userRow[0],"roles":userRow[5]}
        num +=1

    # Call helper functions to add users and roles
    addRoles(roles,serverName, serverPort,token)
    assignPrivilegeToRole(rolePrivileges, serverName, serverPort, token)
    addUsers(users,serverName, serverPort,token)
    addUsersToRoles(userRoles, serverName, serverPort, token)

# A function that reads lines from the input file
def readlinesFromInputFile(filename, delim='|'):
    file = codecs.open(filename,'r','utf-8-sig')
    for line in file.readlines():
        # Remove the trailing whitespaces and the newline characters
        line = line.rstrip()
        
        if line.startswith('#') or len(line) == 0:
            pass # Skip the lines that contain # at the beginning or any empty lines
        else:
            # Split the current line into list
            yield line.split(delim)
    file.close()
             
# A function that will post HTTP POST request to the server
def postToServer(serverName, serverPort, url, params):
    
    httpConn = httplib.HTTPConnection(serverName, serverPort)
    headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}

    # URL encode the resource URL
    url = urllib.quote(url.encode('utf-8'))
    
    # Build the connection to add the roles to the server
    httpConn.request("POST", url, params, headers)

    response = httpConn.getresponse()
    data = response.read()
    httpConn.close()

    return (response, data)

# Helper function that adds the roles
def addRoles(roleDict, serverName, serverPort, token):
    
    for roleToAdd in roleDict:

        role = roleDict[roleToAdd]
        print "Adding the role: " + role['rolename']
        
        # URL for adding a role
        addroleURL = "/arcgis/admin/security/roles/add"
        params = urllib.urlencode({'token':token,'f':'json','rolename':role['rolename'],'description':role['description']})
        response, data = postToServer(serverName, serverPort, addroleURL, params)
        
        if (response.status != 200 or not assertJsonSuccess(data)):
            print "Error adding the role: " + role['rolename']
            print str(data)
        else:
            print "Added the role '" + role['rolename'] + "' successfully"

# Helper function that assigns privileges to roles
def assignPrivilegeToRole(privileges, serverName, serverPort, token):
    
        for privilegeToAssign in privileges:
            
            privilege = privileges[privilegeToAssign]
            
            # URL for assigning a privilege to a role
            assignPrivilegeURL = "/arcgis/admin/security/roles/assignPrivilege"
            params = urllib.urlencode({'token':token,'f':'json','rolename':privilege['rolename'],'privilege':privilege['privilege']})
    
            response, data = postToServer(serverName, serverPort, assignPrivilegeURL, params)

            if (response.status != 200 or not assertJsonSuccess(data)):
                print "Could not assign the privilege '" + privilege['privilege'] + "' to the role '" + privilege['rolename'] + "'"
                print str(data)
            else:
                print "Assigned the privilege '" + privilege['privilege'] + "' to the role '" + privilege['rolename'] + "' successfully" 

# Helper function that adds the users       
def addUsers(userDict,serverName, serverPort, token):

    for userAdd in userDict:
        user = userDict[userAdd]
        
        print "Adding the user:" + user['username']
        
        # URL for adding a user
        addUserURL = "/arcgis/admin/security/users/add"
        params = urllib.urlencode({'token':token,'f':'json','username':user['username'],'password':user['password'],'fullname':user['fullname'],'description':user['description'],'email':user['email']})
        
        response, data = postToServer(serverName, serverPort, addUserURL, params)
        
        if (response.status != 200 or not assertJsonSuccess(data)):
            print "Error adding user: " + user['username']
            print str(data)
        else:
            print "Added the user '" + user['username'] + "' successfully"

# Helper function that adds users to roles
def addUsersToRoles(userRoleDict,serverName, serverPort, token):

    for userAdd in userRoleDict:
        
        userRole = userRoleDict[userAdd]
        print "Adding the user '" + userRole['username'] + "' to the role(s) '" + userRole['roles'] + "'"

        addUserToRolesURL = "/arcgis/admin/security/users/assignRoles"
        params = urllib.urlencode({'token':token,'f':'json',"userName":userRole['username'],"roles":userRole['roles']})
       
        response, data = postToServer(serverName, serverPort, addUserToRolesURL, params)
        
        if (response.status != 200 or not assertJsonSuccess(data)):
            print "Could not add user '" + userRole['username'] + "' to the role(s) '" + userRole['roles'] + "'"
            print str(data)
        else:
            print "Added the user '" + userRole['username'] + "' to the role(s) '" + userRole['roles'] + "' successfully"
                            

def getToken(username, password, serverName, serverPort):

    httpConn = httplib.HTTPConnection(serverName, serverPort)

    tokenURL = "/arcgis/admin/generateToken"
    
    params = urllib.urlencode({'username': username, 'password': password,'client': 'requestip', 'f': 'json'})
    
    response, data = postToServer(serverName, serverPort, tokenURL, params)
        
    if (response.status != 200 or not assertJsonSuccess(data)):
        print "Error while fetching tokens from admin URL. Please check if the server is running and ensure that the username/password provided are correct"
        print str(data)
        return
    else: 
        # Extract the token from it
        token = json.loads(data)   
        return token['token']            
        

# A function that checks that the JSON response received from the server does not contain an error   
def assertJsonSuccess(data):
    obj = json.loads(data)
    if 'status' in obj and obj['status'] == "error":
        return False
    else:
        return True

# Script start 
if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))