Пример #1
0
 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,
     )
Пример #2
0
    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()
Пример #3
0
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
Пример #4
0
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()
Пример #5
0
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
Пример #7
0
    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()
Пример #8
0
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)
Пример #9
0
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,
    )
Пример #10
0
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
Пример #11
0
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
Пример #12
0
    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)
Пример #13
0
    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'])