Skip to content

Commit

Permalink
Merge pull request #2 from wvanhed/develop
Browse files Browse the repository at this point in the history
v0.5.5
  • Loading branch information
wvanhed authored Mar 5, 2024
2 parents 82a5264 + 93b4ea2 commit b76e91b
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 4 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ Tenslotte, via de commandline kan je de module ook als volgt aanroepen:
## Opmerkingen

- **Authenticatie**. Inloggen bij de bibliotheek.be website gebeurt standaard
via een webformulier. Het is ook mogelijk om de snellere `oauth` manier te
gebruiken; dit is nog experimenteel.
via een webformulier. Het is ook mogelijk om de `oauth` manier te gebruiken;
maar dit is nog experimenteel.

mb = MijnBibliotheek(username, password, login_by="oauth")
accounts = mb.get_accounts()

! Opmerking: De oauth flow is sinds maart 2024 broken, en vereist nog een aanpassing.

- **Foutafhandeling**. Afhankelijk van de toepassing, kan het aangeraden zijn om
foutafhandeling te voorzien. Het bestand `errors.py` bevat de lijst van
Mijnbib-specifieke exceptions. De docstrings van de publieke methods bevatten
Expand Down
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

new: new feature / impr: improvement / fix: bug fix

## v0.5.5 - 2024-03-05

- fix: broken login (form) because of change at site.
Note: alternative oauth login still broken.
- impr: raise TemporarySiteError at oauth login when 5xx (part 3)

## v0.5.4 - 2024-02-21

- impr: improve extensibility of oauth login handler
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "mijnbib"
version = "0.5.4"
version = "0.5.5"
description = "Python API voor de website mijn.bibliotheek.be"
readme = "README.md"
authors = [{ name = "Ward Van Heddeghem", email = "[email protected]" }]
Expand Down
16 changes: 15 additions & 1 deletion src/mijnbib/login_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ def _log_in(self):
_log.debug("Opening login page ... ")
response = self._br.open(self._url, timeout=TIMEOUT)
html_string_start_page = response.read().decode("utf-8") # type:ignore
# Workaround for mechanize.BrowserStateError: not viewing HTML
# because suddenly (March 2024) Content-Type header is "application/octet-stream;charset=UTF-8"
# which is not recognized as html by mechanize
# Alternative is to configure the browser instance with
# self._br.set_header("Accept", "text/html")
self._br._factory.is_html = True
self._br.select_form(nr=0)
self._br["email"] = self._username
self._br["password"] = self._pwd
Expand Down Expand Up @@ -100,6 +106,7 @@ def _log_in(self):
# GET https://gent.bibliotheek.be/mijn-bibliotheek/aanmelden
# example response:
# header Location: https://mijn.bibliotheek.be/openbibid/rest/auth/authorize?hint=login&oauth_callback=https://gent.bibliotheek.be/my-library/login/callback&oauth_token=5abee3c0f5c04beead64d8e625ead0e7&uilang=nl
_log.debug("----")
response = self._s.get(self._url, allow_redirects=False)
_log.debug(f"login (1) status code : {response.status_code}")
_log.debug(f"login (1) headers : {response.headers}")
Expand All @@ -125,9 +132,10 @@ def _log_in(self):
)
if "/mijn-bibliotheek/overzicht" in oauth_location_url:
_log.info("Already authenticated. No need to log in again.")
return
return response # better for extensibility (i.e. sOlid)

# (2) Authorize based on Location url (get session id)
_log.debug("----")
response = self._s.get(oauth_location_url, allow_redirects=False)
_log.debug(f"login (2) status code : {response.status_code}")
_log.debug(f"login (2) headers : {response.headers}")
Expand All @@ -149,6 +157,7 @@ def _log_in(self):
"email": self._username,
"password": self._pwd,
}
_log.debug("----")
response = self._s.post(url, data=data, allow_redirects=False)
_log.debug(f"login (3) status code : {response.status_code}")
_log.debug(f"login (3) headers : {response.headers}")
Expand All @@ -164,13 +173,18 @@ def _log_in(self):
_log.debug(f"login (3) hint : {hint}")
if response.status_code == 200:
raise AuthenticationError("Login not accepted. Correct credentials?")
if response.status_code >= 500: # we've observed 500
raise TemporarySiteError(
f"Expected status code 303 during log in. Got '{response.status_code}'"
)
if response.status_code != 303:
raise IncompatibleSourceError(
f"Expected status code 303 during log in. Got '{response.status_code}'",
response.text,
)

# (4) Call login callback based on Location url
_log.debug("----")
response = self._s.get(login_location_url, allow_redirects=False)
_log.debug(f"login (4) status code : {response.status_code}")
_log.debug(f"login (4) headers : {response.headers}")
Expand Down
7 changes: 7 additions & 0 deletions tests/test_mijnbibliotheek.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ def creds_config(scope="module"):
yield dict(**config.defaults())


class X(str):
pass


class FakeMechanizeBrowser:
def __init__(self, form_response: str) -> None:
self._form_response = form_response.encode("utf8")
# trick for nested prop, from https://stackoverflow.com/a/35190607/50899
self._factory = X("_factory")
self._factory.is_html = None # can be whatever

def __setitem__(self, key, value):
pass
Expand Down

0 comments on commit b76e91b

Please sign in to comment.