63 lines
2.6 KiB
Python
63 lines
2.6 KiB
Python
"""Read-only bug-report connectivity check. Never emits response bodies or tokens."""
|
|
import re
|
|
from urllib.parse import quote, urlsplit
|
|
|
|
import httpx
|
|
|
|
from gitea_service import GiteaConfig, GiteaError
|
|
|
|
|
|
def check(config=None, transport=None):
|
|
config = config or GiteaConfig.from_env()
|
|
config.validate()
|
|
try:
|
|
parsed = urlsplit(config.url)
|
|
if (not parsed.hostname or re.search(r'\s|\\', config.url) or
|
|
parsed.port == 0 or config.owner in {'.', '..'} or config.repo in {'.', '..'}):
|
|
raise GiteaError('configuration')
|
|
except ValueError:
|
|
raise GiteaError('configuration') from None
|
|
try:
|
|
with httpx.Client(base_url=config.url.rstrip('/') + '/api/v1/',
|
|
headers={'Authorization': 'token ' + config.token,
|
|
'Accept': 'application/json'},
|
|
timeout=httpx.Timeout(15.0, connect=5.0),
|
|
follow_redirects=False, trust_env=False, transport=transport) as client:
|
|
identity = client.get('user')
|
|
identity.raise_for_status()
|
|
user = identity.json()
|
|
if not isinstance(user, dict) or not isinstance(user.get('login'), str):
|
|
raise GiteaError('invalid_response')
|
|
if user['login'] != 'metalcircle-bot':
|
|
raise GiteaError('wrong_account')
|
|
# Test the issue resource using the existing write:issue scope.
|
|
# GET repository metadata would require an additional read:repository scope.
|
|
repository = 'repos/' + quote(config.owner, safe='') + '/' + quote(config.repo, safe='')
|
|
response = client.get(repository + '/issues', params={'limit': 1, 'page': 1})
|
|
response.raise_for_status()
|
|
if not isinstance(response.json(), list):
|
|
raise GiteaError('invalid_response')
|
|
except GiteaError:
|
|
raise
|
|
except httpx.HTTPStatusError as error:
|
|
raise GiteaError('http_' + str(error.response.status_code)) from None
|
|
except (httpx.TimeoutException, httpx.NetworkError, httpx.RemoteProtocolError):
|
|
raise GiteaError('network_or_timeout') from None
|
|
except (ValueError, TypeError, KeyError, httpx.HTTPError):
|
|
raise GiteaError('invalid_response') from None
|
|
|
|
|
|
def main():
|
|
try:
|
|
check()
|
|
except GiteaError as error:
|
|
print('FAIL: gitea_' + error.kind)
|
|
return 1
|
|
print('PASS: Gitea reachable; metalcircle-bot verified; repository issues readable. '
|
|
'Read-only check; issue creation and attachments not tested.')
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
raise SystemExit(main())
|