70 lines
3.0 KiB
Python
70 lines
3.0 KiB
Python
"""Contract fixture for the dedicated Gitea API, never a fallback auth store."""
|
|
from copy import deepcopy
|
|
from persimmons import gitea
|
|
|
|
|
|
class GiteaFixture:
|
|
def __init__(self):
|
|
self.users = {}
|
|
self.repos = {}
|
|
self.calls = []
|
|
self.variables = {}
|
|
self.secrets = {}
|
|
|
|
def __call__(self, path, method='GET', body=None, login=None):
|
|
self.calls.append((path, method, deepcopy(body)))
|
|
if path == '/admin/users' and method == 'POST':
|
|
name = body['username']
|
|
if name in self.users:
|
|
raise gitea.Failure(422)
|
|
user = {'id': len(self.users) + 2, 'login': name, 'is_admin': False, 'active': True}
|
|
self.users[name] = (user, body['password'])
|
|
return deepcopy(user)
|
|
if path == '/user':
|
|
if not login or login[0] not in self.users or login[1] != self.users[login[0]][1]:
|
|
raise gitea.Failure(401)
|
|
return deepcopy(self.users[login[0]][0])
|
|
if path.startswith('/users/'):
|
|
if path[7:] not in self.users:
|
|
raise gitea.Failure(404)
|
|
return deepcopy(self.users[path[7:]][0])
|
|
if path.startswith('/admin/users/') and path.endswith('/repos'):
|
|
name = path.split('/')[3]
|
|
key = (name, body['name'].lower())
|
|
if key in self.repos:
|
|
raise gitea.Failure(409)
|
|
repo = {'id': len(self.repos) + 1, 'name': body['name'], 'owner': self.users[name][0],
|
|
'private': body['private'], 'empty': not body['auto_init']}
|
|
self.repos[key] = deepcopy(repo)
|
|
return deepcopy(repo)
|
|
if '/actions/' in path:
|
|
base, action = path.split('/actions/')
|
|
self(base)
|
|
kind, _, name = action.partition('/')
|
|
kind = kind.split('?')[0]
|
|
store = self.variables if kind == 'variables' else self.secrets
|
|
key = (base, name)
|
|
if method == 'GET':
|
|
if kind == 'secrets':
|
|
raise AssertionError('Secret read forbidden')
|
|
if not name:
|
|
return [{'name': n, 'data': v} for (b, n), v in store.items() if b == base]
|
|
if key not in store:
|
|
raise gitea.Failure(404)
|
|
return {'name': name, 'data': store[key]}
|
|
if method == 'POST' and key in store:
|
|
raise gitea.Failure(409)
|
|
if method == 'DELETE':
|
|
if key not in store:
|
|
raise gitea.Failure(404)
|
|
del store[key]
|
|
else:
|
|
store[key] = body['value' if kind == 'variables' else 'data']
|
|
return None
|
|
if path.startswith('/repos/'):
|
|
_, _, owner, name = path.split('/')
|
|
if (owner, name.lower()) not in self.repos:
|
|
raise gitea.Failure(404)
|
|
return deepcopy(self.repos[owner, name.lower()])
|
|
raise AssertionError('Unexpected Gitea request: ' + path)
|