Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove outdated CMR, WMS, WMTS endpoints from app #105

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 10 additions & 24 deletions api/endpoints/members.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,21 +505,7 @@ def get(self, endpoint_uri):
if maap_user is None:
return Response('Unauthorized', status=401)
else:
urs_token = db.session.query(Member_db).filter_by(id=maap_user.id).first().urs_token
s.headers.update({'Authorization': f'Bearer {urs_token},Basic {settings.MAAP_EDL_CREDS}',
'Connection': 'close'})

endpoint = parse.unquote(endpoint_uri)
login_resp = s.get(
endpoint, allow_redirects=False
)

if login_resp.status_code == 307:
edl_response = s.get(url=login_resp.headers['location'])
else:
edl_response = edl_federated_request(url=endpoint)

json_response = json.loads(edl_response.content)
json_response = get_edc_credentials(endpoint_uri=endpoint_uri, user_id=maap_user.id)

response = jsonify(
accessKeyId=json_response['accessKeyId'],
Expand Down Expand Up @@ -601,7 +587,7 @@ def get(self):
return response


def creds_expiration_utc(_key, creds, now_utc: datetime) -> datetime:
def creds_expiration_utc(_key, creds, now_utc_cred: float) -> float:
"""Return the UTC time that is halfway between now and the expiration time
of a credentials object.

Expand All @@ -621,28 +607,28 @@ def creds_expiration_utc(_key, creds, now_utc: datetime) -> datetime:
try:
expiration = creds['expiration']
expiration_dt = datetime.strptime(expiration, "%Y-%m-%d %H:%M:%S%z")
expiration_dt_utc = expiration_dt.astimezone(timezone.utc)
expiration_dt_utc = expiration_dt.astimezone(timezone.utc).timestamp() * 1000
except (KeyError, ValueError):
expiration_dt_utc = now_utc
expiration_dt_utc = now_utc_cred

# Expire creds in half the actual expiration time
return expiration_dt_utc - (expiration_dt_utc - now_utc) / 2
return expiration_dt_utc - (expiration_dt_utc - now_utc_cred) / 2


def now_utc() -> datetime:
def now_utc() -> float:
"""Return the current datetime value in UTC."""
return datetime.now(timezone.utc)
return datetime.now(timezone.utc).timestamp() * 1000


@cached(TLRUCache(ttu=creds_expiration_utc, timer=now_utc, maxsize=None))
def get_edc_credentials(endpoint_uri, user):
@cached(TLRUCache(ttu=creds_expiration_utc, timer=now_utc, maxsize=128))
def get_edc_credentials(endpoint_uri, user_id):
"""Get EDC credentials for a user from an endpoint.

Credentials are cached for the given endpoint and user for half the time the
credentials are valid to avoid unnecessary generation of new credentials and
to minimize load on the endpoint, while also ensuring reasonable "freshness".
"""
urs_token = db.session.query(Member_db).filter_by(id=user.id).first().urs_token
urs_token = db.session.query(Member_db).filter_by(id=user_id).first().urs_token

s = requests.Session()

Expand Down
7 changes: 0 additions & 7 deletions api/maapapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
from api.cas.cas_auth import validate
from api.utils.environments import Environments, get_environment
from api.utils.url_util import proxied_url
from api.endpoints.cmr import ns as cmr_collections_namespace
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cmr endpoints are still in use by the file api/endpoints/cmr.py

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my message below that answers this and the other comment

from api.endpoints.algorithm import ns as algorithm_namespace
from api.endpoints.job import ns as job_namespace
from api.endpoints.wmts import ns as wmts_namespace
from api.endpoints.wms import ns as wms_namespace
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're removing these endpoints, we should also delete the files api/endpoints/wms.py and api/endpoints/wmts.py. Are these not being referenced in any registered algorithms?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They would not be in algorithms, WMS and WMTS are visualization only endpoints not data access. If we want we can document that for visualization now users can utilize our Titiler services https://docs.maap-project.org/en/latest/technical_tutorials/visualizing.html

CC: @smk0033 we need a new ticket to update the docs with information about Titiler and how to get a url to data to the MAAP STAC

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my common comment below

from api.endpoints.members import ns as members_namespace
from api.endpoints.environment import ns as environment_namespace
from api.restplus import api
Expand All @@ -29,7 +26,6 @@

blueprint = Blueprint('baseapi', __name__, url_prefix='/api')
api.init_app(blueprint)
api.add_namespace(cmr_collections_namespace)
app.register_blueprint(blueprint)

app.config['CAS_SERVER'] = settings.CAS_SERVER_NAME
Expand Down Expand Up @@ -95,11 +91,8 @@ def initialize_app(flask_app):

blueprint = Blueprint('api', __name__, url_prefix='/api')
api.init_app(blueprint)
api.add_namespace(cmr_collections_namespace)
api.add_namespace(algorithm_namespace)
api.add_namespace(job_namespace)
api.add_namespace(wmts_namespace)
api.add_namespace(wms_namespace)
api.add_namespace(members_namespace)
api.add_namespace(environment_namespace)
flask_app.register_blueprint(blueprint)
Expand Down
64 changes: 64 additions & 0 deletions test/test.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,48 @@
import unittest
from datetime import datetime, timezone
from cachetools import cached, TLRUCache
from flask import jsonify

from api.maapapp import app
import uuid


def now_utc() -> float:
"""Return the current datetime value in UTC."""
return datetime.now(timezone.utc).timestamp() * 1000


def creds_expiration_utc(_key, creds, now_utc_cred: float) -> float:
"""Return the UTC time that is halfway between now and the expiration time
of a credentials object.

Assume ``creds`` is an object containing the key ``'expiration'`` associated
to a ``str`` value representing the expiration date/time of the credentials
in the format ``'%Y-%m-%d %H:%M:%S%z'``.

If there is no such key, or the associated value cannot be successfully
parsed into a ``datetime`` value using the format above, return ``now_utc``.
Otherwise, return a datetime value halfway between ``now_utc`` and the
parsed expiration value (converted to UTC).

Note that if the parsed value is prior to ``now_utc``, the returned value
will also be prior to ``now_utc``, halfway between both values.
"""

try:
expiration = creds['expiration']
expiration_dt = datetime.strptime(expiration, "%Y-%m-%d %H:%M:%S%z")
expiration_dt_utc = expiration_dt.astimezone(timezone.utc).timestamp() * 1000
except (KeyError, ValueError):
expiration_dt_utc = now_utc_cred

# Expire creds in half the actual expiration time
return expiration_dt_utc - (expiration_dt_utc - now_utc_cred) / 2


class MyAppCase(unittest.TestCase):

@classmethod
def setUp(self):
app.config['TESTING'] = True
self.app = app.test_client()
Expand All @@ -10,3 +51,26 @@ def test_index(self):
response = self.app.get('/')
data = response.get_data(as_text=True)
self.assertEqual(data, '<a href=/api/>MAAP API</a>')

def test_cache(self):
testCache1 = self.get_edc_credentials("foo", 1)
testCache2 = self.get_edc_credentials("foo", 2)

self.assertEqual(testCache1, testCache2)

testCache3 = self.get_edc_credentials("foo", 3)
testCache4 = self.get_edc_credentials("foo", 3)

self.assertNotEqual(testCache3, testCache4)

@cached(TLRUCache(ttu=creds_expiration_utc, timer=now_utc, maxsize=128))
def get_edc_credentials(self, endpoint_uri, user_id):
uuid_val = str(uuid.uuid4())

response = {
'user_id': user_id,
'endpoint_uri': endpoint_uri,
'uuid': uuid_val,
'expiration': '2024-01-31 23:32:05+00:00'
}
return response