Example #1
0
def test_farm():
    if valid_restws_config:
        farm = farmOS.farmOS(FARMOS_HOSTNAME, FARMOS_RESTWS_USERNAME,
                             FARMOS_RESTWS_PASSWORD)
        farm.authenticate()
        return farm

    if valid_oauth_config:
        farm = farmOS.farmOS(FARMOS_HOSTNAME,
                             username=FARMOS_OAUTH_USERNAME,
                             password=FARMOS_OAUTH_PASSWORD,
                             client_id=FARMOS_OAUTH_CLIENT_ID,
                             client_secret=FARMOS_OAUTH_CLIENT_SECRET)
        farm.authenticate()
        return farm
Example #2
0
def test_farm():
    if valid_oauth_config:
        farm = farmOS.farmOS(
            FARMOS_HOSTNAME,
            client_id=FARMOS_OAUTH_CLIENT_ID,
            client_secret=FARMOS_OAUTH_CLIENT_SECRET,
        )
        farm.authorize(username=FARMOS_OAUTH_USERNAME,
                       password=FARMOS_OAUTH_PASSWORD)
        return farm
Example #3
0
def authorize_farm(
        *,
        db: Session = Depends(get_db),
        farm_url: str = Body(...),
        auth_params: FarmAuthorizationParams,
):
    """
    Authorize a new farm. Complete the OAuth Authorization Flow.

    This endpoint is only used when authorizing a new farm, before creation.
    See /authorize-farm/{farm_id} for authorizing existing farms.
    """
    logging.debug("Authorizing new farm: " + farm_url)

    token = get_oauth_token(farm_url, auth_params)

    # Check the token expiration time.
    if token is not None and 'expires_at' in token:
        # Create datetime objects for comparison.
        now = datetime.now()
        expiration_time = datetime.fromtimestamp(float(token['expires_at']))

        # Calculate seconds until expiration.
        timedelta = expiration_time - now
        expires_in = timedelta.total_seconds()

        # Update the token expires_in value
        token['expires_in'] = expires_in

    client_id = settings.AGGREGATOR_OAUTH_CLIENT_ID
    client_secret = settings.AGGREGATOR_OAUTH_CLIENT_SECRET

    # Allow OAuth over http
    if settings.AGGREGATOR_OAUTH_INSECURE_TRANSPORT:
        os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

    try:
        logging.debug("Testing OAuth token with farmOS client.")
        logging.debug(token.dict())
        client = farmOS(
            hostname=farm_url,
            client_id=client_id,
            client_secret=client_secret,
            scope=auth_params.scope,
            token=token.dict(),
        )
        info = client.info()

        return {'token': token, 'info': info}
    except Exception as e:
        logging.debug("Error testing OAuth token with farmOS client: ")
        logging.debug(e)
        raise HTTPException(
            status_code=400,
            detail="Could not authenticate with farmOS server.")
Example #4
0
def get_farm_client(db_session, farm):
    client_id = settings.AGGREGATOR_OAUTH_CLIENT_ID
    client_secret = settings.AGGREGATOR_OAUTH_CLIENT_SECRET

    if farm.token is None:
        error = "No OAuth token. Farm must be Authorized before making requests."
        crud.farm.update_is_authorized(db_session,
                                       farm_id=farm.id,
                                       is_authorized=False,
                                       auth_error=error)
        raise ClientError(error)
    token = FarmTokenBase.from_orm(farm.token)

    if farm.scope is None:
        error = "No Scope. Farm must be Authorized before making requests."
        crud.farm.update_is_authorized(db_session,
                                       farm_id=farm.id,
                                       is_authorized=False,
                                       auth_error=error)
        raise ClientError(error)
    # Use the saved scope.
    scope = farm.scope

    token_updater = partial(_save_token, db_session=db_session, farm=farm)

    # Allow OAuth over http
    if settings.AGGREGATOR_OAUTH_INSECURE_TRANSPORT:
        os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

    try:
        client = farmOS(hostname=build_farm_url(farm.url),
                        client_id=client_id,
                        client_secret=client_secret,
                        scope=scope,
                        token=token.dict(),
                        token_updater=token_updater)
        crud.farm.update_last_accessed(db_session, farm_id=farm.id)
        crud.farm.update_is_authorized(db_session,
                                       farm_id=farm.id,
                                       is_authorized=True)
    except Exception as e:
        if settings.AGGREGATOR_ALERT_ALL_ERRORS:
            admin_alert_email(
                db_session=db_session,
                message="Cannot authenticate client with farmOS server id: " +
                str(farm.id) + " - " + repr(e) + str(e))
        logging.error("Cannot authenticate client with farmOS server id: " +
                      str(farm.id) + " - " + repr(e) + str(e))
        crud.farm.update_is_authorized(db_session,
                                       farm_id=farm.id,
                                       is_authorized=False,
                                       auth_error=str(e))
        raise ClientError(e)

    return client
Example #5
0
def test_not_authenticated_exception_raised():
    with pytest.raises(NotAuthenticatedError):
        farm = farmOS.farmOS('test.farmos.net', 'username', 'password')
        farm.info()
Example #6
0
def test_invalid_login():
    farm = farmOS.farmOS('test.farmos.net', 'username', 'password')
    success = farm.authenticate()

    assert success is False
Example #7
0
def test_valid_login():
    farm = farmOS.farmOS(**valid_credentials)
    success = farm.authenticate()

    assert success is True
Example #8
0
def test_unauthorized_request(test_farm):
    with pytest.raises(HTTPError, match=r"403 *."):
        farm = farmOS(FARMOS_HOSTNAME)
        farm.log.get()
Example #9
0
def test_invalid_scopet():
    with pytest.raises(InvalidScopeError):
        farm = farmOS(FARMOS_HOSTNAME, scope="bad_scope")
        farm.authorize(FARMOS_OAUTH_USERNAME, FARMOS_OAUTH_PASSWORD, scope="bad_scope")
Example #10
0
def test_invalid_client_secret():
    with pytest.raises(InvalidClientError):
        farm = farmOS(FARMOS_HOSTNAME, client_id="farm", client_secret="bad_pass")
        farm.authorize(FARMOS_OAUTH_USERNAME, FARMOS_OAUTH_PASSWORD)
Example #11
0
def test_invalid_login():
    with pytest.raises(InvalidGrantError):
        farm = farmOS(FARMOS_HOSTNAME)
        farm.authorize("username", "password")
Example #12
0
def get_farm_client(db, farm):
    client_id = settings.AGGREGATOR_OAUTH_CLIENT_ID
    client_secret = settings.AGGREGATOR_OAUTH_CLIENT_SECRET

    # Check if another thread has started making requests to this same farm.
    existing_client = client_state.get(farm.id, None)
    if existing_client is not None:
        # Wait for the thread to signal that it is done.
        existing_client.wait()
        # Reload farm to get the latest token.
        db.refresh(farm)

    if farm.token is None:
        error = "No OAuth token. Farm must be Authorized before making requests."
        crud.farm.update_is_authorized(db,
                                       farm_id=farm.id,
                                       is_authorized=False,
                                       auth_error=error)
        raise ClientError(error)
    token = FarmTokenBase.from_orm(farm.token)

    if farm.scope is None:
        error = "No Scope. Farm must be Authorized before making requests."
        crud.farm.update_is_authorized(db,
                                       farm_id=farm.id,
                                       is_authorized=False,
                                       auth_error=error)
        raise ClientError(error)
    # Use the saved scope.
    scope = farm.scope

    token_updater = partial(_save_token, db=db, farm=farm)

    # Allow OAuth over http
    if settings.AGGREGATOR_OAUTH_INSECURE_TRANSPORT:
        os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

    # Create a new threading event to signal other threads
    # that we are currently making requests to this farm.
    refreshing = threading.Event()
    client_state[farm.id] = refreshing

    try:
        # Remember if we need to refresh.
        trigger_refresh = False

        # Calculate time until expiration.
        now = time.time()
        expires_at = token.expires_at
        expires_in = expires_at - now

        # Trigger refresh if token expires in the next 15 seconds.
        if expires_in - 15 <= 0:
            # Mark the token as expired.
            token.expires_at = time.time()
            # Trigger refresh.
            trigger_refresh = True

        client = farmOS(hostname=build_farm_url(farm.url),
                        client_id=client_id,
                        client_secret=client_secret,
                        scope=scope,
                        token=token.dict(),
                        token_updater=token_updater)

        # Make an authenticated request to trigger automatic refresh.
        # It is important the refresh is triggered while the thread still has the lock.
        if trigger_refresh:
            client.info()

        crud.farm.update_last_accessed(db, farm_id=farm.id)
        crud.farm.update_is_authorized(db, farm_id=farm.id, is_authorized=True)
    except Exception as e:
        if settings.AGGREGATOR_ALERT_ALL_ERRORS:
            admin_alert_email(
                db=db,
                message="Cannot authenticate client with farmOS server id: " +
                str(farm.id) + " - " + repr(e) + str(e))
        logging.error("Cannot authenticate client with farmOS server id: " +
                      str(farm.id) + " - " + repr(e) + str(e))
        crud.farm.update_is_authorized(db,
                                       farm_id=farm.id,
                                       is_authorized=False,
                                       auth_error=str(e))
        raise ClientError(e)
    finally:
        # Notify other threads that we are done making requests.
        # Tokens will have refreshed by now, so other clients can continue.
        refreshing.set()
        # Remove the threading object from memory.
        client_state.pop(farm.id, None)

    return client
Example #13
0
import farmOS

hostname = 'localhost:8888/farm-7.x-1.1/'
username = '******'
password = '******'

farm = farmOS.farmOS(hostname, username, password)
success = farm.authenticate()

# Get farm info
info = farm.info()

# Get all logs
logs = farm.log.get()
# Get harvest logs
harvests = farm.log.get({'type': 'farm_harvest'})
# Get log number 37
log = farm.log.get(37)

# Get all assets
assets = farm.asset.get()
# Get all animal assets
animals = farm.log.get({'type': 'animal'})

# Get all areas
areas = farm.area.get()
# Get field areas
fields = farm.area.get({'area_type': 'field'})

# Get all terms
terms = farm.term.get()
Example #14
0
def test_farm():
    farm = farmOS.farmOS(**valid_credentials)
    farm.authenticate()
    return farm