diff --git a/endpoints/api/__init__.py b/endpoints/api/__init__.py index 873e21a9a..2ffd359be 100644 --- a/endpoints/api/__init__.py +++ b/endpoints/api/__init__.py @@ -56,6 +56,7 @@ def resource(*urls, **kwargs): if not api_resource: return None + api_resource.registered = True api.add_resource(api_resource, *urls, **kwargs) return api_resource return wrapper @@ -63,6 +64,11 @@ def resource(*urls, **kwargs): def show_if(value): def f(inner): + if hasattr(inner, 'registered') and inner.registered: + msg = ('API endpoint %s is already registered; please switch the ' + + '@show_if to be *below* the @resource decorator') + raise Exception(msg % inner) + if not value: return None @@ -72,6 +78,11 @@ def show_if(value): def hide_if(value): def f(inner): + if hasattr(inner, 'registered') and inner.registered: + msg = ('API endpoint %s is already registered; please switch the ' + + '@hide_if to be *below* the @resource decorator') + raise Exception(msg % inner) + if value: return None @@ -195,6 +206,7 @@ def parse_repository_name(func): class ApiResource(Resource): + registered = False method_decorators = [check_anon_protection] def options(self): diff --git a/endpoints/api/repoemail.py b/endpoints/api/repoemail.py index b3c98bc36..4b0a33b51 100644 --- a/endpoints/api/repoemail.py +++ b/endpoints/api/repoemail.py @@ -29,8 +29,8 @@ def record_view(record): @internal_only -@show_if(features.MAILING) @resource('/v1/repository//authorizedemail/') +@show_if(features.MAILING) @path_param('repository', 'The full path of the repository. e.g. namespace/name') @path_param('email', 'The e-mail address') class RepositoryAuthorizedEmail(RepositoryParamResource): diff --git a/endpoints/api/secscan.py b/endpoints/api/secscan.py index 9ec9dafb2..3929a2e2b 100644 --- a/endpoints/api/secscan.py +++ b/endpoints/api/secscan.py @@ -58,8 +58,8 @@ def _security_status_for_image(namespace, repository, repo_image, include_vulner } -@show_if(features.SECURITY_SCANNER) @resource('/v1/repository//image//security') +@show_if(features.SECURITY_SCANNER) @path_param('repository', 'The full path of the repository. e.g. namespace/name') @path_param('imageid', 'The image ID') class RepositoryImageSecurity(RepositoryParamResource): @@ -80,8 +80,8 @@ class RepositoryImageSecurity(RepositoryParamResource): return _security_status_for_image(namespace, repository, repo_image, parsed_args.vulnerabilities) -@show_if(features.SECURITY_SCANNER) @resource(MANIFEST_DIGEST_ROUTE + '/security') +@show_if(features.SECURITY_SCANNER) @path_param('repository', 'The full path of the repository. e.g. namespace/name') @path_param('manifestref', 'The digest of the manifest') class RepositoryManifestSecurity(RepositoryParamResource): diff --git a/endpoints/api/signing.py b/endpoints/api/signing.py index 161f87760..2758a999d 100644 --- a/endpoints/api/signing.py +++ b/endpoints/api/signing.py @@ -12,8 +12,8 @@ from endpoints.api import (require_repo_read, path_param, logger = logging.getLogger(__name__) -@show_if(features.SIGNING) @resource('/v1/repository//signatures') +@show_if(features.SIGNING) @path_param('repository', 'The full path of the repository. e.g. namespace/name') class RepositorySignatures(RepositoryParamResource): """ Operations for managing the signatures in a repository image. """