-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathauthorisation.py
More file actions
135 lines (102 loc) · 4.52 KB
/
authorisation.py
File metadata and controls
135 lines (102 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
"""Module for authorisation checks."""
import logging
from typing import TYPE_CHECKING
import aiohttp
import bs4
from cogs.check_su_platform_authorisation import SUPlatformAccessCookieStatus
from config import settings
from utils import GLOBAL_SSL_CONTEXT
from .core import BASE_COOKIES, BASE_HEADERS
if TYPE_CHECKING:
from collections.abc import Iterable, Sequence
from logging import Logger
from typing import Final
__all__: "Sequence[str]" = (
"get_su_platform_access_cookie_status",
"get_su_platform_organisations",
)
logger: "Final[Logger]" = logging.getLogger("TeX-Bot")
SU_PLATFORM_PROFILE_URL: "Final[str]" = "https://guildofstudents.com/profile"
SU_PLATFORM_ORGANISATION_URL: "Final[str]" = (
"https://www.guildofstudents.com/organisation/admin"
)
async def _fetch_url_content_with_session(url: str) -> str:
"""Fetch the HTTP content at the given URL, using a shared aiohttp session."""
async with (
aiohttp.ClientSession(headers=BASE_HEADERS, cookies=BASE_COOKIES) as http_session,
http_session.get(url=url, ssl=GLOBAL_SSL_CONTEXT) as http_response,
):
return await http_response.text()
async def get_su_platform_access_cookie_status() -> SUPlatformAccessCookieStatus:
"""Retrieve the current validity status of the SU platform access cookie."""
response_object: bs4.BeautifulSoup = bs4.BeautifulSoup(
await _fetch_url_content_with_session(SU_PLATFORM_PROFILE_URL), "html.parser"
)
page_title: bs4.Tag | bs4.NavigableString | None = response_object.find("title")
if not page_title or "Login" in str(page_title):
logger.debug("Token is invalid or expired.")
return SUPlatformAccessCookieStatus.INVALID
organisation_admin_url: str = (
f"{SU_PLATFORM_ORGANISATION_URL}/{settings['ORGANISATION_ID']}"
)
response_html: str = await _fetch_url_content_with_session(organisation_admin_url)
if "admin tools" in response_html.lower():
return SUPlatformAccessCookieStatus.AUTHORISED
if "You do not have any permissions for this organisation" in response_html.lower():
return SUPlatformAccessCookieStatus.VALID
logger.warning(
"Unexpected response when checking SU platform access cookie authorisation."
)
return SUPlatformAccessCookieStatus.INVALID
async def get_su_platform_organisations() -> "Iterable[str]":
"""Retrieve the MSL organisations the current SU platform cookie has access to."""
response_object: bs4.BeautifulSoup = bs4.BeautifulSoup(
await _fetch_url_content_with_session(SU_PLATFORM_PROFILE_URL), "html.parser"
)
page_title: bs4.Tag | bs4.NavigableString | None = response_object.find("title")
if not page_title:
logger.warning(
"Profile page returned no content when checking "
"SU platform access cookie's authorisation."
)
return ()
if "Login" in str(page_title):
logger.warning(
"Authentication redirected to login page. "
"SU platform access cookie is invalid or expired."
)
return ()
profile_section_html: bs4.Tag | bs4.NavigableString | None = response_object.find(
"div", {"id": "profile_main"}
)
if profile_section_html is None:
logger.warning(
"Couldn't find the profile section of the user "
"when scraping the SU platform's website HTML."
)
logger.debug("Retrieved HTML: %s", response_object.text)
return ()
user_name: bs4.Tag | bs4.NavigableString | int | None = profile_section_html.find("h1")
if not isinstance(user_name, bs4.Tag):
logger.warning("Found user profile on the SU platform but couldn't find their name.")
logger.debug("Retrieved HTML: %s", response_object.text)
return ()
parsed_html: bs4.Tag | bs4.NavigableString | None = response_object.find(
"ul", {"id": "ulOrgs"}
)
if parsed_html is None or isinstance(parsed_html, bs4.NavigableString):
NO_ADMIN_TABLE_MESSAGE: Final[str] = (
f"Failed to retrieve the admin table for user: {user_name.string}. "
"Please check you have used the correct SU platform access token!"
)
logger.warning(NO_ADMIN_TABLE_MESSAGE)
return ()
organisations: Iterable[str] = [
list_item.get_text(strip=True) for list_item in parsed_html.find_all("li")
]
logger.debug(
"SU platform access cookie has admin authorisation to: %s as user %s",
organisations,
user_name.text,
)
return organisations