Merge pull request #2787 from charltonaustin/create_data_interface_for_subsystem_api/repoemail_626
refactor(endpoints/api/repoemail): added in pre_oci model
This commit is contained in:
		
						commit
						48ed4f2875
					
				
					 5 changed files with 176 additions and 20 deletions
				
			
		|  | @ -5,29 +5,18 @@ import logging | |||
| 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) | ||||
|                            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 | ||||
| 
 | ||||
| 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) | ||||
|  | @ -35,16 +24,16 @@ def record_view(record): | |||
| @path_param('email', 'The e-mail address') | ||||
| class RepositoryAuthorizedEmail(RepositoryParamResource): | ||||
|   """ Resource for checking and authorizing e-mail addresses to receive repo notifications. """ | ||||
| 
 | ||||
|   @require_repo_admin | ||||
|   @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 | ||||
|   @nickname('sendAuthorizeRepoEmail') | ||||
|  | @ -52,12 +41,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() | ||||
|  |  | |||
							
								
								
									
										50
									
								
								endpoints/api/repoemail_models_interface.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								endpoints/api/repoemail_models_interface.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| 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. | ||||
|     """ | ||||
							
								
								
									
										28
									
								
								endpoints/api/repoemail_models_pre_oci.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								endpoints/api/repoemail_models_pre_oci.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| 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() | ||||
							
								
								
									
										89
									
								
								endpoints/api/test/test_repoemail_models_pre_oci.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								endpoints/api/test/test_repoemail_models_pre_oci.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| 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