diff --git a/endpoints/api/__init__.py b/endpoints/api/__init__.py index 60b5d7398..61c1f3e6a 100644 --- a/endpoints/api/__init__.py +++ b/endpoints/api/__init__.py @@ -85,11 +85,32 @@ def handle_api_error(error): def resource(*urls, **kwargs): def wrapper(api_resource): + if not api_resource: + return None + api.add_resource(api_resource, *urls, **kwargs) return api_resource return wrapper +def show_if(value): + def f(inner): + if not value: + return None + + return inner + return f + + +def hide_if(value): + def f(inner): + if value: + return None + + return inner + return f + + def truthy_bool(param): return param not in {False, 'false', 'False', '0', 'FALSE', '', 'null'} @@ -116,6 +137,7 @@ def method_metadata(func, name): return None + nickname = partial(add_method_metadata, 'nickname') related_user_resource = partial(add_method_metadata, 'related_user_resource') internal_only = add_method_metadata('internal', True) diff --git a/endpoints/api/user.py b/endpoints/api/user.py index ba245209c..f89d7ed62 100644 --- a/endpoints/api/user.py +++ b/endpoints/api/user.py @@ -9,7 +9,7 @@ from flask.ext.principal import identity_changed, AnonymousIdentity from app import app from endpoints.api import (ApiResource, nickname, resource, validate_json_request, request_error, log_action, internal_only, NotFound, require_user_admin, - InvalidToken, require_scope, format_date) + InvalidToken, require_scope, format_date, hide_if, show_if) from endpoints.api.subscribe import subscribe from endpoints.common import common_login from data import model @@ -22,6 +22,7 @@ from util.gravatar import compute_hash from util.email import (send_confirmation_email, send_recovery_email, send_change_email) +import features logger = logging.getLogger(__name__) diff --git a/endpoints/common.py b/endpoints/common.py index 749cf3ba0..a2e3625e0 100644 --- a/endpoints/common.py +++ b/endpoints/common.py @@ -3,7 +3,7 @@ import urlparse import json import string -from flask import make_response, render_template, request +from flask import make_response, render_template, request, abort from flask.ext.login import login_user, UserMixin from flask.ext.principal import identity_changed from random import SystemRandom @@ -15,7 +15,7 @@ from auth.permissions import QuayDeferredPermissionUser from auth import scopes from endpoints.api.discovery import swagger_route_data from werkzeug.routing import BaseConverter - +from functools import wraps logger = logging.getLogger(__name__) @@ -27,6 +27,29 @@ class RepoPathConverter(BaseConverter): app.url_map.converters['repopath'] = RepoPathConverter +def route_show_if(value): + def decorator(f): + @wraps(f) + def decorated_function(*args, **kwargs): + if not value: + abort(404) + + return f(*args, **kwargs) + return decorated_function + return decorator + + +def route_hide_if(value): + def decorator(f): + @wraps(f) + def decorated_function(*args, **kwargs): + if value: + abort(404) + + return f(*args, **kwargs) + return decorated_function + return decorator + def get_route_data(): global route_data diff --git a/endpoints/web.py b/endpoints/web.py index 02d0ffd50..1e78b12af 100644 --- a/endpoints/web.py +++ b/endpoints/web.py @@ -14,7 +14,7 @@ from auth.permissions import AdministerOrganizationPermission from util.invoice import renderInvoiceToPdf from util.seo import render_snapshot from util.cache import no_cache -from endpoints.common import common_login, render_page_template +from endpoints.common import common_login, render_page_template, route_show_if, route_hide_if from endpoints.csrf import csrf_protect, generate_csrf_token from util.names import parse_repository_name from util.gravatar import compute_hash diff --git a/features/__init__.py b/features/__init__.py index b784a154e..ef9ee253a 100644 --- a/features/__init__.py +++ b/features/__init__.py @@ -2,4 +2,24 @@ def import_features(config_dict): for feature, feature_val in config_dict.items(): if feature.startswith('FEATURE_'): feature_name = feature[8:] - globals()[feature_name] = feature_val + globals()[feature_name] = FeatureNameValue(feature_name, feature_val) + + +class FeatureNameValue(object): + def __init__(self, name, value): + self.value = value + self.name = name + + def __str__(self): + return '%s => %s' % (self.name, self.value) + + def __repr__(self): + return self.value + + def __cmp__(self, other): + return self.value.__cmp__(other) + + def __nonzero__(self): + return self.value.__nonzero__() + +