Add MasAdminClient class
A class to request OAuth2 tokens from MAS, and create users using them. Requires data from the config options we defined.
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# Copyright 2025 New Vector Ltd.
|
||||
#
|
||||
# SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
# Please see LICENSE files in the project root for full details.
|
||||
|
||||
import base64
|
||||
import logging
|
||||
from typing import Any, Dict
|
||||
|
||||
from synapse.module_api import ModuleApi
|
||||
|
||||
from synapse_guest_module.config import MasConfig
|
||||
|
||||
logger = logging.getLogger("synapse.contrib." + __name__)
|
||||
|
||||
|
||||
class MasAdminClient:
|
||||
def __init__(self, api: ModuleApi, config: MasConfig):
|
||||
self._api = api
|
||||
self._config = config
|
||||
# Strip trailing any slashes if present
|
||||
self._admin_api_base_url = config.admin_api_base_url.rstrip("/")
|
||||
self._oauth_base_url = config.oauth_base_url.rstrip("/")
|
||||
|
||||
async def create_user(self, username: str) -> None:
|
||||
token = await self.request_admin_token()
|
||||
url = self._build_admin_url("/api/admin/v1/users")
|
||||
|
||||
await self._api.http_client.post_json_get_json(
|
||||
uri=url,
|
||||
post_json={"username": username},
|
||||
headers={"Authorization": [f"Bearer {token}"]},
|
||||
)
|
||||
|
||||
async def request_admin_token(self) -> str:
|
||||
url = self._build_oauth_url("/oauth2/token")
|
||||
basic_auth = base64.b64encode(
|
||||
f"{self._config.client_id}:{self._config.client_secret}".encode("utf-8")
|
||||
).decode("ascii")
|
||||
headers = {
|
||||
"Authorization": [f"Basic {basic_auth}"],
|
||||
"Content-Type": ["application/x-www-form-urlencoded"],
|
||||
}
|
||||
data = {
|
||||
"grant_type": "client_credentials",
|
||||
"scope": "urn:mas:admin",
|
||||
}
|
||||
|
||||
response = await self._post_urlencoded_get_json(url, data, headers)
|
||||
access_token = response.get("access_token")
|
||||
if not isinstance(access_token, str) or len(access_token) == 0:
|
||||
raise ValueError("MAS token response missing access_token")
|
||||
return access_token
|
||||
|
||||
async def _post_urlencoded_get_json(
|
||||
self, url: str, data: Dict[str, str], headers: Dict[str, Any]
|
||||
) -> Any:
|
||||
http_client = self._api.http_client
|
||||
post_urlencoded = getattr(http_client, "post_urlencoded_get_json", None)
|
||||
if callable(post_urlencoded):
|
||||
return await post_urlencoded(url, data, headers=headers)
|
||||
|
||||
logger.debug(
|
||||
"MAS client falling back to post_json_get_json for %s", url
|
||||
)
|
||||
return await http_client.post_json_get_json(
|
||||
uri=url, post_json=data, headers=headers
|
||||
)
|
||||
|
||||
def _build_admin_url(self, path: str) -> str:
|
||||
if not path.startswith("/"):
|
||||
path = "/" + path
|
||||
return f"{self._admin_api_base_url}{path}"
|
||||
|
||||
def _build_oauth_url(self, path: str) -> str:
|
||||
if not path.startswith("/"):
|
||||
path = "/" + path
|
||||
return f"{self._oauth_base_url}{path}"
|
||||
Reference in New Issue
Block a user