ctfy.sdk.admin_resources.competition_admins
client.admin.competition_admins — per-competition admin grants (admin).
1"""``client.admin.competition_admins`` — per-competition admin grants (admin).""" 2 3from __future__ import annotations 4 5from datetime import datetime 6 7from ctfy.sdk._helpers import PagedList, _extract_items, _raise_for_status 8from ctfy.sdk.base import BaseHttpClient 9from ctfy.server.models import CompetitionAdminInfo 10 11 12class AdminCompetitionAdminsResource: 13 """Grant / revoke the per-competition admin role.""" 14 15 def __init__(self, http: BaseHttpClient) -> None: 16 self._http = http 17 18 def list( 19 self, competition_id: str, offset: int = 0, limit: int = 50 20 ) -> PagedList[CompetitionAdminInfo]: 21 """Users granted admin on one competition.""" 22 resp = self._http.request( 23 "GET", 24 f"/admin/competitions/{competition_id}/admins", 25 params={"offset": offset, "limit": limit}, 26 ) 27 _raise_for_status(resp) 28 return _extract_items(resp.json(), CompetitionAdminInfo) 29 30 def grant( 31 self, 32 competition_id: str, 33 *, 34 user_id: str = "", 35 email: str = "", 36 expires_at: datetime | None = None, 37 ) -> CompetitionAdminInfo: 38 """Grant per-competition admin. Identify the target by 39 ``user_id`` or ``email`` (the server accepts either). 40 41 ``expires_at`` (timezone-aware, in the future) makes the grant 42 lapse then (#2429 b); ``None`` is a grant that never lapses. 43 Re-granting writes a new value, so it is also how to renew one.""" 44 body: dict[str, str] = {"user_id": user_id, "email": email} 45 if expires_at is not None: 46 body["expires_at"] = expires_at.isoformat() 47 resp = self._http.request( 48 "POST", 49 f"/admin/competitions/{competition_id}/admins", 50 json=body, 51 ) 52 _raise_for_status(resp) 53 return CompetitionAdminInfo.model_validate(resp.json()) 54 55 def revoke(self, competition_id: str, user_id: str) -> None: 56 """Revoke a user's per-competition admin grant.""" 57 resp = self._http.request( 58 "DELETE", f"/admin/competitions/{competition_id}/admins/{user_id}" 59 ) 60 _raise_for_status(resp)
class
AdminCompetitionAdminsResource:
13class AdminCompetitionAdminsResource: 14 """Grant / revoke the per-competition admin role.""" 15 16 def __init__(self, http: BaseHttpClient) -> None: 17 self._http = http 18 19 def list( 20 self, competition_id: str, offset: int = 0, limit: int = 50 21 ) -> PagedList[CompetitionAdminInfo]: 22 """Users granted admin on one competition.""" 23 resp = self._http.request( 24 "GET", 25 f"/admin/competitions/{competition_id}/admins", 26 params={"offset": offset, "limit": limit}, 27 ) 28 _raise_for_status(resp) 29 return _extract_items(resp.json(), CompetitionAdminInfo) 30 31 def grant( 32 self, 33 competition_id: str, 34 *, 35 user_id: str = "", 36 email: str = "", 37 expires_at: datetime | None = None, 38 ) -> CompetitionAdminInfo: 39 """Grant per-competition admin. Identify the target by 40 ``user_id`` or ``email`` (the server accepts either). 41 42 ``expires_at`` (timezone-aware, in the future) makes the grant 43 lapse then (#2429 b); ``None`` is a grant that never lapses. 44 Re-granting writes a new value, so it is also how to renew one.""" 45 body: dict[str, str] = {"user_id": user_id, "email": email} 46 if expires_at is not None: 47 body["expires_at"] = expires_at.isoformat() 48 resp = self._http.request( 49 "POST", 50 f"/admin/competitions/{competition_id}/admins", 51 json=body, 52 ) 53 _raise_for_status(resp) 54 return CompetitionAdminInfo.model_validate(resp.json()) 55 56 def revoke(self, competition_id: str, user_id: str) -> None: 57 """Revoke a user's per-competition admin grant.""" 58 resp = self._http.request( 59 "DELETE", f"/admin/competitions/{competition_id}/admins/{user_id}" 60 ) 61 _raise_for_status(resp)
Grant / revoke the per-competition admin role.
def
list( self, competition_id: str, offset: int = 0, limit: int = 50) -> ctfy.sdk._helpers.PagedList[ctfy.server.models.CompetitionAdminInfo]:
19 def list( 20 self, competition_id: str, offset: int = 0, limit: int = 50 21 ) -> PagedList[CompetitionAdminInfo]: 22 """Users granted admin on one competition.""" 23 resp = self._http.request( 24 "GET", 25 f"/admin/competitions/{competition_id}/admins", 26 params={"offset": offset, "limit": limit}, 27 ) 28 _raise_for_status(resp) 29 return _extract_items(resp.json(), CompetitionAdminInfo)
Users granted admin on one competition.
def
grant( self, competition_id: str, *, user_id: str = '', email: str = '', expires_at: datetime.datetime | None = None) -> ctfy.server.models.CompetitionAdminInfo:
31 def grant( 32 self, 33 competition_id: str, 34 *, 35 user_id: str = "", 36 email: str = "", 37 expires_at: datetime | None = None, 38 ) -> CompetitionAdminInfo: 39 """Grant per-competition admin. Identify the target by 40 ``user_id`` or ``email`` (the server accepts either). 41 42 ``expires_at`` (timezone-aware, in the future) makes the grant 43 lapse then (#2429 b); ``None`` is a grant that never lapses. 44 Re-granting writes a new value, so it is also how to renew one.""" 45 body: dict[str, str] = {"user_id": user_id, "email": email} 46 if expires_at is not None: 47 body["expires_at"] = expires_at.isoformat() 48 resp = self._http.request( 49 "POST", 50 f"/admin/competitions/{competition_id}/admins", 51 json=body, 52 ) 53 _raise_for_status(resp) 54 return CompetitionAdminInfo.model_validate(resp.json())
Grant per-competition admin. Identify the target by
user_id or email (the server accepts either).
expires_at (timezone-aware, in the future) makes the grant
lapse then (#2429 b); None is a grant that never lapses.
Re-granting writes a new value, so it is also how to renew one.
def
revoke(self, competition_id: str, user_id: str) -> None:
56 def revoke(self, competition_id: str, user_id: str) -> None: 57 """Revoke a user's per-competition admin grant.""" 58 resp = self._http.request( 59 "DELETE", f"/admin/competitions/{competition_id}/admins/{user_id}" 60 ) 61 _raise_for_status(resp)
Revoke a user's per-competition admin grant.