I am currently developing a GP Tool / WebTool for ArcGIS Enterprise. Main goal of the tool is to write what3word tags to point features.
Workflow is as follows:
- User selects a layer in the webmap
- Run the tool
- Tool checks if certain attributes are available in the layer (
w3w
,w3w_last_edited_date
andlast_edited_date
- editor tracking must be enabled) - If
w3w_last_edited_date
andlast_edited_date
do not match the w3w field gets updated using the w3w endpoint likehttps://api.what3words.com/v3/convert-to-3wa?coordinates={lat}%2C{lng}&key={key}
Running the tool from ArcGIS Pro is working fine. But when I publish it as a WebTool
on ArcGIS Enterprise I get a long error message - the important part is Exception: Unable to generate token. 'token' must be specified in the request, for server token.
As you can see in my code I am using the GetSigninToken
method from arcpy
. But it looks like this is not what I want. My question is - is it possible to access the token of the user who runs the GP Tool / WebTool so the tool can make all the requests / updates using the user token?
from arcpy import GetSigninToken, GetParameterAsText, AddMessage, AddError
from arcgis.features import FeatureLayer, FeatureCollection
from platform import node
from datetime import datetime
import requests
# Main Function
def ScriptTool(featureLayerUrl):
# W3W Key
W3WKEY = "********"
# Check for token
tokenDict = GetSigninToken()
if tokenDict is not None:
token = tokenDict["token"]
# Load Layer
layerUrl = f'{featureLayerUrl}/0?token={token}'
featureLayer = FeatureLayer(layerUrl)
# Check if mandatory fields exist
mandatoryFieldNames = ["w3w", "w3w_last_edited_date", "last_edited_date"]
existingFieldNames = [f["name"] for f in featureLayer.properties["fields"]]
for mandatoryFieldName in mandatoryFieldNames:
if mandatoryFieldName not in existingFieldNames:
AddError(f'Missing mandatory field: {mandatoryFieldName}!')
return
# Iterate over all items
# If w3w_last_edited_date and last_edited_date are different update w3w
fc = FeatureCollection.from_featureset(featureLayer.query(out_sr=4326))
updates = []
for feature in fc.query():
# Access properties
w3w_last_edited_date = feature.attributes["w3w_last_edited_date"]
last_edited_date = feature.attributes["last_edited_date"]
lat = feature.geometry["y"]
lng = feature.geometry["x"]
# Check if date changed
if w3w_last_edited_date != last_edited_date:
try:
res = requests.get(f'https://api.what3words.com/v3/convert-to-3wa?coordinates={lat}%2C{lng}&key={W3WKEY}')
w3w = res.json()["words"]
feature.attributes["w3w"] = w3w
feature.attributes["w3w_last_edited_date"] = last_edited_date
updates.append(feature)
AddMessage(f'Updated location at Lat: {lat}, Lng: {lng}')
except:
AddError("Error updating w3w")
update_result = featureLayer.edit_features(updates=updates)
AddMessage(update_result)
return
# This is used to execute code if the file was run but not imported
if __name__ == '__main__':
# Parameter 1 is the layer on which the w3w tag should be set
featureLayerUrl = GetParameterAsText(0)
ScriptTool(featureLayerUrl)