I have a feature layer that I query from a python script using the ARCGIS REST API. I also call the Geoprocessing service to create buffers, etc. all using a token generated via my [portal_root]/oauth2/token endpoint. The APP ID and Secret that I use were generated in the same portal. All queries work fine, even if the services are not published publicly.
data = {
'client_id':os.environ['CLIENT_ID'],
'client_secret':os.environ['CLIENT_SECRET'],
'grant_type':'client_credentials'
}
response = requests.post('{}/{}'.format(os.environ['PORTAL_ROOT'],'oauth2/token'), data=data, verify=True)
if response.ok== False:
raise Exception("Could not authenticate to arcgis")
else:
content = json.loads(response.content)
token = content["access_token"]
print('][==Authenticated==][')
I can then do things like:
apiEndpoint='Utilities/Geometry/GeometryServer/buffer'
data = {
'geometries':json.dumps(quoteLocationGeometry),
'inSR':4326,
'outSR':102100,
'distances':2000,
'unit':9001,
'token':token,
'f':'json'
}
response = requests.post('{}/{}'.format(os.environ['SERVER_ROOT'],apiEndpoint), data=data, verify=True)
# Sprint(response.text)
if response.ok== False:
raise Exception("Could not get Buffer",response.text)
else:
quoteLocationBuffer = json.loads(response.content)
This all works fine. The last step in my script is to write some data back to a feature service/layer:
apiEndpoint = 'Hosted/SavedQuotes/FeatureServer/0/addFeatures'
feat = solvedRoutes['routes']['features'][0]
data = {
'token':token,
'f':'json',
'features':json.dumps([{
'attributes':{
'details':feat['attributes']['Name'],
'total_cost':feat['attributes']['Total_Cost'],
'total_length':feat['attributes']['Total_Length'],
'SHAPE__Length' : feat['attributes']['Shape_Length'],
'origin_latitude' : lat,
'origin_longitude' : lon,
'rid':args.rid,
'creator_userid' : 'some user ID or email',
'creator_email' : '[email protected]',
'creation_date': int(time.time())*1000
},
'geometry':{
'spatialReference':solvedRoutes['routes']['spatialReference'],
'paths':feat['geometry']['paths']
}
}])
}
print(json.dumps(data))
response = requests.post('{}/{}'.format(os.environ['SERVER_ROOT'],apiEndpoint), data=data, verify=True)
if response.ok== False:
raise Exception("Could not Save Quote",response.text)
print(response.content)
This call fails with a:
'{"error":{"code":500,"message":"User does not have the privilege to perform this operation.","details":[]}}
If I make the Feature layer public, the write works fine, so I know the API call is formatted correctly. I have a valid Auth token, and all READ operations work fine using this token. I opened a ticket with ESRI and it was closed with "sorry, you can't write to a feature layer using OAuth. The layer has to be public. I 100% cannot believe this to be the case. Why can't I write to a feature layer using the REST API + OAuth? The ESRI rep kept sending me docs on the Portal Administration REST api, even after me sending the script and describing in detail what I am trying to do, he just keeps saying it's not possible. He did say I could call the generateToken endpoint with a username and password, but the docs state that interface is superseded by OAuth, and we use OAuth everywhere. It's not adding up.