Skip to content

Commit babdd22

Browse files
Implement automatic cookie refreshing (#11)
1 parent f87113a commit babdd22

3 files changed

Lines changed: 57 additions & 6 deletions

File tree

css-reports/app.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
11
from flask import Flask, request, send_file, jsonify, redirect
2-
from report import get_product_customisations
2+
from typing import Final, LiteralString
3+
from report import get_product_customisations, check_or_refresh_cookie
34
from datetime import datetime
5+
from apscheduler.schedulers.background import BackgroundScheduler # type: ignore[import-untyped]
6+
7+
import asyncio
48
import os
59
import re
610

11+
712
app = Flask("css-reports")
813

914

15+
TRUE_VALUES: Final[set[LiteralString]] = {"true", "1", "t", "y", "yes", "on"}
16+
17+
18+
persistent_organisations: dict[str, tuple[str, str]] = {}
19+
20+
21+
async def refresh_persistent_cookies() -> None:
22+
for org_id, (origonal_cookie, auth_cookie) in persistent_organisations.items():
23+
persistent_organisations[org_id] = (
24+
origonal_cookie,
25+
await check_or_refresh_cookie(org_id, auth_cookie)
26+
)
27+
28+
1029
@app.route("/")
1130
def hello():
1231
return redirect("https://cssbham.com", code=302)
@@ -28,9 +47,7 @@ async def fetch_customisation_report():
2847
product_names: str | None = request.args.get("product_names")
2948
start_date: str | None = request.args.get("start_date")
3049
end_date: str | None = request.args.get("end_date")
31-
32-
print(f"Organisation ID: {organisation_id}")
33-
print(f"Product Name: {product_name}")
50+
persist: str | None = request.args.get("persist")
3451

3552
if not auth_cookie or not organisation_id:
3653
return jsonify({"error": "An auth token and organisation id are required."}), 400
@@ -59,13 +76,27 @@ async def fetch_customisation_report():
5976
name_or_id: str = product_name or product_names # type: ignore[assignment]
6077
name_or_id = re.sub(r"\W\s", "", name_or_id)
6178

79+
prod_cookie: str
80+
81+
if persist and persist.lower().strip() in TRUE_VALUES:
82+
if organisation_id in persistent_organisations.keys():
83+
if persistent_organisations[organisation_id][0] != auth_cookie:
84+
return jsonify({"error": "Persistent auth cookie does not match existing one for this organisation ID."}), 400
85+
else:
86+
prod_cookie = persistent_organisations[organisation_id][1]
87+
else:
88+
persistent_organisations[organisation_id] = (auth_cookie, auth_cookie)
89+
prod_cookie = auth_cookie
90+
else:
91+
prod_cookie = auth_cookie
92+
6293
csv_file_path: str | None = None
6394

6495
try:
6596
# Generate the CSV file
6697
csv_file_path = await get_product_customisations(
6798
product_id_or_name=name_or_id,
68-
auth_cookie=auth_cookie,
99+
auth_cookie=prod_cookie,
69100
org_id=organisation_id,
70101
from_date_input=start_date_dt,
71102
to_date_input=end_date_dt,
@@ -90,4 +121,8 @@ async def fetch_customisation_report():
90121

91122
if __name__ == "__main__":
92123
# from waitress import serve
124+
125+
scheduler = BackgroundScheduler()
126+
scheduler.add_job(func=lambda: asyncio.run(refresh_persistent_cookies()), trigger="interval", minutes=5)
127+
scheduler.start()
93128
app.run(host="0.0.0.0", port=8000, debug=True)

css-reports/report.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,21 @@
2929
ssl_context: ssl.SSLContext = ssl.create_default_context(cafile=certifi.where())
3030

3131

32+
async def check_or_refresh_cookie(org_id: str, auth_cookie: str) -> str:
33+
"""Queries the org page and the cookie will either be returned if valid or a new cookie returned."""
34+
async with (
35+
aiohttp.ClientSession(headers=BASE_HEADERS, cookies={".AspNet.SharedCookie": auth_cookie}) as session,
36+
session.get(f"https://www.guildofstudents.com/organisation/admin/{org_id}") as response,
37+
):
38+
await response.text()
39+
40+
returned_asp_cookie: Morsel[str] | None = response.cookies.get(
41+
".AspNet.SharedCookie"
42+
)
43+
44+
return returned_asp_cookie.value if returned_asp_cookie else auth_cookie
45+
46+
3247
async def get_msl_context(
3348
url: str, auth_cookie: str
3449
) -> tuple[dict[str, str], dict[str, str]]:

css-reports/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ aiohttp
44
beautifulsoup4
55
python-dotenv
66
waitress
7-
certifi
7+
certifi
8+
APScheduler

0 commit comments

Comments
 (0)