Skip to content

Commit f2810ca

Browse files
prepare rebase
1 parent 206ce5d commit f2810ca

5 files changed

Lines changed: 351 additions & 53 deletions

File tree

eodag/api/product/_assets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def _pre_check(self, asset_key: str, asset_values: dict[str, Any]) -> bool:
113113
asset_values["order_link"] = order_link
114114

115115
if "href" not in asset_values and "order_link" not in asset_values:
116-
logger.warning(
116+
logger.debug(
117117
"asset '{}' skipped ignored because neither href nor order_link is available".format(
118118
asset_key
119119
),

eodag/plugins/authentication/eoiam/eoiamsessionauth.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
from typing import TYPE_CHECKING
2121

22+
import requests
2223
from requests.auth import AuthBase
2324

2425
if TYPE_CHECKING:
@@ -37,19 +38,19 @@ def __call__(self, request):
3738
This is called by requests before sending a request.
3839
We use the session's get/post to ensure login happens if needed.
3940
"""
40-
session = self.auth_plugin.session
4141

42-
# Lazy login
43-
if not self.auth_plugin._logged_in:
42+
session = self.auth_plugin.session
43+
try:
4444
resp = session.get(request.url, allow_redirects=True)
4545
if "Earth Observation Identity and Access Management System" in resp.text:
46-
self.auth_plugin._login_from_html(resp.text, req_url=request.url)
47-
self.auth_plugin._logged_in = True
46+
resp = self.auth_plugin._login_from_html(resp.text, request.url)
4847

49-
# Copy cookies from session to the request
50-
request.prepare_cookies(self.auth_plugin.session.cookies)
48+
# Copy cookies from session to the request
49+
request.prepare_cookies(self.auth_plugin.session.cookies)
5150

52-
return request
51+
return request
52+
finally:
53+
self.auth_plugin.session = requests.Session()
5354

5455

5556
__all__ = ["EOIAMSessionAuth"]

eodag/resources/providers.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7408,6 +7408,29 @@
74087408
- $.null
74097409
eodag:quicklook: '$.Assets[?(@.Type="QUICKLOOK")].DownloadLink'
74107410
eodag:thumbnail: '$.Assets[?(@.Type="QUICKLOOK")].DownloadLink'
7411+
assets: '$.Assets'
7412+
assets_mapping:
7413+
download_link:
7414+
href: '$.S3Path.`sub(/^(.*)$/, s3:/\\1)`'
7415+
roles:
7416+
- 'archive'
7417+
- 'data'
7418+
type: 'application/octet-stream'
7419+
order:status: '{$.Online#get_group_name((?P<succeeded>True)|(?P<orderable>False))}'
7420+
quicklook:
7421+
# Mixed protocol makes error, http with S3 downloader
7422+
href: '$.Assets[?(@.Type="QUICKLOOK")].DownloadLink'
7423+
title: "quicklook"
7424+
roles:
7425+
- 'overwiev'
7426+
type: 'image/jpeg'
7427+
thumbnail:
7428+
# Mixed protocol makes error, http with S3 downloader
7429+
href: '$.Assets[?(@.Type="QUICKLOOK")].DownloadLink'
7430+
title: "quicklook"
7431+
roles:
7432+
- 'overwiev'
7433+
type: 'image/jpeg'
74117434
download: !plugin
74127435
type: AwsDownload
74137436
s3_endpoint: 'https://eodata.dataspace.copernicus.eu'

tests/units/auth_plugins/test_eoiamauth.py

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717

1818
from unittest import mock
1919

20+
import requests
2021
import responses
22+
from requests import Request
2123
from requests.auth import AuthBase
2224

2325
from eodag.api.provider import ProvidersDict
26+
from eodag.plugins.authentication.eoiam import EOIAMSessionAuth
2427
from eodag.plugins.manager import PluginManager
2528
from eodag.utils.exceptions import AuthenticationError, MisconfiguredError
2629
from tests.units.auth_plugins.base import BaseAuthPluginTest
@@ -107,9 +110,9 @@ def test_plugins_auth_eoiam_authenticate_no_login_required(self):
107110
auth = auth_plugin.authenticate()
108111
req = mock.Mock(headers={})
109112
req.url = "http://test.url"
110-
auth(req)
111-
112-
self.assertFalse(auth_plugin._logged_in is False)
113+
with mock.patch.object(auth_plugin, "_login_from_html") as mock_login_from_html:
114+
auth(req)
115+
mock_login_from_html.assert_not_called()
113116

114117
@responses.activate
115118
def test_plugins_auth_eoiam_login_from_html_success(self):
@@ -556,3 +559,74 @@ def test_plugins_auth_eoiam_data_access_required(self):
556559
AuthenticationError, f"Data access request required: .* {final_url}"
557560
):
558561
auth_plugin._login_from_html(login_html, req_url="http://test.url")
562+
563+
def test_eoiam_session_auth_call_triggers_login_and_prepares_cookies(self):
564+
"""_EOIAMSessionAuth.__call__ should trigger login when landing on EOIAM page"""
565+
auth_plugin = self.get_auth_plugin("foo_provider")
566+
auth_plugin.config.credentials = {
567+
"username": "test_user",
568+
"password": "test_pass",
569+
}
570+
571+
# prepare a requests PreparedRequest
572+
req = Request("GET", "http://service.test/resource").prepare()
573+
574+
# initial session.get returns EOIAM page
575+
initial_resp = requests.Response()
576+
initial_resp._content = (
577+
b"Earth Observation Identity and Access Management System"
578+
)
579+
initial_resp.url = "http://login"
580+
581+
# login result is a normal response
582+
login_result = requests.Response()
583+
login_result._content = b"{}"
584+
585+
old_session = auth_plugin.session
586+
587+
with mock.patch.object(auth_plugin.session, "get", return_value=initial_resp):
588+
with mock.patch.object(
589+
auth_plugin, "_login_from_html", return_value=login_result
590+
) as mock_login:
591+
# ensure there is a cookie jar so prepare_cookies can operate
592+
jar = requests.cookies.RequestsCookieJar()
593+
jar.set("sid", "1234", domain="service.test", path="/")
594+
auth_plugin.session.cookies = jar
595+
596+
auth = EOIAMSessionAuth(auth_plugin)
597+
returned = auth(req)
598+
599+
mock_login.assert_called_once_with(initial_resp.text, req.url)
600+
self.assertIs(returned, req)
601+
602+
self.assertIsInstance(auth_plugin.session, requests.Session)
603+
self.assertIsNot(auth_plugin.session, old_session)
604+
605+
def test_eoiam_session_auth_call_resets_session_on_login_error(self):
606+
"""_EOIAMSessionAuth.__call__ should reset session even when login fails"""
607+
auth_plugin = self.get_auth_plugin("foo_provider")
608+
auth_plugin.config.credentials = {
609+
"username": "test_user",
610+
"password": "test_pass",
611+
}
612+
613+
req = Request("GET", "http://service.test/resource").prepare()
614+
initial_resp = requests.Response()
615+
initial_resp._content = (
616+
b"Earth Observation Identity and Access Management System"
617+
)
618+
initial_resp.url = "http://login"
619+
620+
old_session = auth_plugin.session
621+
with mock.patch.object(auth_plugin.session, "get", return_value=initial_resp):
622+
with mock.patch.object(
623+
auth_plugin,
624+
"_login_from_html",
625+
side_effect=AuthenticationError("boom"),
626+
):
627+
auth = EOIAMSessionAuth(auth_plugin)
628+
with self.assertRaises(AuthenticationError):
629+
auth(req)
630+
631+
self.assertIsInstance(auth_plugin.session, requests.Session)
632+
self.assertIsNot(auth_plugin.session, old_session)

0 commit comments

Comments
 (0)