refactor(endpoints/api/repoemail): added in pre_oci model
### Description of Changes this is so we can abstract away the data interface [TESTING->locally with docker compose] Issue: https://coreosdev.atlassian.net/browse/QUAY-626 ## Reviewer Checklist - [ ] It works! - [ ] Comments provide sufficient explanations for the next contributor - [ ] Tests cover changes and corner cases - [ ] Follows Quay syntax patterns and format
This commit is contained in:
parent
82488c9102
commit
d01b55f27d
5 changed files with 158 additions and 16 deletions
|
@ -7,9 +7,9 @@ from flask import request, abort
|
|||
from endpoints.api import (resource, nickname, require_repo_admin, RepositoryParamResource,
|
||||
log_action, validate_json_request, internal_only,
|
||||
path_param, show_if)
|
||||
from endpoints.api.repoemail_models_pre_oci import pre_oci_model as model
|
||||
from endpoints.exception import NotFound
|
||||
from app import tf
|
||||
from data import model
|
||||
from data.database import db
|
||||
from util.useremails import send_repo_authorization_email
|
||||
|
||||
|
@ -19,15 +19,6 @@ import features
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def record_view(record):
|
||||
return {
|
||||
'email': record.email,
|
||||
'repository': record.repository.name,
|
||||
'namespace': record.repository.namespace_user.username,
|
||||
'confirmed': record.confirmed
|
||||
}
|
||||
|
||||
|
||||
@internal_only
|
||||
@resource('/v1/repository/<apirepopath:repository>/authorizedemail/<email>')
|
||||
@show_if(features.MAILING)
|
||||
|
@ -39,11 +30,11 @@ class RepositoryAuthorizedEmail(RepositoryParamResource):
|
|||
@nickname('checkRepoEmailAuthorized')
|
||||
def get(self, namespace, repository, email):
|
||||
""" Checks to see if the given e-mail address is authorized on this repository. """
|
||||
record = model.repository.get_email_authorized_for_repo(namespace, repository, email)
|
||||
record = model.get_email_authorized_for_repo(namespace, repository, email)
|
||||
if not record:
|
||||
abort(404)
|
||||
|
||||
return record_view(record)
|
||||
return record.to_dict()
|
||||
|
||||
|
||||
@require_repo_admin
|
||||
|
@ -52,12 +43,12 @@ class RepositoryAuthorizedEmail(RepositoryParamResource):
|
|||
""" Starts the authorization process for an e-mail address on a repository. """
|
||||
|
||||
with tf(db):
|
||||
record = model.repository.get_email_authorized_for_repo(namespace, repository, email)
|
||||
record = model.get_email_authorized_for_repo(namespace, repository, email)
|
||||
if record and record.confirmed:
|
||||
return record_view(record)
|
||||
return record.to_dict()
|
||||
|
||||
if not record:
|
||||
record = model.repository.create_email_authorization_for_repo(namespace, repository, email)
|
||||
record = model.create_email_authorization_for_repo(namespace, repository, email)
|
||||
|
||||
send_repo_authorization_email(namespace, repository, email, record.code)
|
||||
return record_view(record)
|
||||
return record.to_dict()
|
||||
|
|
44
endpoints/api/repoemail_models_interface.py
Normal file
44
endpoints/api/repoemail_models_interface.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from abc import ABCMeta, abstractmethod
|
||||
from collections import namedtuple
|
||||
|
||||
from six import add_metaclass
|
||||
|
||||
|
||||
class RepositoryAuthorizedEmail(
|
||||
namedtuple('RepositoryAuthorizedEmail', ['email', 'repository_name', 'namespace_name', 'confirmed', 'code',])):
|
||||
"""
|
||||
Tag represents a name to an image.
|
||||
:type email: string
|
||||
:type repository_name: string
|
||||
:type namespace_name: string
|
||||
:type confirmed: boolean
|
||||
:type code: string
|
||||
"""
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'email': self.email,
|
||||
'repository': self.repository_name,
|
||||
'namespace': self.namespace_name,
|
||||
'confirmed': self.confirmed,
|
||||
'code': self.code
|
||||
}
|
||||
|
||||
|
||||
@add_metaclass(ABCMeta)
|
||||
class RepoEmailDataInterface(object):
|
||||
"""
|
||||
Interface that represents all data store interactions required by a Repo Email.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def get_email_authorized_for_repo(self, namespace_name, repository_name, email):
|
||||
"""
|
||||
Returns a RepositoryAuthorizedEmail if available else None
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def create_email_authorization_for_repo(self, namespace_name, repository_name, email):
|
||||
"""
|
||||
Returns the newly created repository authorized email.
|
||||
"""
|
26
endpoints/api/repoemail_models_pre_oci.py
Normal file
26
endpoints/api/repoemail_models_pre_oci.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from data import model
|
||||
from endpoints.api.repoemail_models_interface import RepoEmailDataInterface, RepositoryAuthorizedEmail
|
||||
|
||||
|
||||
def _return_none_or_data(func, namespace_name, repository_name, email):
|
||||
data = func(namespace_name, repository_name, email)
|
||||
if data is None:
|
||||
return data
|
||||
return RepositoryAuthorizedEmail(email, repository_name, namespace_name, data.confirmed, data.code)
|
||||
|
||||
|
||||
class PreOCIModel(RepoEmailDataInterface):
|
||||
"""
|
||||
PreOCIModel implements the data model for the Repo Email using a database schema
|
||||
before it was changed to support the OCI specification.
|
||||
"""
|
||||
|
||||
def get_email_authorized_for_repo(self, namespace_name, repository_name, email):
|
||||
return _return_none_or_data(model.repository.get_email_authorized_for_repo, namespace_name, repository_name, email)
|
||||
|
||||
def create_email_authorization_for_repo(self, namespace_name, repository_name, email):
|
||||
return _return_none_or_data(model.repository.create_email_authorization_for_repo, namespace_name, repository_name,
|
||||
email)
|
||||
|
||||
|
||||
pre_oci_model = PreOCIModel()
|
81
endpoints/api/test/test_repoemail_models_pre_oci.py
Normal file
81
endpoints/api/test/test_repoemail_models_pre_oci.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
import pytest
|
||||
from mock import Mock
|
||||
|
||||
import util
|
||||
from data import model
|
||||
from endpoints.api.repoemail_models_interface import RepositoryAuthorizedEmail
|
||||
from endpoints.api.repoemail_models_pre_oci import pre_oci_model
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def get_monkeypatch(monkeypatch):
|
||||
return monkeypatch
|
||||
|
||||
|
||||
def return_none(name, repo, email):
|
||||
return None
|
||||
|
||||
|
||||
def get_return_mock(mock):
|
||||
def return_mock(name, repo, email):
|
||||
return mock
|
||||
|
||||
return return_mock
|
||||
|
||||
|
||||
def test_get_email_authorized_for_repo(get_monkeypatch):
|
||||
mock = Mock()
|
||||
|
||||
get_monkeypatch.setattr(model.repository, 'get_email_authorized_for_repo', mock)
|
||||
|
||||
pre_oci_model.get_email_authorized_for_repo('namespace_name', 'repository_name', 'email')
|
||||
|
||||
mock.assert_called_once_with('namespace_name', 'repository_name', 'email')
|
||||
|
||||
|
||||
def test_get_email_authorized_for_repo_return_none(get_monkeypatch):
|
||||
get_monkeypatch.setattr(model.repository, 'get_email_authorized_for_repo', return_none)
|
||||
|
||||
repo = pre_oci_model.get_email_authorized_for_repo('namespace_name', 'repository_name', 'email')
|
||||
|
||||
assert repo is None
|
||||
|
||||
|
||||
def test_get_email_authorized_for_repo_return_repo(get_monkeypatch):
|
||||
mock = Mock(confirmed=True, code='code')
|
||||
get_monkeypatch.setattr(model.repository, 'get_email_authorized_for_repo', get_return_mock(mock))
|
||||
|
||||
actual = pre_oci_model.get_email_authorized_for_repo('namespace_name', 'repository_name', 'email')
|
||||
|
||||
assert actual == RepositoryAuthorizedEmail('email', 'repository_name', 'namespace_name', True, 'code')
|
||||
|
||||
|
||||
def test_create_email_authorization_for_repo(get_monkeypatch):
|
||||
mock = Mock()
|
||||
get_monkeypatch.setattr(model.repository, 'create_email_authorization_for_repo', mock)
|
||||
|
||||
pre_oci_model.create_email_authorization_for_repo('namespace_name', 'repository_name', 'email')
|
||||
|
||||
mock.assert_called_once_with('namespace_name', 'repository_name', 'email')
|
||||
|
||||
|
||||
def test_create_email_authorization_for_repo_return_none(get_monkeypatch):
|
||||
get_monkeypatch.setattr(model.repository, 'create_email_authorization_for_repo', return_none)
|
||||
|
||||
assert pre_oci_model.create_email_authorization_for_repo('namespace_name', 'repository_name', 'email') is None
|
||||
|
||||
|
||||
def test_create_email_authorization_for_repo_return_mock(get_monkeypatch):
|
||||
mock = Mock()
|
||||
get_monkeypatch.setattr(model.repository, 'create_email_authorization_for_repo', get_return_mock(mock))
|
||||
|
||||
assert pre_oci_model.create_email_authorization_for_repo('namespace_name', 'repository_name', 'email') is not None
|
||||
|
||||
|
||||
def test_create_email_authorization_for_repo_return_value(get_monkeypatch):
|
||||
mock = Mock(confirmed=False, code='code')
|
||||
|
||||
get_monkeypatch.setattr(model.repository, 'create_email_authorization_for_repo', get_return_mock(mock))
|
||||
|
||||
actual = pre_oci_model.create_email_authorization_for_repo('namespace_name', 'repository_name', 'email')
|
||||
assert actual == RepositoryAuthorizedEmail('email', 'repository_name', 'namespace_name', False, 'code')
|
Reference in a new issue