def setUp(self): self.api = saw.ArcgisAPI( access_token=AGOL_ACCESS_TOKEN, refresh_token=AGOL_REFRESH_TOKEN, username=AGOL_USERNAME, client_id=AGOL_CLIENT_ID, )
def test_refresh_token_invalid(self): api = saw.ArcgisAPI(access_token="abc123", refresh_token="def456") self.assertFalse(api.requester.is_refresh_token_active()) api.close()
def _create_feature_layer(title, fields, feature_service, agol_account, description=""): arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) feature_layer = arcgis.services.create_feature_layer( layer_type="point", name=title, description=description, feature_service_url=feature_service.url, fields=fields, x_min=X_MIN, y_min=Y_MIN, x_max=X_MAX, y_max=Y_MAX, ) return feature_layer
def is_account_connected(agol_account): "Checks if account is connect by checking if refresh token is active." arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) return arcgis.requester.is_refresh_token_active()
def delete_feature_layers(layer_ids, feature_service_url, agol_account): arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) return arcgis.services.delete_feature_layers(layer_ids, feature_service_url)
def setUpClass(cls): api = saw.ArcgisAPI( access_token=AGOL_ACCESS_TOKEN, refresh_token=AGOL_REFRESH_TOKEN, client_id=AGOL_CLIENT_ID, username=AGOL_USERNAME, ) feature_service = api.services.create_feature_service( f"Testing {random.randint(0, 99)}", "This is a test." ) cls.api = api cls.feature_service = feature_service
def test_refresh_token_valid(self): api = saw.ArcgisAPI( access_token=AGOL_ACCESS_TOKEN, refresh_token=AGOL_REFRESH_TOKEN, username=AGOL_USERNAME, client_id=AGOL_CLIENT_ID, ) self.assertTrue(api.requester.is_refresh_token_active()) api.close()
def update_features(updates, layer_id, agol_account): "docs" # TODO: validate updates? arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) return arcgis.services.update_features(updates, layer_id, agol_account.feature_service_url)
def _get_features(out_fields, where, layer_id, agol_account): arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) return arcgis.services.get_features( out_fields=out_fields, where=where, layer_id=layer_id, feature_service_url=agol_account.feature_service_url, )
def get_or_create_caracal_feature_service(agol_account): arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) feature_service = arcgis.services.get_feature_service( name=CARACAL_SERVICE_NAME, owner_username=agol_account.username) if feature_service is None: feature_service = arcgis.services.create_feature_service( CARACAL_SERVICE_NAME, CARACAL_SERVICE_DESCRIPTION) agol_account.feature_service_url = feature_service.url agol_account.feature_service_id = feature_service.id agol_account.save() return feature_service
def _create_table(title, fields, feature_service, agol_account, description=""): arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID, ) table = arcgis.services.create_table( name=title, description=description, feature_service_url=feature_service.url, fields=fields) return table
def post(self, request): user = request.user try: agol_account = user.agol_account except AgolAccount.DoesNotExist: pass else: connections = agol_account.connections.all() for connection in connections: cloudwatch.delete_cloudwatch_rule( connection.cloudwatch_update_rule_name) now = datetime.utcnow().replace(tzinfo=timezone.utc) title = f'Caracal (Disconnected - {str(now).split(".")[0]})' arcgis = saw.ArcgisAPI( access_token=agol_account.oauth_access_token, refresh_token=agol_account.oauth_refresh_token, username=agol_account.username, client_id=settings.AGOL_CLIENT_ID) try: arcgis.services.update_feature_service( agol_account.feature_service_id, title=title) except saw.exceptions.ArcGISException as e: print( str(e) ) # likely agol account exists in db but no service in agol connections.delete() agol_account.delete() user.agol_account = None user.save() return Response(status=status.HTTP_200_OK)
def get(self, request): serializer = serializers.ReceiveAgolOauthResponseUrlQueryParamsSerializer( data=request.query_params) serializer.is_valid(raise_exception=True) data = serializer.data error = data.get('error') if error is not None: return Response({'error': 'access_denied'}, status=status.HTTP_401_UNAUTHORIZED) # code or state occasionally missing if 'code' not in data.keys() or 'state' not in data.keys(): sentry_sdk.capture_message( f'WARNING: code or state missing: {data.get("code")} - {data.get("state")}' ) return Response( { 'error': 'access_denied', 'message': 'code or state missing' }, status=status.HTTP_401_UNAUTHORIZED) code = data['code'] state = json.loads(data['state']) account_uid = state['account_uid'] #refresh_token user account uid agol_redirect_uri = settings.HOSTNAME + reverse('agol-oauth-response') # exchange code for tokens token_url = f'{AGOL_BASE_URL}/token' data = { 'client_id': settings.AGOL_CLIENT_ID, 'code': code, 'redirect_uri': agol_redirect_uri, 'grant_type': 'authorization_code' } res = requests.post(token_url, data=data) tokens = res.json() # access token occasionaly missing? if 'access_token' not in tokens: sentry_sdk.capture_message( f'WARNING: access_token missing - {json.dumps(tokens)}') return Response( { 'error': 'access_denied', 'message': 'access_token missing' }, status=status.HTTP_401_UNAUTHORIZED) access_token = tokens['access_token'] refresh_token = tokens['refresh_token'] username = tokens['username'] expires_in = tokens['expires_in'] expiry = datetime.utcnow().replace(tzinfo=timezone.utc) + timedelta( seconds=expires_in) try: user = Account.objects.get(uid_cognito=account_uid) except Account.DoesNotExist: return Response({'error': 'account_not_found'}, status=status.HTTP_400_BAD_REQUEST) # instead of always using most recent agol account (as before), if already exists, update the tokens # this will support users signing in again after an expired refresh token without losing data try: agol_account = user.agol_account agol_account.oauth_access_token = access_token agol_account.oauth_refresh_token = refresh_token agol_account.oauth_access_token_expiry = expiry agol_account.save() except AgolAccount.DoesNotExist: agol_account = AgolAccount.objects.create( organization=user.organization, account=user, oauth_access_token=access_token, oauth_access_token_expiry=expiry, oauth_refresh_token=refresh_token, username=username) # create a feature service in AGOL, update name if changed arcgis = saw.ArcgisAPI(access_token=access_token, refresh_token=refresh_token, username=username, client_id=settings.AGOL_CLIENT_ID) try: # get feature service and update agol_account service = agol.get_or_create_caracal_feature_service(agol_account) except saw.exceptions.ArcGISException as e: agol_account.delete() sentry_sdk.capture_exception(e) return redirect( state['callback']) # TODO: go somewhere else if failed? # changed a name like Caracal (Disconnected) back to Caracal if service.title != 'Caracal': arcgis.services.update_feature_service( agol_account.feature_service_id, title='Caracal') return redirect(state['callback'])