Module librusapi.token
Expand source code
from urllib.parse import urljoin
from requests import Session
from json import JSONDecodeError
from requests.models import Response
from requests.sessions import PreparedRequest
from librusapi.exceptions import AuthorizationError
import typing
from typing import Dict
from librusapi.urls import HEADERS
from librusapi.urls import API_URLS, INDEX_URL
from base64 import b64decode, b64encode
from requests import Request
import re
class Token:
"""Combines all necessary functions to create
authenticated requests.
Can be retrieved using `get_token` function.
Or loaded from a base64 encoded string.
Attributes:
librus_token: DZIENNIKSID cookie
csrf_token: CSRF token, can be used for unlimited
amount of requests within a single session
"""
def __init__(self, token: str = None):
"""Load both Librus token and CSRF token from
base64 encoded string.
e.g. base64($librus_token + ':' + $csrf_token)
Args:
token: base64 encoded token.
When is None sets all properties to an
empty string.
Raises:
ValueError: Whenever there are too many or too little
strings separated by a colon
binascii.Error: Whenever parsing base64 encoded string fails
UnicodeDecodeError: Whenever parsing token string from
binary to utf-8 fails
Example:
>>> token = Token('THh4LXh4eHh4eHh4eHh4eHh4eHh4eHh\
4eHh4eHh4eHh4eHh4OkNTUkZUT0tFTjEyMzQ1Njc4OQ==')
>>> print(token.librus_token)
Lxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>>> print(token.csrf_token)
CSRFTOKEN123456789
"""
self._session = Session()
if not token:
self.librus_token = ""
self.csrf_token = ""
return
token = b64decode(token).decode("utf-8")
librus_token, csrf_token = token.split(":")
self.librus_token = librus_token
"""DZIENNIKSID cookie"""
self.csrf_token = csrf_token
"""CSRF token, can be used for unlimited
amount of requests within a single session"""
def __str__(self) -> str:
combine = self.librus_token + ":" + self.csrf_token
return b64encode(combine.encode()).decode("utf-8")
def create_request(
self, method: str, url: str, data=None, files=None
) -> PreparedRequest:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0"
}
cookies = {"DZIENNIKSID": self.librus_token}
if files:
files["requestkey"] = (None, self.csrf_token)
return Request(
method, url, headers=headers, data=data, files=files, cookies=cookies
).prepare()
def post_request(self, url: str, data=None, files=None) -> PreparedRequest:
return self.create_request("POST", url, data, files)
def get_request(self, url: str) -> PreparedRequest:
return self.create_request("GET", url)
def post(self, url: str, data=None, files=None) -> Response:
req = self.post_request(url, data, files)
resp = self._session.send(req)
resp.raise_for_status()
return resp
def get(self, url: str) -> Response:
req = self.get_request(url)
resp = self._session.send(req)
resp.raise_for_status()
return resp
def get_token(login: str, password: str):
"""Get DZIENNIKSID cookie that acts as an authorization token.
Args:
login: Full Librus username.
password: Librus password.
Returns:
string DZIENNIKSID cookie.
Raises:
AuthorizationError: Whenever anything fails.
Example:
>>> get_token('username', 'password')
returns instance of Token()
"""
s = Session()
s.headers = HEADERS
s.get(
url=typing.cast(
str, typing.cast(Dict[str, dict], API_URLS["auth"])["handshake"]
)
)
resp = s.post(
typing.cast(
str, typing.cast(Dict[str, dict], API_URLS["auth"])["authorization"]
),
data={"action": "login", "login": login, "pass": password},
)
try:
json = resp.json()
except JSONDecodeError:
raise AuthorizationError("Invalid username and/or password")
if not (status := json.get("status")) == "ok" and status == "error":
error_messages = [e.get("message") for e in json.get("errors")]
raise AuthorizationError("\n".join(error_messages))
if (goTo := json.get("goTo")) :
s.get(urljoin(typing.cast(str, API_URLS["base_api"]), goTo))
resp = s.get(INDEX_URL)
else:
raise AuthorizationError("'goTo' was not provided in the response JSON")
cookies = s.cookies.get_dict()
try:
librus_token = cookies["DZIENNIKSID"]
except KeyError:
raise AuthorizationError(f"This should not happen. Cookies: {cookies}")
token = Token()
token.librus_token = librus_token
token.csrf_token = ""
matches = re.search(r'(?<=csrfTokenValue = ").*(?=")', resp.text)
if not matches:
raise AuthorizationError("CSRF token not found on Librus index page")
token.csrf_token = matches.group(0)
return token
Functions
def get_token(login: str, password: str)
-
Get DZIENNIKSID cookie that acts as an authorization token.
Args
login
- Full Librus username.
password
- Librus password.
Returns
string DZIENNIKSID cookie.
Raises
AuthorizationError
- Whenever anything fails.
Example:
>>> get_token('username', 'password') returns instance of Token()
Expand source code
def get_token(login: str, password: str): """Get DZIENNIKSID cookie that acts as an authorization token. Args: login: Full Librus username. password: Librus password. Returns: string DZIENNIKSID cookie. Raises: AuthorizationError: Whenever anything fails. Example: >>> get_token('username', 'password') returns instance of Token() """ s = Session() s.headers = HEADERS s.get( url=typing.cast( str, typing.cast(Dict[str, dict], API_URLS["auth"])["handshake"] ) ) resp = s.post( typing.cast( str, typing.cast(Dict[str, dict], API_URLS["auth"])["authorization"] ), data={"action": "login", "login": login, "pass": password}, ) try: json = resp.json() except JSONDecodeError: raise AuthorizationError("Invalid username and/or password") if not (status := json.get("status")) == "ok" and status == "error": error_messages = [e.get("message") for e in json.get("errors")] raise AuthorizationError("\n".join(error_messages)) if (goTo := json.get("goTo")) : s.get(urljoin(typing.cast(str, API_URLS["base_api"]), goTo)) resp = s.get(INDEX_URL) else: raise AuthorizationError("'goTo' was not provided in the response JSON") cookies = s.cookies.get_dict() try: librus_token = cookies["DZIENNIKSID"] except KeyError: raise AuthorizationError(f"This should not happen. Cookies: {cookies}") token = Token() token.librus_token = librus_token token.csrf_token = "" matches = re.search(r'(?<=csrfTokenValue = ").*(?=")', resp.text) if not matches: raise AuthorizationError("CSRF token not found on Librus index page") token.csrf_token = matches.group(0) return token
Classes
class Token (token: str = None)
-
Combines all necessary functions to create authenticated requests.
Can be retrieved using
get_token()
function. Or loaded from a base64 encoded string.Attributes
librus_token
- DZIENNIKSID cookie
csrf_token
- CSRF token, can be used for unlimited amount of requests within a single session
Load both Librus token and CSRF token from base64 encoded string.
e.g. base64($librus_token + ':' + $csrf_token)
Args
token
- base64 encoded token. When is None sets all properties to an empty string.
Raises
ValueError
- Whenever there are too many or too little strings separated by a colon
binascii.Error
- Whenever parsing base64 encoded string fails
UnicodeDecodeError
- Whenever parsing token string from binary to utf-8 fails
Example:
>>> token = Token('THh4LXh4eHh4eHh4eHh4eHh4eHh4eHh 4eHh4eHh4eHh4eHh4OkNTUkZUT0tFTjEyMzQ1Njc4OQ==') >>> print(token.librus_token) Lxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx >>> print(token.csrf_token) CSRFTOKEN123456789
Expand source code
class Token: """Combines all necessary functions to create authenticated requests. Can be retrieved using `get_token` function. Or loaded from a base64 encoded string. Attributes: librus_token: DZIENNIKSID cookie csrf_token: CSRF token, can be used for unlimited amount of requests within a single session """ def __init__(self, token: str = None): """Load both Librus token and CSRF token from base64 encoded string. e.g. base64($librus_token + ':' + $csrf_token) Args: token: base64 encoded token. When is None sets all properties to an empty string. Raises: ValueError: Whenever there are too many or too little strings separated by a colon binascii.Error: Whenever parsing base64 encoded string fails UnicodeDecodeError: Whenever parsing token string from binary to utf-8 fails Example: >>> token = Token('THh4LXh4eHh4eHh4eHh4eHh4eHh4eHh\ 4eHh4eHh4eHh4eHh4OkNTUkZUT0tFTjEyMzQ1Njc4OQ==') >>> print(token.librus_token) Lxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx >>> print(token.csrf_token) CSRFTOKEN123456789 """ self._session = Session() if not token: self.librus_token = "" self.csrf_token = "" return token = b64decode(token).decode("utf-8") librus_token, csrf_token = token.split(":") self.librus_token = librus_token """DZIENNIKSID cookie""" self.csrf_token = csrf_token """CSRF token, can be used for unlimited amount of requests within a single session""" def __str__(self) -> str: combine = self.librus_token + ":" + self.csrf_token return b64encode(combine.encode()).decode("utf-8") def create_request( self, method: str, url: str, data=None, files=None ) -> PreparedRequest: headers = { "User-Agent": "Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0" } cookies = {"DZIENNIKSID": self.librus_token} if files: files["requestkey"] = (None, self.csrf_token) return Request( method, url, headers=headers, data=data, files=files, cookies=cookies ).prepare() def post_request(self, url: str, data=None, files=None) -> PreparedRequest: return self.create_request("POST", url, data, files) def get_request(self, url: str) -> PreparedRequest: return self.create_request("GET", url) def post(self, url: str, data=None, files=None) -> Response: req = self.post_request(url, data, files) resp = self._session.send(req) resp.raise_for_status() return resp def get(self, url: str) -> Response: req = self.get_request(url) resp = self._session.send(req) resp.raise_for_status() return resp
Instance variables
var csrf_token
-
CSRF token, can be used for unlimited amount of requests within a single session
var librus_token
-
DZIENNIKSID cookie
Methods
def create_request(self, method: str, url: str, data=None, files=None) ‑> requests.models.PreparedRequest
-
Expand source code
def create_request( self, method: str, url: str, data=None, files=None ) -> PreparedRequest: headers = { "User-Agent": "Mozilla/5.0 (Windows NT x.y; Win64; x64; rv:10.0) Gecko/20100101 Firefox/10.0" } cookies = {"DZIENNIKSID": self.librus_token} if files: files["requestkey"] = (None, self.csrf_token) return Request( method, url, headers=headers, data=data, files=files, cookies=cookies ).prepare()
def get(self, url: str) ‑> requests.models.Response
-
Expand source code
def get(self, url: str) -> Response: req = self.get_request(url) resp = self._session.send(req) resp.raise_for_status() return resp
def get_request(self, url: str) ‑> requests.models.PreparedRequest
-
Expand source code
def get_request(self, url: str) -> PreparedRequest: return self.create_request("GET", url)
def post(self, url: str, data=None, files=None) ‑> requests.models.Response
-
Expand source code
def post(self, url: str, data=None, files=None) -> Response: req = self.post_request(url, data, files) resp = self._session.send(req) resp.raise_for_status() return resp
def post_request(self, url: str, data=None, files=None) ‑> requests.models.PreparedRequest
-
Expand source code
def post_request(self, url: str, data=None, files=None) -> PreparedRequest: return self.create_request("POST", url, data, files)