initial import for Open Source 🎉

This commit is contained in:
Jimmy Zelinskie 2019-11-12 11:09:47 -05:00
parent 1898c361f3
commit 9c0dd3b722
2048 changed files with 218743 additions and 0 deletions

View file

80
endpoints/test/shared.py Normal file
View file

@ -0,0 +1,80 @@
import datetime
import json
import base64
from contextlib import contextmanager
from data import model
from flask import g
from flask_principal import Identity
CSRF_TOKEN_KEY = '_csrf_token'
@contextmanager
def client_with_identity(auth_username, client):
with client.session_transaction() as sess:
if auth_username and auth_username is not None:
loaded = model.user.get_user(auth_username)
sess['user_id'] = loaded.uuid
sess['login_time'] = datetime.datetime.now()
else:
sess['user_id'] = 'anonymous'
yield client
with client.session_transaction() as sess:
sess['user_id'] = None
sess['login_time'] = None
sess[CSRF_TOKEN_KEY] = None
@contextmanager
def toggle_feature(name, enabled):
""" Context manager which temporarily toggles a feature. """
import features
previous_value = getattr(features, name)
setattr(features, name, enabled)
yield
setattr(features, name, previous_value)
def add_csrf_param(client, params):
""" Returns a params dict with the CSRF parameter added. """
params = params or {}
with client.session_transaction() as sess:
params[CSRF_TOKEN_KEY] = 'sometoken'
sess[CSRF_TOKEN_KEY] = 'sometoken'
return params
def gen_basic_auth(username, password):
""" Generates a basic auth header. """
return 'Basic ' + base64.b64encode("%s:%s" % (username, password))
def conduct_call(client, resource, url_for, method, params, body=None, expected_code=200,
headers=None, raw_body=None):
""" Conducts a call to a Flask endpoint. """
params = add_csrf_param(client, params)
final_url = url_for(resource, **params)
headers = headers or {}
headers.update({"Content-Type": "application/json"})
if body is not None:
body = json.dumps(body)
if raw_body is not None:
body = raw_body
# Required for anonymous calls to not exception.
g.identity = Identity(None, 'none')
rv = client.open(final_url, method=method, data=body, headers=headers)
msg = '%s %s: got %s expected: %s | %s' % (method, final_url, rv.status_code, expected_code,
rv.data)
assert rv.status_code == expected_code, msg
return rv

View file

@ -0,0 +1,27 @@
import pytest
from app import app
from endpoints.v1 import v1_bp
from endpoints.v2 import v2_bp
from endpoints.verbs import verbs
@pytest.mark.parametrize('blueprint', [
v2_bp,
v1_bp,
verbs,
])
def test_verify_blueprint(blueprint):
class Checker(object):
def __init__(self):
self.first_registration = True
self.app = app
def add_url_rule(self, rule, endpoint, view_function, methods=None):
result = ('__anon_protected' in dir(view_function) or
'__anon_allowed' in dir(view_function))
error_message = ('Missing anonymous access protection decorator on function ' +
'%s under blueprint %s' % (endpoint, blueprint.name))
assert result, error_message
for deferred_function in blueprint.deferred_functions:
deferred_function(Checker())

View file

@ -0,0 +1,97 @@
import pytest
from data import model
from buildtrigger.triggerutil import raise_if_skipped_build, SkipRequestException
from endpoints.building import (start_build, PreparedBuild, MaximumBuildsQueuedException,
BuildTriggerDisabledException)
from test.fixtures import *
def test_maximum_builds(app):
# Change the maximum number of builds to 1.
user = model.user.create_user('foobar', 'password', 'foo@example.com')
user.maximum_queued_builds_count = 1
user.save()
repo = model.repository.create_repository('foobar', 'somerepo', user)
# Try to queue a build; should succeed.
prepared_build = PreparedBuild()
prepared_build.build_name = 'foo'
prepared_build.is_manual = True
prepared_build.dockerfile_id = 'foobar'
prepared_build.archive_url = 'someurl'
prepared_build.tags = ['latest']
prepared_build.subdirectory = '/'
prepared_build.context = '/'
prepared_build.metadata = {}
start_build(repo, prepared_build)
# Try to queue a second build; should fail.
with pytest.raises(MaximumBuildsQueuedException):
start_build(repo, prepared_build)
def test_start_build_disabled_trigger(app):
trigger = model.build.list_build_triggers('devtable', 'building')[0]
trigger.enabled = False
trigger.save()
build = PreparedBuild(trigger=trigger)
with pytest.raises(BuildTriggerDisabledException):
start_build(trigger.repository, build)
@pytest.mark.parametrize('ref, expected_tags', [
('ref/heads/somebranch', ['somebranch']),
('ref/heads/master', ['master', 'latest']),
('ref/tags/somebranch', ['somebranch']),
('ref/tags/master', ['master', 'latest']),
('ref/heads/slash/branch', ['slash_branch']),
('ref/tags/slash/tag', ['slash_tag']),
('ref/heads/foobar#2', ['foobar_2']),
])
def test_tags_for_ref(ref, expected_tags):
prepared = PreparedBuild()
prepared.tags_from_ref(ref, default_branch='master')
assert set(prepared._tags) == set(expected_tags)
@pytest.mark.parametrize('metadata, config', [
({}, {}),
pytest.param({'ref': 'ref/heads/master'}, {'branchtag_regex': 'nothing'}, id='branchtag regex'),
pytest.param({
'ref': 'ref/heads/master',
'commit_info': {
'message': '[skip build]',
},
}, {}, id='commit message'),
])
def test_skip(metadata, config):
prepared = PreparedBuild()
prepared.metadata = metadata
config = config
with pytest.raises(SkipRequestException):
raise_if_skipped_build(prepared, config)
def test_does_not_skip():
prepared = PreparedBuild()
prepared.metadata = {
'ref': 'ref/heads/master',
'commit_info': {
'message': 'some cool message',
},
}
config = {
'branchtag_regex': '(master)|(heads/master)',
}
raise_if_skipped_build(prepared, config)

View file

@ -0,0 +1,29 @@
import pytest
from endpoints.common import common_login
from endpoints.csrf import QUAY_CSRF_UPDATED_HEADER_NAME
from test.fixtures import *
from endpoints.common_models_pre_oci import pre_oci_model as model
@pytest.mark.parametrize('username, expect_success', [
# Valid users.
('devtable', True),
('public', True),
# Org.
('buynlarge', False),
# Robot.
('devtable+dtrobot', False),
# Unverified user.
('unverified', False),
])
def test_common_login(username, expect_success, app):
uuid = model.get_namespace_uuid(username)
with app.app_context():
success, headers = common_login(uuid)
assert success == expect_success
if success:
assert QUAY_CSRF_UPDATED_HEADER_NAME in headers

View file

@ -0,0 +1,35 @@
from data import model
from endpoints.api import api
from endpoints.api.repository import Repository
from endpoints.test.shared import conduct_call
from test.fixtures import *
@pytest.mark.parametrize('user_agent, include_header, expected_code', [
('curl/whatever', True, 200),
('curl/whatever', False, 200),
('Mozilla/whatever', True, 200),
('Mozilla/5.0', True, 200),
('Mozilla/5.0 (Windows NT 5.1; Win64; x64)', False, 400),
])
def test_require_xhr_from_browser(user_agent, include_header, expected_code, app, client):
# Create a public repo with a dot in its name.
user = model.user.get_user('devtable')
model.repository.create_repository('devtable', 'somerepo.bat', user, 'public')
# Retrieve the repository and ensure we either allow it through or fail, depending on the
# user agent and header.
params = {
'repository': 'devtable/somerepo.bat'
}
headers = {
'User-Agent': user_agent,
}
if include_header:
headers['X-Requested-With'] = 'XMLHttpRequest'
conduct_call(client, Repository, api.url_for, 'GET', params, headers=headers,
expected_code=expected_code)

View file

@ -0,0 +1,24 @@
import base64
import pytest
from flask import url_for
from data import model
from endpoints.test.shared import conduct_call
from test.fixtures import *
def test_start_build_disabled_trigger(app, client):
trigger = model.build.list_build_triggers('devtable', 'building')[0]
trigger.enabled = False
trigger.save()
params = {
'trigger_uuid': trigger.uuid,
}
headers = {
'Authorization': 'Basic ' + base64.b64encode('devtable:password'),
}
conduct_call(client, 'webhooks.build_trigger_webhook', url_for, 'POST', params, None, 400,
headers=headers)