Move each flask module into a Blueprint and have CSRF protection only on the API blueprint

This commit is contained in:
Joseph Schorr 2013-12-30 17:05:27 -05:00
parent b598c7ec85
commit 310c98df50
8 changed files with 174 additions and 162 deletions

View file

@ -6,12 +6,12 @@ from app import app as application
logging.basicConfig(**application.config['LOGGING_CONFIG'])
import endpoints.index
import endpoints.api
import endpoints.web
import endpoints.tags
import endpoints.registry
import endpoints.webhooks
from endpoints.api import api
from endpoints.index import index
from endpoints.web import web
from endpoints.tags import tags
from endpoints.registry import registry
from endpoints.webhooks import webhooks
logger = logging.getLogger(__name__)
@ -20,6 +20,13 @@ if application.config.get('INCLUDE_TEST_ENDPOINTS', False):
logger.debug('Loading test endpoints.')
import endpoints.test
application.register_blueprint(web)
application.register_blueprint(index, url_prefix='/v1')
application.register_blueprint(tags, url_prefix='/v1')
application.register_blueprint(registry, url_prefix='/v1')
application.register_blueprint(api, url_prefix='/api')
application.register_blueprint(webhooks, url_prefix='/webhooks')
# Remove this for prod config
application.debug = True

View file

@ -4,7 +4,7 @@ import requests
import urlparse
import json
from flask import request, make_response, jsonify, abort, url_for
from flask import request, make_response, jsonify, abort, url_for, Blueprint, session
from flask.ext.login import current_user, logout_user
from flask.ext.principal import identity_changed, AnonymousIdentity
from functools import wraps
@ -30,13 +30,25 @@ from endpoints.common import common_login
from util.cache import cache_control
from datetime import datetime, timedelta
store = app.config['STORAGE']
user_files = app.config['USERFILES']
logger = logging.getLogger(__name__)
route_data = None
api = Blueprint('api', __name__)
@api.before_request
def csrf_protect():
if request.method != "GET" and request.method != "HEAD":
token = session.get('_csrf_token', None)
found_token = request.values.get('_csrf_token', None)
# TODO: add if not token here, once we are sure all sessions have a token.
if token != found_token:
abort(403)
def get_route_data():
global route_data
if route_data:
@ -44,14 +56,14 @@ def get_route_data():
routes = []
for rule in app.url_map.iter_rules():
if rule.rule.startswith('/api/'):
endpoint_method = globals()[rule.endpoint]
if rule.endpoint.startswith('api.'):
endpoint_method = globals()[rule.endpoint[4:]] # Remove api.
is_internal = '__internal_call' in dir(endpoint_method)
is_org_api = '__user_call' in dir(endpoint_method)
methods = list(rule.methods.difference(['HEAD', 'OPTIONS']))
route = {
'name': rule.endpoint,
'name': rule.endpoint[4:],
'methods': methods,
'path': rule.rule,
'parameters': list(rule.arguments)
@ -112,28 +124,19 @@ def org_api_call(user_call_name):
return internal_decorator
@app.errorhandler(model.DataModelException)
def handle_dme(ex):
return make_response(ex.message, 400)
@app.errorhandler(KeyError)
def handle_dme_key_error(ex):
return make_response(ex.message, 400)
@app.route('/api/discovery')
@api.route('/discovery')
def discovery():
return jsonify(get_route_data())
@app.route('/api/')
@api.route('/')
@internal_api_call
def welcome():
return make_response('welcome', 200)
@app.route('/api/plans/')
@api.route('/plans/')
def list_plans():
return jsonify({
'plans': PLANS,
@ -165,7 +168,7 @@ def user_view(user):
}
@app.route('/api/user/', methods=['GET'])
@api.route('/user/', methods=['GET'])
@internal_api_call
def get_logged_in_user():
if current_user.is_anonymous():
@ -178,7 +181,7 @@ def get_logged_in_user():
return jsonify(user_view(user))
@app.route('/api/user/private', methods=['GET'])
@api.route('/user/private', methods=['GET'])
@api_login_required
@internal_api_call
def get_user_private_count():
@ -199,7 +202,7 @@ def get_user_private_count():
})
@app.route('/api/user/convert', methods=['POST'])
@api.route('/user/convert', methods=['POST'])
@api_login_required
@internal_api_call
def convert_user_to_organization():
@ -236,7 +239,7 @@ def convert_user_to_organization():
return conduct_signin(admin_username, admin_password)
@app.route('/api/user/', methods=['PUT'])
@api.route('/user/', methods=['PUT'])
@api_login_required
@internal_api_call
def change_user_details():
@ -264,7 +267,7 @@ def change_user_details():
return jsonify(user_view(user))
@app.route('/api/user/', methods=['POST'])
@api.route('/user/', methods=['POST'])
@internal_api_call
def create_new_user():
user_data = request.get_json()
@ -291,7 +294,7 @@ def create_new_user():
return error_resp
@app.route('/api/signin', methods=['POST'])
@api.route('/signin', methods=['POST'])
@internal_api_call
def signin_user():
signin_data = request.get_json()
@ -325,7 +328,7 @@ def conduct_signin(username, password):
return response
@app.route("/api/signout", methods=['POST'])
@api.route("/signout", methods=['POST'])
@api_login_required
@internal_api_call
def logout():
@ -334,7 +337,7 @@ def logout():
return make_response('Success', 200)
@app.route("/api/recovery", methods=['POST'])
@api.route("/recovery", methods=['POST'])
@internal_api_call
def request_recovery_email():
email = request.get_json()['email']
@ -343,7 +346,7 @@ def request_recovery_email():
return make_response('Created', 201)
@app.route('/api/users/<prefix>', methods=['GET'])
@api.route('/users/<prefix>', methods=['GET'])
@api_login_required
def get_matching_users(prefix):
users = model.get_matching_users(prefix)
@ -353,7 +356,7 @@ def get_matching_users(prefix):
})
@app.route('/api/entities/<prefix>', methods=['GET'])
@api.route('/entities/<prefix>', methods=['GET'])
@api_login_required
def get_matching_entities(prefix):
teams = []
@ -419,7 +422,7 @@ def team_view(orgname, team):
}
@app.route('/api/organization/', methods=['POST'])
@api.route('/organization/', methods=['POST'])
@api_login_required
@internal_api_call
def create_organization():
@ -468,7 +471,7 @@ def org_view(o, teams):
return view
@app.route('/api/organization/<orgname>', methods=['GET'])
@api.route('/organization/<orgname>', methods=['GET'])
@api_login_required
def get_organization(orgname):
permission = OrganizationMemberPermission(orgname)
@ -484,7 +487,7 @@ def get_organization(orgname):
abort(403)
@app.route('/api/organization/<orgname>', methods=['PUT'])
@api.route('/organization/<orgname>', methods=['PUT'])
@api_login_required
@org_api_call('change_user_details')
def change_organization_details(orgname):
@ -506,7 +509,7 @@ def change_organization_details(orgname):
abort(403)
@app.route('/api/organization/<orgname>/members', methods=['GET'])
@api.route('/organization/<orgname>/members', methods=['GET'])
@api_login_required
def get_organization_members(orgname):
permission = AdministerOrganizationPermission(orgname)
@ -534,7 +537,7 @@ def get_organization_members(orgname):
abort(403)
@app.route('/api/organization/<orgname>/members/<membername>', methods=['GET'])
@api.route('/organization/<orgname>/members/<membername>', methods=['GET'])
@api_login_required
def get_organization_member(orgname, membername):
permission = AdministerOrganizationPermission(orgname)
@ -562,7 +565,7 @@ def get_organization_member(orgname, membername):
abort(403)
@app.route('/api/organization/<orgname>/private', methods=['GET'])
@api.route('/organization/<orgname>/private', methods=['GET'])
@api_login_required
@internal_api_call
def get_organization_private_allowed(orgname):
@ -597,7 +600,7 @@ def member_view(member):
}
@app.route('/api/organization/<orgname>/team/<teamname>',
@api.route('/organization/<orgname>/team/<teamname>',
methods=['PUT', 'POST'])
@api_login_required
def update_organization_team(orgname, teamname):
@ -643,7 +646,7 @@ def update_organization_team(orgname, teamname):
abort(403)
@app.route('/api/organization/<orgname>/team/<teamname>',
@api.route('/organization/<orgname>/team/<teamname>',
methods=['DELETE'])
@api_login_required
def delete_organization_team(orgname, teamname):
@ -656,7 +659,7 @@ def delete_organization_team(orgname, teamname):
abort(403)
@app.route('/api/organization/<orgname>/team/<teamname>/members',
@api.route('/organization/<orgname>/team/<teamname>/members',
methods=['GET'])
@api_login_required
def get_organization_team_members(orgname, teamname):
@ -679,7 +682,7 @@ def get_organization_team_members(orgname, teamname):
abort(403)
@app.route('/api/organization/<orgname>/team/<teamname>/members/<membername>',
@api.route('/organization/<orgname>/team/<teamname>/members/<membername>',
methods=['PUT', 'POST'])
@api_login_required
def update_organization_team_member(orgname, teamname, membername):
@ -708,7 +711,7 @@ def update_organization_team_member(orgname, teamname, membername):
abort(403)
@app.route('/api/organization/<orgname>/team/<teamname>/members/<membername>',
@api.route('/organization/<orgname>/team/<teamname>/members/<membername>',
methods=['DELETE'])
@api_login_required
def delete_organization_team_member(orgname, teamname, membername):
@ -724,7 +727,7 @@ def delete_organization_team_member(orgname, teamname, membername):
abort(403)
@app.route('/api/repository', methods=['POST'])
@api.route('/repository', methods=['POST'])
@api_login_required
def create_repo():
owner = current_user.db_user()
@ -758,7 +761,7 @@ def create_repo():
abort(403)
@app.route('/api/find/repository', methods=['GET'])
@api.route('/find/repository', methods=['GET'])
def find_repos():
prefix = request.args.get('query', '')
@ -781,7 +784,7 @@ def find_repos():
return jsonify(response)
@app.route('/api/repository/', methods=['GET'])
@api.route('/repository/', methods=['GET'])
def list_repos():
def repo_view(repo_obj):
return {
@ -822,7 +825,7 @@ def list_repos():
return jsonify(response)
@app.route('/api/repository/<path:repository>', methods=['PUT'])
@api.route('/repository/<path:repository>', methods=['PUT'])
@api_login_required
@parse_repository_name
def update_repo(namespace, repository):
@ -844,7 +847,7 @@ def update_repo(namespace, repository):
abort(403)
@app.route('/api/repository/<path:repository>/changevisibility',
@api.route('/repository/<path:repository>/changevisibility',
methods=['POST'])
@api_login_required
@parse_repository_name
@ -865,7 +868,7 @@ def change_repo_visibility(namespace, repository):
abort(403)
@app.route('/api/repository/<path:repository>', methods=['DELETE'])
@api.route('/repository/<path:repository>', methods=['DELETE'])
@api_login_required
@parse_repository_name
def delete_repository(namespace, repository):
@ -890,7 +893,7 @@ def image_view(image):
}
@app.route('/api/repository/<path:repository>', methods=['GET'])
@api.route('/repository/<path:repository>', methods=['GET'])
@parse_repository_name
def get_repo(namespace, repository):
logger.debug('Get repo: %s/%s' % (namespace, repository))
@ -939,7 +942,7 @@ def get_repo(namespace, repository):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/build/', methods=['GET'])
@api.route('/repository/<path:repository>/build/', methods=['GET'])
@api_login_required
@parse_repository_name
def get_repo_builds(namespace, repository):
@ -972,7 +975,7 @@ def get_repo_builds(namespace, repository):
abort(403) # Permissions denied
@app.route('/api/repository/<path:repository>/build/', methods=['POST'])
@api.route('/repository/<path:repository>/build/', methods=['POST'])
@api_login_required
@parse_repository_name
def request_repo_build(namespace, repository):
@ -1010,7 +1013,7 @@ def webhook_view(webhook):
}
@app.route('/api/repository/<path:repository>/webhook/', methods=['POST'])
@api.route('/repository/<path:repository>/webhook/', methods=['POST'])
@api_login_required
@parse_repository_name
def create_webhook(namespace, repository):
@ -1030,7 +1033,7 @@ def create_webhook(namespace, repository):
abort(403) # Permissions denied
@app.route('/api/repository/<path:repository>/webhook/<public_id>',
@api.route('/repository/<path:repository>/webhook/<public_id>',
methods=['GET'])
@api_login_required
@parse_repository_name
@ -1043,7 +1046,7 @@ def get_webhook(namespace, repository, public_id):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/webhook/', methods=['GET'])
@api.route('/repository/<path:repository>/webhook/', methods=['GET'])
@api_login_required
@parse_repository_name
def list_webhooks(namespace, repository):
@ -1057,7 +1060,7 @@ def list_webhooks(namespace, repository):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/webhook/<public_id>',
@api.route('/repository/<path:repository>/webhook/<public_id>',
methods=['DELETE'])
@api_login_required
@parse_repository_name
@ -1073,7 +1076,7 @@ def delete_webhook(namespace, repository, public_id):
abort(403) # Permission denied
@app.route('/api/filedrop/', methods=['POST'])
@api.route('/filedrop/', methods=['POST'])
@api_login_required
@internal_api_call
def get_filedrop_url():
@ -1101,7 +1104,7 @@ def wrap_role_view_org(role_json, user, org_members):
return role_json
@app.route('/api/repository/<path:repository>/image/', methods=['GET'])
@api.route('/repository/<path:repository>/image/', methods=['GET'])
@parse_repository_name
def list_repository_images(namespace, repository):
permission = ReadRepositoryPermission(namespace, repository)
@ -1126,7 +1129,7 @@ def list_repository_images(namespace, repository):
abort(403)
@app.route('/api/repository/<path:repository>/image/<image_id>',
@api.route('/repository/<path:repository>/image/<image_id>',
methods=['GET'])
@parse_repository_name
def get_image(namespace, repository, image_id):
@ -1140,7 +1143,7 @@ def get_image(namespace, repository, image_id):
abort(403)
@app.route('/api/repository/<path:repository>/image/<image_id>/changes',
@api.route('/repository/<path:repository>/image/<image_id>/changes',
methods=['GET'])
@cache_control(max_age=60*60) # Cache for one hour
@parse_repository_name
@ -1158,7 +1161,7 @@ def get_image_changes(namespace, repository, image_id):
abort(403)
@app.route('/api/repository/<path:repository>/tag/<tag>/images',
@api.route('/repository/<path:repository>/tag/<tag>/images',
methods=['GET'])
@parse_repository_name
def list_tag_images(namespace, repository, tag):
@ -1182,7 +1185,7 @@ def list_tag_images(namespace, repository, tag):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/team/',
@api.route('/repository/<path:repository>/permissions/team/',
methods=['GET'])
@api_login_required
@parse_repository_name
@ -1199,7 +1202,7 @@ def list_repo_team_permissions(namespace, repository):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/user/',
@api.route('/repository/<path:repository>/permissions/user/',
methods=['GET'])
@api_login_required
@parse_repository_name
@ -1240,7 +1243,7 @@ def list_repo_user_permissions(namespace, repository):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/user/<username>',
@api.route('/repository/<path:repository>/permissions/user/<username>',
methods=['GET'])
@api_login_required
@parse_repository_name
@ -1265,7 +1268,7 @@ def get_user_permissions(namespace, repository, username):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/team/<teamname>',
@api.route('/repository/<path:repository>/permissions/team/<teamname>',
methods=['GET'])
@api_login_required
@parse_repository_name
@ -1280,7 +1283,7 @@ def get_team_permissions(namespace, repository, teamname):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/user/<username>',
@api.route('/repository/<path:repository>/permissions/user/<username>',
methods=['PUT', 'POST'])
@api_login_required
@parse_repository_name
@ -1323,7 +1326,7 @@ def change_user_permissions(namespace, repository, username):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/team/<teamname>',
@api.route('/repository/<path:repository>/permissions/team/<teamname>',
methods=['PUT', 'POST'])
@api_login_required
@parse_repository_name
@ -1351,7 +1354,7 @@ def change_team_permissions(namespace, repository, teamname):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/user/<username>',
@api.route('/repository/<path:repository>/permissions/user/<username>',
methods=['DELETE'])
@api_login_required
@parse_repository_name
@ -1376,7 +1379,7 @@ def delete_user_permissions(namespace, repository, username):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/permissions/team/<teamname>',
@api.route('/repository/<path:repository>/permissions/team/<teamname>',
methods=['DELETE'])
@api_login_required
@parse_repository_name
@ -1402,7 +1405,7 @@ def token_view(token_obj):
}
@app.route('/api/repository/<path:repository>/tokens/', methods=['GET'])
@api.route('/repository/<path:repository>/tokens/', methods=['GET'])
@api_login_required
@parse_repository_name
def list_repo_tokens(namespace, repository):
@ -1417,7 +1420,7 @@ def list_repo_tokens(namespace, repository):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/tokens/<code>', methods=['GET'])
@api.route('/repository/<path:repository>/tokens/<code>', methods=['GET'])
@api_login_required
@parse_repository_name
def get_tokens(namespace, repository, code):
@ -1429,7 +1432,7 @@ def get_tokens(namespace, repository, code):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/tokens/', methods=['POST'])
@api.route('/repository/<path:repository>/tokens/', methods=['POST'])
@api_login_required
@parse_repository_name
def create_token(namespace, repository):
@ -1451,7 +1454,7 @@ def create_token(namespace, repository):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/tokens/<code>', methods=['PUT'])
@api.route('/repository/<path:repository>/tokens/<code>', methods=['PUT'])
@api_login_required
@parse_repository_name
def change_token(namespace, repository, code):
@ -1476,7 +1479,7 @@ def change_token(namespace, repository, code):
abort(403) # Permission denied
@app.route('/api/repository/<path:repository>/tokens/<code>',
@api.route('/repository/<path:repository>/tokens/<code>',
methods=['DELETE'])
@api_login_required
@parse_repository_name
@ -1504,7 +1507,7 @@ def subscription_view(stripe_subscription, used_repos):
}
@app.route('/api/user/card', methods=['GET'])
@api.route('/user/card', methods=['GET'])
@api_login_required
@internal_api_call
def get_user_card():
@ -1512,7 +1515,7 @@ def get_user_card():
return get_card(user)
@app.route('/api/organization/<orgname>/card', methods=['GET'])
@api.route('/organization/<orgname>/card', methods=['GET'])
@api_login_required
@internal_api_call
@org_api_call('get_user_card')
@ -1525,7 +1528,7 @@ def get_org_card(orgname):
abort(403)
@app.route('/api/user/card', methods=['POST'])
@api.route('/user/card', methods=['POST'])
@api_login_required
@internal_api_call
def set_user_card():
@ -1536,7 +1539,7 @@ def set_user_card():
return response
@app.route('/api/organization/<orgname>/card', methods=['POST'])
@api.route('/organization/<orgname>/card', methods=['POST'])
@api_login_required
@org_api_call('set_user_card')
def set_org_card(orgname):
@ -1588,7 +1591,7 @@ def get_card(user):
return jsonify({'card': card_info})
@app.route('/api/user/plan', methods=['PUT'])
@api.route('/user/plan', methods=['PUT'])
@api_login_required
@internal_api_call
def update_user_subscription():
@ -1681,7 +1684,7 @@ def subscribe(user, plan, token, require_business_plan):
return resp
@app.route('/api/user/invoices', methods=['GET'])
@api.route('/user/invoices', methods=['GET'])
@api_login_required
def list_user_invoices():
user = current_user.db_user()
@ -1691,7 +1694,7 @@ def list_user_invoices():
return get_invoices(user.stripe_id)
@app.route('/api/organization/<orgname>/invoices', methods=['GET'])
@api.route('/organization/<orgname>/invoices', methods=['GET'])
@api_login_required
@org_api_call('list_user_invoices')
def list_org_invoices(orgname):
@ -1728,7 +1731,7 @@ def get_invoices(customer_id):
})
@app.route('/api/organization/<orgname>/plan', methods=['PUT'])
@api.route('/organization/<orgname>/plan', methods=['PUT'])
@api_login_required
@internal_api_call
@org_api_call('update_user_subscription')
@ -1744,7 +1747,7 @@ def update_org_subscription(orgname):
abort(403)
@app.route('/api/user/plan', methods=['GET'])
@api.route('/user/plan', methods=['GET'])
@api_login_required
@internal_api_call
def get_user_subscription():
@ -1763,7 +1766,7 @@ def get_user_subscription():
})
@app.route('/api/organization/<orgname>/plan', methods=['GET'])
@api.route('/organization/<orgname>/plan', methods=['GET'])
@api_login_required
@internal_api_call
@org_api_call('get_user_subscription')
@ -1793,7 +1796,7 @@ def robot_view(name, token):
}
@app.route('/api/user/robots', methods=['GET'])
@api.route('/user/robots', methods=['GET'])
@api_login_required
def get_user_robots():
user = current_user.db_user()
@ -1803,7 +1806,7 @@ def get_user_robots():
})
@app.route('/api/organization/<orgname>/robots', methods=['GET'])
@api.route('/organization/<orgname>/robots', methods=['GET'])
@api_login_required
@org_api_call('get_user_robots')
def get_org_robots(orgname):
@ -1817,7 +1820,7 @@ def get_org_robots(orgname):
abort(403)
@app.route('/api/user/robots/<robot_shortname>', methods=['PUT'])
@api.route('/user/robots/<robot_shortname>', methods=['PUT'])
@api_login_required
def create_user_robot(robot_shortname):
parent = current_user.db_user()
@ -1828,7 +1831,7 @@ def create_user_robot(robot_shortname):
return resp
@app.route('/api/organization/<orgname>/robots/<robot_shortname>',
@api.route('/organization/<orgname>/robots/<robot_shortname>',
methods=['PUT'])
@api_login_required
@org_api_call('create_user_robot')
@ -1845,7 +1848,7 @@ def create_org_robot(orgname, robot_shortname):
abort(403)
@app.route('/api/user/robots/<robot_shortname>', methods=['DELETE'])
@api.route('/user/robots/<robot_shortname>', methods=['DELETE'])
@api_login_required
def delete_user_robot(robot_shortname):
parent = current_user.db_user()
@ -1854,7 +1857,7 @@ def delete_user_robot(robot_shortname):
return make_response('No Content', 204)
@app.route('/api/organization/<orgname>/robots/<robot_shortname>',
@api.route('/organization/<orgname>/robots/<robot_shortname>',
methods=['DELETE'])
@api_login_required
@org_api_call('delete_user_robot')
@ -1886,7 +1889,7 @@ def log_view(log):
@app.route('/api/repository/<path:repository>/logs', methods=['GET'])
@api.route('/repository/<path:repository>/logs', methods=['GET'])
@api_login_required
@parse_repository_name
def list_repo_logs(namespace, repository):
@ -1903,7 +1906,7 @@ def list_repo_logs(namespace, repository):
abort(403)
@app.route('/api/organization/<orgname>/logs', methods=['GET'])
@api.route('/organization/<orgname>/logs', methods=['GET'])
@api_login_required
@org_api_call('list_user_logs')
def list_org_logs(orgname):
@ -1919,7 +1922,7 @@ def list_org_logs(orgname):
abort(403)
@app.route('/api/user/logs', methods=['GET'])
@api.route('/user/logs', methods=['GET'])
@api_login_required
def list_user_logs():
performer_name = request.args.get('performer', None)

View file

@ -51,15 +51,14 @@ def common_login(db_user):
return False
@app.before_request
def csrf_protect():
if request.method != "GET" and request.method != "HEAD":
token = session.get('_csrf_token', None)
found_token = request.values.get('_csrf_token', None)
@app.errorhandler(model.DataModelException)
def handle_dme(ex):
return make_response(ex.message, 400)
# TODO: add if not token here, once we are sure all sessions have a token.
if token != found_token:
abort(403)
@app.errorhandler(KeyError)
def handle_dme_key_error(ex):
return make_response(ex.message, 400)
def generate_csrf_token():

View file

@ -2,7 +2,7 @@ import json
import logging
import urlparse
from flask import request, make_response, jsonify, abort, session
from flask import request, make_response, jsonify, abort, session, Blueprint
from functools import wraps
from data import model
@ -18,6 +18,7 @@ from auth.permissions import (ModifyRepositoryPermission, UserPermission,
logger = logging.getLogger(__name__)
index = Blueprint('index', __name__)
def generate_headers(role='read'):
def decorator_method(f):
@ -51,8 +52,8 @@ def generate_headers(role='read'):
return decorator_method
@app.route('/v1/users', methods=['POST'])
@app.route('/v1/users/', methods=['POST'])
@index.route('/users', methods=['POST'])
@index.route('/users/', methods=['POST'])
def create_user():
user_data = request.get_json()
username = user_data['username']
@ -87,8 +88,8 @@ def create_user():
return make_response('Created', 201)
@app.route('/v1/users', methods=['GET'])
@app.route('/v1/users/', methods=['GET'])
@index.route('/users', methods=['GET'])
@index.route('/users/', methods=['GET'])
@process_auth
def get_user():
if get_authenticated_user():
@ -99,7 +100,7 @@ def get_user():
abort(404)
@app.route('/v1/users/<username>/', methods=['PUT'])
@index.route('/users/<username>/', methods=['PUT'])
@process_auth
def update_user(username):
permission = UserPermission(username)
@ -124,7 +125,7 @@ def update_user(username):
abort(403)
@app.route('/v1/repositories/<path:repository>', methods=['PUT'])
@index.route('/repositories/<path:repository>', methods=['PUT'])
@process_auth
@parse_repository_name
@generate_headers(role='write')
@ -192,7 +193,7 @@ def create_repository(namespace, repository):
return response
@app.route('/v1/repositories/<path:repository>/images', methods=['PUT'])
@index.route('/repositories/<path:repository>/images', methods=['PUT'])
@process_auth
@parse_repository_name
@generate_headers(role='write')
@ -238,7 +239,7 @@ def update_images(namespace, repository):
abort(403)
@app.route('/v1/repositories/<path:repository>/images', methods=['GET'])
@index.route('/repositories/<path:repository>/images', methods=['GET'])
@process_auth
@parse_repository_name
@generate_headers(role='read')
@ -294,7 +295,7 @@ def get_repository_images(namespace, repository):
abort(403)
@app.route('/v1/repositories/<path:repository>/images', methods=['DELETE'])
@index.route('/repositories/<path:repository>/images', methods=['DELETE'])
@process_auth
@parse_repository_name
@generate_headers(role='write')
@ -302,19 +303,19 @@ def delete_repository_images(namespace, repository):
return make_response('Not Implemented', 501)
@app.route('/v1/repositories/<path:repository>/auth', methods=['PUT'])
@index.route('/repositories/<path:repository>/auth', methods=['PUT'])
@parse_repository_name
def put_repository_auth(namespace, repository):
return make_response('Not Implemented', 501)
@app.route('/v1/search', methods=['GET'])
@index.route('/search', methods=['GET'])
def get_search():
return make_response('Not Implemented', 501)
@app.route('/_ping')
@app.route('/v1/_ping')
@index.route('/_ping')
@index.route('/_ping')
def ping():
response = make_response('true', 200)
response.headers['X-Docker-Registry-Version'] = '0.6.0'

View file

@ -1,7 +1,8 @@
import logging
import json
from flask import make_response, request, session, Response, abort, redirect
from flask import (make_response, request, session, Response, abort,
redirect, Blueprint)
from functools import wraps
from datetime import datetime
from time import time
@ -15,6 +16,7 @@ from auth.permissions import (ReadRepositoryPermission,
ModifyRepositoryPermission)
from data import model
registry = Blueprint('registry', __name__)
store = app.config['STORAGE']
logger = logging.getLogger(__name__)
@ -72,7 +74,7 @@ def set_cache_headers(f):
return wrapper
@app.route('/v1/images/<image_id>/layer', methods=['GET'])
@registry.route('/images/<image_id>/layer', methods=['GET'])
@process_auth
@extract_namespace_repo_from_session
@require_completion
@ -92,7 +94,7 @@ def get_image_layer(namespace, repository, image_id, headers):
abort(403)
@app.route('/v1/images/<image_id>/layer', methods=['PUT'])
@registry.route('/images/<image_id>/layer', methods=['PUT'])
@process_auth
@extract_namespace_repo_from_session
def put_image_layer(namespace, repository, image_id):
@ -158,7 +160,7 @@ def put_image_layer(namespace, repository, image_id):
return make_response('true', 200)
@app.route('/v1/images/<image_id>/checksum', methods=['PUT'])
@registry.route('/images/<image_id>/checksum', methods=['PUT'])
@process_auth
@extract_namespace_repo_from_session
def put_image_checksum(namespace, repository, image_id):
@ -199,7 +201,7 @@ def put_image_checksum(namespace, repository, image_id):
return make_response('true', 200)
@app.route('/v1/images/<image_id>/json', methods=['GET'])
@registry.route('/images/<image_id>/json', methods=['GET'])
@process_auth
@extract_namespace_repo_from_session
@require_completion
@ -229,7 +231,7 @@ def get_image_json(namespace, repository, image_id, headers):
return response
@app.route('/v1/images/<image_id>/ancestry', methods=['GET'])
@registry.route('/images/<image_id>/ancestry', methods=['GET'])
@process_auth
@extract_namespace_repo_from_session
@require_completion
@ -274,7 +276,7 @@ def store_checksum(namespace, repository, image_id, checksum):
store.put_content(checksum_path, checksum)
@app.route('/v1/images/<image_id>/json', methods=['PUT'])
@registry.route('/images/<image_id>/json', methods=['PUT'])
@process_auth
@extract_namespace_repo_from_session
def put_image_json(namespace, repository, image_id):

View file

@ -2,7 +2,7 @@
import logging
import json
from flask import abort, request, jsonify, make_response
from flask import abort, request, jsonify, make_response, Blueprint
from app import app
from util.names import parse_repository_name
@ -14,8 +14,10 @@ from data import model
logger = logging.getLogger(__name__)
tags = Blueprint('tags', __name__)
@app.route('/v1/repositories/<path:repository>/tags',
@tags.route('/repositories/<path:repository>/tags',
methods=['GET'])
@process_auth
@parse_repository_name
@ -30,7 +32,7 @@ def get_tags(namespace, repository):
abort(403)
@app.route('/v1/repositories/<path:repository>/tags/<tag>',
@tags.route('/repositories/<path:repository>/tags/<tag>',
methods=['GET'])
@process_auth
@parse_repository_name
@ -46,7 +48,7 @@ def get_tag(namespace, repository, tag):
abort(403)
@app.route('/v1/repositories/<path:repository>/tags/<tag>',
@tags.route('/repositories/<path:repository>/tags/<tag>',
methods=['PUT'])
@process_auth
@parse_repository_name
@ -62,7 +64,7 @@ def put_tag(namespace, repository, tag):
abort(403)
@app.route('/v1/repositories/<path:repository>/tags/<tag>',
@tags.route('/repositories/<path:repository>/tags/<tag>',
methods=['DELETE'])
@process_auth
@parse_repository_name
@ -77,7 +79,7 @@ def delete_tag(namespace, repository, tag):
abort(403)
@app.route('/v1/repositories/<path:repository>/tags',
@tags.route('/repositories/<path:repository>/tags',
methods=['DELETE'])
@process_auth
@parse_repository_name

View file

@ -3,7 +3,7 @@ import requests
import stripe
from flask import (abort, redirect, request, url_for, render_template,
make_response, Response)
make_response, Response, Blueprint)
from flask.ext.login import current_user
from urlparse import urlparse
@ -18,6 +18,8 @@ from endpoints.common import common_login
logger = logging.getLogger(__name__)
web = Blueprint('web', __name__)
def render_page_template(name):
resp = make_response(render_template(name, route_data=get_route_data()))
@ -25,16 +27,16 @@ def render_page_template(name):
return resp
@app.route('/', methods=['GET'], defaults={'path': ''})
@app.route('/repository/<path:path>', methods=['GET'])
@app.route('/organization/<path:path>', methods=['GET'])
@web.route('/', methods=['GET'], defaults={'path': ''})
@web.route('/repository/<path:path>', methods=['GET'])
@web.route('/organization/<path:path>', methods=['GET'])
def index(path):
return render_page_template('index.html')
@app.route('/snapshot', methods=['GET'])
@app.route('/snapshot/', methods=['GET'])
@app.route('/snapshot/<path:path>', methods=['GET'])
@web.route('/snapshot', methods=['GET'])
@web.route('/snapshot/', methods=['GET'])
@web.route('/snapshot/<path:path>', methods=['GET'])
def snapshot(path = ''):
parsed = urlparse(request.url)
final_url = '%s://%s/%s' % (parsed.scheme, 'localhost', path)
@ -45,74 +47,74 @@ def snapshot(path = ''):
abort(404)
@app.route('/plans/')
@web.route('/plans/')
def plans():
return index('')
@app.route('/guide/')
@web.route('/guide/')
def guide():
return index('')
@app.route('/organizations/')
@app.route('/organizations/new/')
@web.route('/organizations/')
@web.route('/organizations/new/')
def organizations():
return index('')
@app.route('/user/')
@web.route('/user/')
def user():
return index('')
@app.route('/signin/')
@web.route('/signin/')
def signin():
return index('')
@app.route('/new/')
@web.route('/new/')
def new():
return index('')
@app.route('/repository/')
@web.route('/repository/')
def repository():
return index('')
@app.route('/security/')
@web.route('/security/')
def security():
return index('')
@app.route('/v1')
@app.route('/v1/')
@web.route('/v1')
@web.route('/v1/')
def v1():
return index('')
@app.route('/status', methods=['GET'])
@web.route('/status', methods=['GET'])
def status():
return make_response('Healthy')
@app.route('/tos', methods=['GET'])
@web.route('/tos', methods=['GET'])
def tos():
return render_page_template('tos.html')
@app.route('/disclaimer', methods=['GET'])
@web.route('/disclaimer', methods=['GET'])
def disclaimer():
return render_page_template('disclaimer.html')
@app.route('/privacy', methods=['GET'])
@web.route('/privacy', methods=['GET'])
def privacy():
return render_page_template('privacy.html')
@app.route('/receipt', methods=['GET'])
@web.route('/receipt', methods=['GET'])
def receipt():
if not current_user.is_authenticated():
abort(401)
@ -142,7 +144,7 @@ def receipt():
abort(404)
@app.route('/oauth2/github/callback', methods=['GET'])
@web.route('/oauth2/github/callback', methods=['GET'])
def github_oauth_callback():
code = request.args.get('code')
payload = {
@ -205,7 +207,7 @@ def github_oauth_callback():
return render_page_template('githuberror.html')
@app.route('/confirm', methods=['GET'])
@web.route('/confirm', methods=['GET'])
def confirm_email():
code = request.values['code']
@ -219,7 +221,7 @@ def confirm_email():
return redirect(url_for('index'))
@app.route('/recovery', methods=['GET'])
@web.route('/recovery', methods=['GET'])
def confirm_recovery():
code = request.values['code']
user = model.validate_reset_code(code)
@ -229,8 +231,3 @@ def confirm_recovery():
return redirect(url_for('user'))
else:
abort(403)
@app.route('/reset', methods=['GET'])
def password_reset():
pass

View file

@ -1,7 +1,7 @@
import logging
import stripe
from flask import request, make_response
from flask import request, make_response, Blueprint
from data import model
from app import app
@ -11,8 +11,9 @@ from util.email import send_invoice_email
logger = logging.getLogger(__name__)
webhooks = Blueprint('webhooks', __name__)
@app.route('/webhooks/stripe', methods=['POST'])
@webhooks.route('/stripe', methods=['POST'])
def stripe_webhook():
request_data = request.get_json()
logger.debug('Stripe webhook call: %s' % request_data)