Skip To Content

示例:向门户添加成员

本例将采用包含用户信息的输入文本文件,并将其中的用户批量地添加到门户中。 为门户中的每个用户定义并授予角色。

运行脚本时,输入以下信息:

  • 包含用户信息的文本文件的路径,例如,C:\users.txt
  • 希望添加到门户的用户类型,例如内置企业。 有关用户类型的详细信息,请参阅管理对门户的访问
  • 托管门户的计算机的完全限定域名,例如 myportal.acme.com。 此脚本将通过端口 7443 上的 HTTPS 访问门户,并绕过 ArcGIS Web Adaptor。 采用这种方法时,如果已将门户配置为使用 Web 层身份验证,则脚本无需对其进行处理。
  • 具有门户管理权限的帐户的用户名和密码。 如果您正在添加内置帐户,则可以提供任何具有管理权限的门户成员的凭据。 如果正在添加组织特定的帐户,则可使用安装 Portal for ArcGIS 后创建的初始管理员帐户
注:

本示例中不会演示如何使 Python 脚本处理 Web 层身份验证。

注册企业帐户

注册企业帐户时,文本文件中每个条目的格式如下:

<login>|<email address>|<name>|<role>|<description>|<Idp UserName>

  • 登录名 - 要注册的企业登录名。

    • 如果使用活动目录,则登录名的形式为 sAMAccountName@DOMAIN。 域名字母必须全大写。
    • 如果使用 LDAP,则登录名与配置身份存储时指定的 userNameAttribute 值匹配。
    • 如果使用的是基于 SAML 的企业登录,则指定的登录名值与 SAML 身份提供者中的 NameID 属性匹配。
  • 电子邮件地址 - 电子邮件应与登录名相关联,并匹配标识存储中的值。 如果用户帐户没有电子邮件地址,则提供一个 false 或通用值。

  • 名称 - 您 ArcGIS 组织中使用的登录名的别名。 大部分标识存储将用户的全名用作默认别名。 用户连接到门户网站后,此名称将显示在网站顶部。

  • 用户类型 - 将为用户分配的用户类型的名称。 可以从下拉列表中选择任意可用的用户类型。 可以单击兼容的角色和兼容的加载项许可计数,以了解有关与所选用户类型兼容的内容的详细信息。 有关详细信息,请参阅用户类型、角色和权限
  • 角色 - 企业登录帐户将在 ArcGIS 组织中拥有的角色。 有效的角色值包括 userpublisheradmin<custom_role_name>,其中 <custom_role_name> 为自定义角色的名称(例如 hostedservicepublisher)。

    旧版本:

    在 Portal for ArcGIS 10.3 和更早版本中,可以接受的非自定义角色值包括 org_userorg_publisherorg_admin。 10.3.1 版本已经弃用这些值,并替换为上述值。 在 10.3.1 版本中,您可以继续使用这些弃用值,但是请注意,未来版本可能无法接受这些值。

  • 描述 - 还可以使用文本描述帐户。 该值与标识存储中的所有属性均不对应。 描述的长度不能超过 250 个字符。

  • Idp 用户名 - 您还可以指定身份提供者中企业帐户的用户名。 如果未给出此值,则使用为登录名参数指定的值。

您需要为登录名、电子邮件地址、名称和角色提供一个值。 描述和 Idp 用户名为可选项。 对文件中列出的每个帐户,验证登录名、电子邮件和名称输入的值是否与标识存储中的值准确匹配。 门户将不会连接到您的标识存储以验证这些值。

以下是注册活动目录企业帐户的条目示例,登录名为 jcho111,电子邮件地址是 jcho@domain.com,全名为 Jon Cho。 此登录位于用户角色 (user) 和 Viewer 用户类型中,并描述为部门 b 中的用户。

jcho111@DOMAIN|jcho@domain.com|Jon Cho|Viewer|user|department b

以下是注册 SAML 身份提供者中企业帐户的条目示例。 用户的登录名为 rsmith@domain.com,电子邮件地址为 rsmith@domain.com,全名为 Robert Smith。 登录位于发布者角色 (publisher) 和 Creator 用户类型中,Idp 用户名为 rsmith@domain.com。

rsmith@domain.com|rsmith@domain.com|Robert Smith|Creator|publisher||rsmith@domain.com

以下是注册 LDAP 企业帐户的条目示例,登录名为 sjames4513,电子邮件地址是 sjames@domain.com,全名为 Sara James。 此登录位于用户角色 (admin) 和 GIS Professional 用户类型中,并提供了描述。

sjames4513@DOMAIN|sjames@domain.com|Sara James|GISProfessional|admin|Department Lead and GIS Manager

以下是注册企业帐户的条目示例,登录名为 srajhandas,电子邮件地址是 srajhandas@domain.com,全名为 Satish Rajhandas。 此登录位于用户角色 (user) 和 Viewer 用户类型中。

srajhandas@DOMAIN|srajhandas@domain.com|Satish Rajhandas|Viewer|user

以下是注册 SAML 身份提供者中企业帐户的条目示例。 用户的登录名为 djohnson308,电子邮件地址为 djohnson@domain.com,全名为 Daisha Johnson。 此登录位于用户角色 (user) 和 Creator 用户类型中,并提供了描述,Idp 用户名定义为 djohnson@domain.com。

djohnson308@DOMAIN|djohnson@domain.com|Daisha Johnson|Creator|user|Account Specialist|djohnson@domain.com

添加内置门户帐户

添加内置门户帐户时,文本文件中每个条目的格式如下:

<username>|<password>|<email address>|<name>|<user type>|<role>|<description>

  • 用户名 - 用于内置帐户的用户名。 用户名必须是唯一的;不同成员不可以具有相同的用户名。
  • 密码 - 分配给此帐户的密码。 用户可在首次登录门户时使用此密码,之后可通过编辑配置文件修改密码。
  • 电子邮件地址 - 为此帐户提供电子邮件地址。 此参数是必填项,因此必须为电子邮件地址提供一个值,即使该地址无效。
  • 名称 - 将在 ArcGIS 组织中使用的帐户的别名。 用户连接到门户网站后,此名称将显示在门户网站的顶部。
  • 用户类型 - 将为用户分配的用户类型的名称。 可以从下拉列表中选择任意可用的用户类型。 可以单击兼容的角色和兼容的加载项许可计数,以了解有关与所选用户类型兼容的内容的详细信息。 有关详细信息,请参阅用户类型、角色和权限
  • 角色 - 帐户在 ArcGIS 组织中拥有的角色。 有效的角色值包括 user、publisher、admin 或 <custom_role_name>,其中 <custom_role_name> 为自定义角色的名称(例如 hostedservicepublisher)。
  • 描述 - 还可以使用文本描述帐户。 描述的长度不能超过 250 个字符。

以下是为 Barbara Williams 添加内置门户帐户的条目示例,其中用户名为 pub1,电子邮件帐户为 bwilliams@domain.com。 示例还会将 pub1 添加到发布者角色:

pub1|changepasswordlater|bwilliams@domain.com|Barbara Williams|Creator|publisher

以下是为 Jon Cho 添加内置门户帐户的条目示例,其中用户名为 jcho,电子邮件帐户为 jcho@domain.com。 示例还会将 jcho 添加到管理员角色并将其描述为 GIS 经理:

jcho|changepasswordlater|jcho@domain.com|Jon Cho|GISProfessional|admin|GIS Manager

#!/usr/bin/env python
# Requires Python 2.7+

# Demonstrates how to add users to the ArcGIS Enterprise portal in bulk

# For Http calls
import urllib2, urllib, json
# For system tools
import sys, os
# For reading passwords without echoing
import getpass
# Other utilities
import Queue

# Defines the entry point into the script
def main(argv):

    print "This script adds users in bulk into a portal. \n"

    #Get parameters
    parameters = getParametersFromUser ()

    portalURL = parameters['portalURL']
    provider = parameters['provider']
    userName = parameters['userName']
    password = parameters['password']
    inUserFile = parameters['inUserFile']


    #Get user data from file
    usersData = getUserDataFromFile(inUserFile,provider)

    #Create users
    createUsers (userName,password, portalURL,provider, usersData)

    raw_input('Press ENTER to close the script.')

    return


# This function loads all the user data in the input text file into a Python Queue.
# This usersQueue can be later passed to the createUsers function
def getUserDataFromFile(inUserFile,provider):

    usersQ = Queue.Queue()
    inFileHandle = open(inUserFile, 'r')
    userCount = 0
    print '...Processing input users file at: ' + inUserFile
    entryCount = 1
    roleID = {'admin':'org_admin', 'publisher':'org_publisher', 'user':'org_user', 'viewer':'iAAAAAAAAAAAAAAA'}
    for line in inFileHandle.readlines():
        userParams = line.strip('\n').split('|')
        userParamDict = {}
        if provider=="enterprise":
            keyParams = ['username', 'email', 'fullname', 'role', 'userLicenseTypeId', 'description', 'idpUsername', 'firstname', 'lastname']
            if len(userParams) == len(keyParams):
                for i, param in enumerate(keyParams):
                    userParamDict[param] = userParams[i]
                if userParamDict['role'] in roleID.keys():
                    userParamDict['role'] = roleID[userParamDict['role']]
                else:
                    print('The value for the user role "{}" in users text file is invalid.'.format(userParamDict['role']))
                    print('Accepted values are viewer, user, publisher, or admin.')
                    raise SystemExit('Invalid user role')
                usersQ.put(userParamDict)
                userCount = userCount + 1
            else:
                print('The format for entry "{}" is invalid.\nThe format for enterprise accounts is:'.format(line.strip('\n')))
                print(' <login>|<email address>|<full name>|<role>|<user type id>|<description>|<idp username>|<first name>|<last name>')
                raise SystemExit('Invalid format')
        elif provider=="arcgis":
            keyParams = ['username', 'password', 'email', 'fullname', 'role', 'userLicenseTypeId', 'description', 'firstname', 'lastname']
            if len(userParams) == len(keyParams):
                for i, param in enumerate(keyParams):
                    userParamDict[param] = userParams[i]
                if userParamDict['role'] in roleID.keys():
                    userParamDict['role'] = roleID[userParamDict['role']]
                else:
                    print('The value for the user role "{}" in users text file is invalid.'.format(userParamDict['role']))
                    print('Accepted values are viewer, user, publisher, or admin.')
                    raise SystemExit('Invalid user role')
                usersQ.put (userParamDict)
                userCount = userCount + 1
            else:
                print('The format for entry "{}" is invalid.\nThe format for built-in accounts is:'.format(line.strip('\n')))
                print(' <account>|<password>|<email address>|<full name>|<role>|<description>|<first name>|<last name>|<level>')
                raise SystemExit('Invalid format')
        else:
            raise SystemExit( 'The value for the user type is invalid. ')
        entryCount = entryCount +1
    inFileHandle.close()
    # Create users and report results
    print '...Total members to be added: ' + str(userCount)

    return usersQ


# This function connects to the portal and adds members to it from a collection
def createUsers(username,password, portalUrl, provider,userParamsQ):

    print '...Connecting to ' + portalUrl
    token = generateToken(username,password, portalUrl)
    print '...Adding users '
    usersLeftInQueue = True
    while usersLeftInQueue:
        try:
            userDict = userParamsQ.get(False)
            userDict['f'] = 'json'
            userDict['token'] = token
            userDict['provider'] = provider
            params = urllib.urlencode(userDict)

            request = urllib2.Request(portalUrl + '/portaladmin/security/users/createUser?',params, { 'Referer' : portalUrl })

            # POST the create request
            response = urllib2.urlopen(request).read()
            responseJSON = json.loads(response)

            # Log results
            if responseJSON.has_key('error'):
                errDict = responseJSON['error']
                if int(errDict['code'])==498:
                    message = 'Token Expired. Getting new token... Username: ' + userDict['username'] + ' will be added later'
                    token = generateToken(username,password, portalUrl)
                    userParamsQ.put(userDict)
                else:
                    message =  'Error Code: %s \n Message: %s' % (errDict['code'], errDict['message'])
                print '\n' + message
            else:
                # Success
                if responseJSON.has_key('status'):
                    resultStatus = responseJSON['status']
                    print 'User: %s account created' % (userDict['username'])
        except Queue.Empty:
              usersLeftInQueue = False

# This function gets a token from the portal
def generateToken(username, password, portalUrl):
    parameters = urllib.urlencode({'username' : username,
                                   'password' : password,
                                   'client' : 'referer',
                                   'referer': portalUrl,
                                   'expiration': 60,
                                   'f' : 'json'})
    try:
        response = urllib.urlopen(portalUrl + '/sharing/rest/generateToken?',
                              parameters).read()
    except Exception as e:
        raise SystemExit( 'Unable to open the url %s/sharing/rest/generateToken' % (portalUrl))
    responseJSON =  json.loads(response.strip(' \t\n\r'))
    # Log results
    if responseJSON.has_key('error'):
        errDict = responseJSON['error']
        if int(errDict['code'])==498:
            message = 'Token Expired. Getting new token... '
            token = generateToken(username,password, portalUrl)
        else:
            message =  'Error Code: %s \n Message: %s' % (errDict['code'],
            errDict['message'])
            raise SystemExit(message)
    token = responseJSON.get('token')
    return token

# This function gets gets parameters from the user in interactive mode
def getParametersFromUser():

    parameters = {}
    # Get Location of users file
    inUserFile = raw_input ("Enter path to users text file: ")
    if not os.path.exists(inUserFile):
        raise SystemExit( 'Input file: %s does not exist' % (inUserFile))
    parameters['inUserFile'] = inUserFile

    # Enteprise logins or built-in accounts?
    userInput = raw_input ("What type of users do you want to add to the portal?  Accepted values are built-in or enterprise: ")
    if userInput.lower()=="built-in":
        parameters['provider'] = 'arcgis'
        print '   Built-in accounts will be added to the portal. \n'
    elif userInput.lower()=="enterprise":
        parameters['provider'] = 'enterprise'
        print '   Enterprise accounts will be added to the portal. \n'
    else:
        raise SystemExit( 'The value entered for the user type %s is invalid.  Accepted values are built-in or enterprise. ' % (userInput))

    # Get Portal URL
    hostname = raw_input("Enter the fully qualified portal hostname (for example myportal.acme.com): ")
    parameters['portalURL'] = 'https://' + hostname + ':7443/arcgis'
    print '   Users will be added to portal at: ' + parameters['portalURL'] + '\n'

    # Get a username and password with portal administrative privileges
    parameters['userName'] = raw_input("Enter a built-in user name with portal administrative privileges: ")

    parameters['password'] = getpass.getpass("Enter password: ")
    print '\n'

    return  parameters

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