Skip To Content

Example: Create users and roles from two text files

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:]))