Feed error messages through a cors wrapper so that people on other domains can see what's happening.
This commit is contained in:
parent
4673f40dd2
commit
3b3d71bfd7
18 changed files with 162 additions and 129 deletions
|
@ -1,9 +1,10 @@
|
|||
import logging
|
||||
import json
|
||||
|
||||
from flask import Blueprint, request
|
||||
from flask import Blueprint, request, make_response, jsonify
|
||||
from flask.ext.restful import Resource, abort, Api, reqparse
|
||||
from flask.ext.restful.utils.cors import crossdomain
|
||||
from werkzeug.exceptions import HTTPException
|
||||
from calendar import timegm
|
||||
from email.utils import formatdate
|
||||
from functools import partial, wraps
|
||||
|
@ -27,6 +28,57 @@ api.decorators = [process_oauth,
|
|||
crossdomain(origin='*', headers=['Authorization', 'Content-Type'])]
|
||||
|
||||
|
||||
class ApiException(Exception):
|
||||
def __init__(self, error_type, status_code, error_description, payload=None):
|
||||
Exception.__init__(self)
|
||||
self.error_description = error_description
|
||||
self.status_code = status_code
|
||||
self.payload = payload
|
||||
self.error_type = error_type
|
||||
|
||||
def to_dict(self):
|
||||
rv = dict(self.payload or ())
|
||||
if self.error_description is not None:
|
||||
rv['error_description'] = self.error_description
|
||||
|
||||
rv['error_type'] = self.error_type
|
||||
return rv
|
||||
|
||||
|
||||
invalid_request = partial(ApiException, 'invalid_request', 400)
|
||||
|
||||
|
||||
class InvalidRequest(ApiException):
|
||||
def __init__(self, error_description, payload=None):
|
||||
ApiException.__init__(self, 'invalid_request', 400, error_description, payload)
|
||||
|
||||
|
||||
class InvalidToken(ApiException):
|
||||
def __init__(self, error_description, payload=None):
|
||||
ApiException.__init__(self, 'invalid_token', 401, error_description, payload)
|
||||
|
||||
|
||||
class Unauthorized(ApiException):
|
||||
def __init__(self, payload=None):
|
||||
ApiException.__init__(self, 'insufficient_scope', 403, 'Unauthorized', payload)
|
||||
|
||||
|
||||
class NotFound(ApiException):
|
||||
def __init__(self, payload=None):
|
||||
ApiException.__init__(self, None, 404, 'Not Found', payload)
|
||||
|
||||
|
||||
@api_bp.app_errorhandler(ApiException)
|
||||
@crossdomain(origin='*', headers=['Authorization', 'Content-Type'])
|
||||
def handle_api_error(error):
|
||||
response = jsonify(error.to_dict())
|
||||
response.status_code = error.status_code
|
||||
if error.error_type is not None:
|
||||
response.headers['WWW-Authenticate'] = ('Bearer error="%s" error_description="%s"' %
|
||||
(error.error_type, error.error_description))
|
||||
return response
|
||||
|
||||
|
||||
def resource(*urls, **kwargs):
|
||||
def wrapper(api_resource):
|
||||
api.add_resource(api_resource, *urls, **kwargs)
|
||||
|
@ -84,7 +136,7 @@ def parse_args(func):
|
|||
@wraps(func)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
if '__api_query_params' not in dir(func):
|
||||
abort(400)
|
||||
abort(500)
|
||||
|
||||
parser = reqparse.RequestParser()
|
||||
for arg_spec in func.__api_query_params:
|
||||
|
@ -124,7 +176,7 @@ def require_repo_permission(permission_class, scope, allow_public=False):
|
|||
(allow_public and
|
||||
model.repository_is_public(namespace, repository))):
|
||||
return func(self, namespace, repository, *args, **kwargs)
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
return wrapped
|
||||
return wrapper
|
||||
|
||||
|
@ -154,17 +206,14 @@ def validate_json_request(schema_name):
|
|||
validate(request.get_json(), schema)
|
||||
return func(self, *args, **kwargs)
|
||||
except ValidationError as ex:
|
||||
abort(400, message=ex.message)
|
||||
InvalidRequest(ex.message)
|
||||
return wrapped
|
||||
return wrapper
|
||||
|
||||
|
||||
def request_error(exception=None, **kwargs):
|
||||
data = kwargs.copy()
|
||||
if exception:
|
||||
data['message'] = exception.message
|
||||
|
||||
return json.dumps(data), 400
|
||||
raise InvalidRequest(exception.message, data)
|
||||
|
||||
|
||||
def log_action(kind, user_or_orgname, metadata={}, repo=None):
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import logging
|
||||
import stripe
|
||||
|
||||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, log_action,
|
||||
related_user_resource, internal_only)
|
||||
related_user_resource, internal_only, Unauthorized, NotFound)
|
||||
from endpoints.api.subscribe import subscribe, subscription_view
|
||||
from auth.permissions import AdministerOrganizationPermission
|
||||
from auth.auth_context import get_authenticated_user
|
||||
|
@ -158,7 +156,7 @@ class OrganizationCard(ApiResource):
|
|||
organization = model.get_organization(orgname)
|
||||
return get_card(organization)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('setOrgCard')
|
||||
@validate_json_request('OrgCard')
|
||||
|
@ -172,7 +170,7 @@ class OrganizationCard(ApiResource):
|
|||
log_action('account_change_cc', orgname)
|
||||
return response
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/user/plan')
|
||||
|
@ -266,7 +264,7 @@ class OrganizationPlan(ApiResource):
|
|||
organization = model.get_organization(orgname)
|
||||
return subscribe(organization, plan, token, True) # Business plan required
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('getOrgSubscription')
|
||||
def get(self, orgname):
|
||||
|
@ -286,7 +284,7 @@ class OrganizationPlan(ApiResource):
|
|||
'usedPrivateRepos': private_repos,
|
||||
}
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/user/invoices')
|
||||
|
@ -297,7 +295,7 @@ class UserInvoiceList(ApiResource):
|
|||
""" List the invoices for the current user. """
|
||||
user = get_authenticated_user()
|
||||
if not user.stripe_id:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return get_invoices(user.stripe_id)
|
||||
|
||||
|
@ -313,8 +311,8 @@ class OrgnaizationInvoiceList(ApiResource):
|
|||
if permission.can():
|
||||
organization = model.get_organization(orgname)
|
||||
if not organization.stripe_id:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return get_invoices(organization.stripe_id)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
|
@ -2,12 +2,11 @@ import logging
|
|||
import json
|
||||
|
||||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from app import app
|
||||
from endpoints.api import (RepositoryParamResource, parse_args, query_param, nickname, resource,
|
||||
require_repo_read, require_repo_write, validate_json_request,
|
||||
ApiResource, internal_only, format_date, api)
|
||||
ApiResource, internal_only, format_date, api, Unauthorized, NotFound)
|
||||
from endpoints.common import start_build
|
||||
from endpoints.trigger import BuildTrigger
|
||||
from data import model
|
||||
|
@ -111,7 +110,7 @@ class RepositoryBuildList(RepositoryParamResource):
|
|||
if associated_repository:
|
||||
if not ModifyRepositoryPermission(associated_repository.namespace,
|
||||
associated_repository.name):
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
# Start the build.
|
||||
repo = model.get_repository(namespace, repository)
|
||||
|
@ -137,7 +136,7 @@ class RepositoryBuildStatus(RepositoryParamResource):
|
|||
""" Return the status for the builds specified by the build uuids. """
|
||||
build = model.get_repository_build(namespace, repository, build_uuid)
|
||||
if not build:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
can_write = ModifyRepositoryPermission(namespace, repository).can()
|
||||
return build_status_view(build, can_write)
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import json
|
||||
|
||||
from collections import defaultdict
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from app import app
|
||||
from endpoints.api import (resource, nickname, require_repo_read, RepositoryParamResource,
|
||||
format_date)
|
||||
format_date, NotFound)
|
||||
from data import model
|
||||
from util.cache import cache_control_flask_restful
|
||||
|
||||
|
@ -64,7 +63,7 @@ class RepositoryImage(RepositoryParamResource):
|
|||
""" Get the information available for the specified image. """
|
||||
image = model.get_repo_image(namespace, repository, image_id)
|
||||
if not image:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return image_view(image)
|
||||
|
||||
|
@ -81,7 +80,7 @@ class RepositoryImageChanges(RepositoryParamResource):
|
|||
image = model.get_repo_image(namespace, repository, image_id)
|
||||
|
||||
if not image:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
uuid = image.storage and image.storage.uuid
|
||||
diffs_path = store.image_file_diffs_path(namespace, repository, image_id, uuid)
|
||||
|
@ -90,4 +89,4 @@ class RepositoryImageChanges(RepositoryParamResource):
|
|||
response_json = json.loads(store.get_content(diffs_path))
|
||||
return response_json
|
||||
except IOError:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import json
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, ApiResource, query_param, parse_args,
|
||||
RepositoryParamResource, require_repo_admin, related_user_resource,
|
||||
format_date)
|
||||
format_date, Unauthorized, NotFound)
|
||||
from auth.permissions import AdministerOrganizationPermission, AdministerOrganizationPermission
|
||||
from auth.auth_context import get_authenticated_user
|
||||
from data import model
|
||||
|
@ -75,7 +74,7 @@ class RepositoryLogs(RepositoryParamResource):
|
|||
""" List the logs for the specified repository. """
|
||||
repo = model.get_repository(namespace, repository)
|
||||
if not repo:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
start_time = args['starttime']
|
||||
end_time = args['endtime']
|
||||
|
@ -119,4 +118,4 @@ class OrgLogs(ApiResource):
|
|||
|
||||
return get_logs(orgname, start_time, end_time, performer_name=performer_name)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
|
@ -2,10 +2,9 @@ import logging
|
|||
import stripe
|
||||
|
||||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
||||
related_user_resource, internal_only)
|
||||
related_user_resource, internal_only, Unauthorized, NotFound)
|
||||
from endpoints.api.team import team_view
|
||||
from endpoints.api.user import User, PrivateRepositories
|
||||
from auth.permissions import (AdministerOrganizationPermission, OrganizationMemberPermission,
|
||||
|
@ -83,13 +82,13 @@ class OrganizationList(ApiResource):
|
|||
|
||||
if existing:
|
||||
msg = 'A user or organization with this name already exists'
|
||||
return request_error(message=msg)
|
||||
raise request_error(message=msg)
|
||||
|
||||
try:
|
||||
model.create_organization(org_data['name'], org_data['email'], get_authenticated_user())
|
||||
return 'Created', 201
|
||||
except model.DataModelException as ex:
|
||||
return request_error(exception=ex)
|
||||
raise request_error(exception=ex)
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>')
|
||||
|
@ -121,12 +120,12 @@ class Organization(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
teams = model.get_teams_within_org(org)
|
||||
return org_view(org, teams)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('changeOrganizationDetails')
|
||||
@validate_json_request('UpdateOrg')
|
||||
|
@ -135,7 +134,7 @@ class Organization(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
org_data = request.get_json()
|
||||
if 'invoice_email' in org_data:
|
||||
|
@ -145,7 +144,7 @@ class Organization(ApiResource):
|
|||
if 'email' in org_data and org_data['email'] != org.email:
|
||||
new_email = org_data['email']
|
||||
if model.find_user_by_email(new_email):
|
||||
return request_error(message='E-mail address already used')
|
||||
raise request_error(message='E-mail address already used')
|
||||
|
||||
logger.debug('Changing email address for organization: %s', org.username)
|
||||
model.update_email(org, new_email)
|
||||
|
@ -185,7 +184,7 @@ class OrgPrivateRepositories(ApiResource):
|
|||
|
||||
return data
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/members')
|
||||
|
@ -199,7 +198,7 @@ class OrgnaizationMemberList(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
# Loop to create the members dictionary. Note that the members collection
|
||||
# will return an entry for *every team* a member is on, so we will have
|
||||
|
@ -217,7 +216,7 @@ class OrgnaizationMemberList(ApiResource):
|
|||
|
||||
return {'members': members_dict}
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/members/<membername>')
|
||||
|
@ -231,7 +230,7 @@ class OrganizationMember(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
member_dict = None
|
||||
member_teams = model.get_organization_members_with_teams(org, membername=membername)
|
||||
|
@ -245,8 +244,8 @@ class OrganizationMember(ApiResource):
|
|||
member_dict['teams'].append(member.team.name)
|
||||
|
||||
if not member_dict:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return {'member': member_dict}
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
|
@ -145,7 +145,7 @@ class RepositoryUserPermission(RepositoryParamResource):
|
|||
# This repository is not part of an organization
|
||||
pass
|
||||
except model.DataModelException as ex:
|
||||
return request_error(exception=ex)
|
||||
raise request_error(exception=ex)
|
||||
|
||||
log_action('change_repo_permission', namespace,
|
||||
{'username': username, 'repo': repository,
|
||||
|
@ -161,7 +161,7 @@ class RepositoryUserPermission(RepositoryParamResource):
|
|||
try:
|
||||
model.delete_user_permission(username, namespace, repository)
|
||||
except model.DataModelException as ex:
|
||||
return request_error(exception=ex)
|
||||
raise request_error(exception=ex)
|
||||
|
||||
log_action('delete_repo_permission', namespace,
|
||||
{'username': username, 'repo': repository},
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
||||
log_action)
|
||||
log_action, Unauthorized, NotFound)
|
||||
from auth.permissions import AdministerOrganizationPermission
|
||||
from auth.auth_context import get_authenticated_user
|
||||
from data import model
|
||||
|
@ -123,13 +122,13 @@ class PermissionPrototypeList(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
permissions = model.get_prototype_permissions(org)
|
||||
org_members = model.get_organization_member_set(orgname)
|
||||
return {'prototypes': [prototype_view(p, org_members) for p in permissions]}
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('createOrganizationPrototypePermission')
|
||||
@validate_json_request('NewPrototype')
|
||||
|
@ -140,7 +139,7 @@ class PermissionPrototypeList(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
details = request.get_json()
|
||||
activating_username = None
|
||||
|
@ -162,10 +161,10 @@ class PermissionPrototypeList(ApiResource):
|
|||
if delegate_teamname else None)
|
||||
|
||||
if activating_username and not activating_user:
|
||||
return request_error(message='Unknown activating user')
|
||||
raise request_error(message='Unknown activating user')
|
||||
|
||||
if not delegate_user and not delegate_team:
|
||||
return request_error(message='Missing delegate user or team')
|
||||
raise request_error(message='Missing delegate user or team')
|
||||
|
||||
role_name = details['role']
|
||||
|
||||
|
@ -175,7 +174,7 @@ class PermissionPrototypeList(ApiResource):
|
|||
org_members = model.get_organization_member_set(orgname)
|
||||
return prototype_view(prototype, org_members)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/prototypes/<prototypeid>')
|
||||
|
@ -211,17 +210,17 @@ class PermissionPrototype(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
prototype = model.delete_prototype_permission(org, prototypeid)
|
||||
if not prototype:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
log_prototype_action('delete_prototype_permission', orgname, prototype)
|
||||
|
||||
return 'Deleted', 204
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('updateOrganizationPrototypePermission')
|
||||
@validate_json_request('PrototypeUpdate')
|
||||
|
@ -232,21 +231,21 @@ class PermissionPrototype(ApiResource):
|
|||
try:
|
||||
org = model.get_organization(orgname)
|
||||
except model.InvalidOrganizationException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
existing = model.get_prototype_permission(org, prototypeid)
|
||||
if not existing:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
details = request.get_json()
|
||||
role_name = details['role']
|
||||
prototype = model.update_prototype_permission(org, prototypeid, role_name)
|
||||
if not prototype:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
log_prototype_action('modify_prototype_permission', orgname, prototype,
|
||||
original_role=existing.role.name)
|
||||
org_members = model.get_organization_member_set(orgname)
|
||||
return prototype_view(prototype, org_members)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
|
|
@ -2,13 +2,12 @@ import logging
|
|||
import json
|
||||
|
||||
from flask import current_app, request
|
||||
from flask.ext.restful import reqparse, abort
|
||||
|
||||
from data import model
|
||||
from endpoints.api import (truthy_bool, format_date, nickname, log_action, validate_json_request,
|
||||
require_repo_read, require_repo_write, require_repo_admin,
|
||||
RepositoryParamResource, resource, query_param, parse_args, ApiResource,
|
||||
request_error, require_scope)
|
||||
request_error, require_scope, Unauthorized, NotFound)
|
||||
from auth.permissions import (ReadRepositoryPermission, ModifyRepositoryPermission,
|
||||
AdministerRepositoryPermission, CreateRepositoryPermission)
|
||||
from auth.auth import process_auth
|
||||
|
@ -73,7 +72,7 @@ class RepositoryList(ApiResource):
|
|||
|
||||
existing = model.get_repository(namespace_name, repository_name)
|
||||
if existing:
|
||||
return request_error(message='Repository already exists')
|
||||
raise request_error(message='Repository already exists')
|
||||
|
||||
visibility = req['visibility']
|
||||
|
||||
|
@ -89,7 +88,7 @@ class RepositoryList(ApiResource):
|
|||
'name': repository_name
|
||||
}, 201
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('listRepos')
|
||||
@parse_args
|
||||
|
@ -213,7 +212,7 @@ class Repository(RepositoryParamResource):
|
|||
'status_token': repo.badge_token if not is_public else ''
|
||||
}
|
||||
|
||||
abort(404) # Not found
|
||||
raise NotFound()
|
||||
|
||||
@require_repo_write
|
||||
@nickname('updateRepo')
|
||||
|
@ -232,7 +231,7 @@ class Repository(RepositoryParamResource):
|
|||
return {
|
||||
'success': True
|
||||
}
|
||||
abort(404) # Not found
|
||||
raise NotFound()
|
||||
|
||||
@require_repo_admin
|
||||
@nickname('deleteRepository')
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import logging
|
||||
|
||||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, require_repo_admin, RepositoryParamResource,
|
||||
log_action, validate_json_request)
|
||||
log_action, validate_json_request, NotFound)
|
||||
from data import model
|
||||
|
||||
|
||||
|
@ -97,7 +96,7 @@ class RepositoryToken(RepositoryParamResource):
|
|||
try:
|
||||
perm = model.get_repo_delegate_token(namespace, repository, code)
|
||||
except model.InvalidTokenException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return token_view(perm)
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import resource, nickname, ApiResource, log_action, related_user_resource
|
||||
from endpoints.api import (resource, nickname, ApiResource, log_action, related_user_resource,
|
||||
Unauthorized)
|
||||
from auth.permissions import AdministerOrganizationPermission, OrganizationMemberPermission
|
||||
from auth.auth_context import get_authenticated_user
|
||||
from data import model
|
||||
|
@ -21,6 +20,9 @@ class UserRobotList(ApiResource):
|
|||
def get(self):
|
||||
""" List the available robots for the user. """
|
||||
user = get_authenticated_user()
|
||||
if not user:
|
||||
raise Unauthorized()
|
||||
|
||||
robots = model.list_entity_robots(user.username)
|
||||
return {
|
||||
'robots': [robot_view(name, password) for name, password in robots]
|
||||
|
@ -34,6 +36,9 @@ class UserRobot(ApiResource):
|
|||
def put(self, robot_shortname):
|
||||
""" Create a new user robot with the specified name. """
|
||||
parent = get_authenticated_user()
|
||||
if not parent:
|
||||
raise Unauthorized()
|
||||
|
||||
robot, password = model.create_robot(robot_shortname, parent)
|
||||
log_action('create_robot', parent.username, {'robot': robot_shortname})
|
||||
return robot_view(robot.username, password), 201
|
||||
|
@ -42,6 +47,9 @@ class UserRobot(ApiResource):
|
|||
def delete(self, robot_shortname):
|
||||
""" Delete an existing robot. """
|
||||
parent = get_authenticated_user()
|
||||
if not parent:
|
||||
raise Unauthorized()
|
||||
|
||||
model.delete_robot(format_robot_username(parent.username, robot_shortname))
|
||||
log_action('delete_robot', parent.username, {'robot': robot_shortname})
|
||||
return 'Deleted', 204
|
||||
|
@ -61,7 +69,7 @@ class OrgRobotList(ApiResource):
|
|||
'robots': [robot_view(name, password) for name, password in robots]
|
||||
}
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/robots/<robot_shortname>')
|
||||
|
@ -78,7 +86,7 @@ class OrgRobot(ApiResource):
|
|||
log_action('create_robot', orgname, {'robot': robot_shortname})
|
||||
return robot_view(robot.username, password), 201
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('deleteOrgRobot')
|
||||
def delete(self, orgname, robot_shortname):
|
||||
|
@ -89,4 +97,4 @@ class OrgRobot(ApiResource):
|
|||
log_action('delete_robot', orgname, {'robot': robot_shortname})
|
||||
return 'Deleted', 204
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import logging
|
||||
import stripe
|
||||
|
||||
from endpoints.api import request_error, log_action
|
||||
from endpoints.api import request_error, log_action, NotFound
|
||||
from data import model
|
||||
from data.plans import PLANS
|
||||
from util.http import abort
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -31,13 +30,13 @@ def subscribe(user, plan, token, require_business_plan):
|
|||
|
||||
if not plan_found or plan_found['deprecated']:
|
||||
logger.warning('Plan not found or deprecated: %s', plan)
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
if (require_business_plan and not plan_found['bus_features'] and not
|
||||
plan_found['price'] == 0):
|
||||
logger.warning('Business attempting to subscribe to personal plan: %s',
|
||||
user.username)
|
||||
return request_error(message='No matching plan found')
|
||||
raise request_error(message='No matching plan found')
|
||||
|
||||
private_repos = model.get_private_repo_count(user.username)
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, require_repo_read, require_repo_admin,
|
||||
RepositoryParamResource, log_action)
|
||||
RepositoryParamResource, log_action, NotFound)
|
||||
from endpoints.api.image import image_view
|
||||
from data import model
|
||||
from auth.auth_context import get_authenticated_user
|
||||
|
@ -36,7 +34,7 @@ class RepositoryTagImages(RepositoryParamResource):
|
|||
try:
|
||||
tag_image = model.get_tag_image(namespace, repository, tag)
|
||||
except model.DataModelException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
parent_images = model.get_parent_images(tag_image)
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
||||
log_action)
|
||||
log_action, Unauthorized, NotFound)
|
||||
from auth.permissions import AdministerOrganizationPermission, ViewTeamPermission
|
||||
from auth.auth_context import get_authenticated_user
|
||||
from data import model
|
||||
|
@ -95,7 +94,7 @@ class OrganizationTeam(ApiResource):
|
|||
|
||||
return team_view(orgname, team), 200
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('deleteOrganizationTeam')
|
||||
def delete(self, orgname, teamname):
|
||||
|
@ -106,7 +105,7 @@ class OrganizationTeam(ApiResource):
|
|||
log_action('org_delete_team', orgname, {'team': teamname})
|
||||
return 'Deleted', 204
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/team/<teamname>/members')
|
||||
|
@ -123,7 +122,7 @@ class TeamMemberList(ApiResource):
|
|||
try:
|
||||
team = model.get_organization_team(orgname, teamname)
|
||||
except model.InvalidTeamException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
members = model.get_organization_team_members(team.id)
|
||||
return {
|
||||
|
@ -131,7 +130,7 @@ class TeamMemberList(ApiResource):
|
|||
'can_edit': edit_permission.can()
|
||||
}
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/organization/<orgname>/team/<teamname>/members/<membername>')
|
||||
|
@ -149,19 +148,19 @@ class TeamMember(ApiResource):
|
|||
try:
|
||||
team = model.get_organization_team(orgname, teamname)
|
||||
except model.InvalidTeamException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
# Find the user.
|
||||
user = model.get_user(membername)
|
||||
if not user:
|
||||
return request_error(message='Unknown user')
|
||||
raise request_error(message='Unknown user')
|
||||
|
||||
# Add the user to the team.
|
||||
model.add_user_to_team(user, team)
|
||||
log_action('org_add_team_member', orgname, {'member': membername, 'team': teamname})
|
||||
return member_view(user)
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
@nickname('deleteOrganizationTeamMember')
|
||||
def delete(self, orgname, teamname, membername):
|
||||
|
@ -174,4 +173,4 @@ class TeamMember(ApiResource):
|
|||
log_action('org_remove_team_member', orgname, {'member': membername, 'team': teamname})
|
||||
return 'Deleted', 204
|
||||
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
|
|
@ -2,14 +2,13 @@ import json
|
|||
import logging
|
||||
|
||||
from flask import request, url_for
|
||||
from flask.ext.restful import abort
|
||||
from urllib import quote
|
||||
from urlparse import urlunparse
|
||||
|
||||
from app import app
|
||||
from endpoints.api import (RepositoryParamResource, nickname, resource, require_repo_admin,
|
||||
log_action, request_error, query_param, parse_args,
|
||||
validate_json_request, api)
|
||||
validate_json_request, api, Unauthorized, NotFound, InvalidRequest)
|
||||
from endpoints.api.build import build_status_view, trigger_view, RepositoryBuildStatus
|
||||
from endpoints.common import start_build
|
||||
from endpoints.trigger import (BuildTrigger, TriggerDeactivationException,
|
||||
|
@ -51,7 +50,7 @@ class BuildTrigger(RepositoryParamResource):
|
|||
try:
|
||||
trigger = model.get_build_trigger(namespace, repository, trigger_uuid)
|
||||
except model.InvalidBuildTriggerException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return trigger_view(trigger)
|
||||
|
||||
|
@ -62,8 +61,7 @@ class BuildTrigger(RepositoryParamResource):
|
|||
try:
|
||||
trigger = model.get_build_trigger(namespace, repository, trigger_uuid)
|
||||
except model.InvalidBuildTriggerException:
|
||||
abort(404)
|
||||
return
|
||||
raise NotFound()
|
||||
|
||||
handler = BuildTrigger.get_trigger_for_service(trigger.service.name)
|
||||
config_dict = json.loads(trigger.config)
|
||||
|
@ -102,8 +100,7 @@ class BuildTriggerSubdirs(RepositoryParamResource):
|
|||
try:
|
||||
trigger = model.get_build_trigger(namespace, repository, trigger_uuid)
|
||||
except model.InvalidBuildTriggerException:
|
||||
abort(404)
|
||||
return
|
||||
raise NotFound()
|
||||
|
||||
handler = BuildTrigger.get_trigger_for_service(trigger.service.name)
|
||||
user_permission = UserPermission(trigger.connected_user.username)
|
||||
|
@ -122,7 +119,7 @@ class BuildTriggerSubdirs(RepositoryParamResource):
|
|||
'message': exc.msg
|
||||
}
|
||||
else:
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/repository/<path:repository>/trigger/<trigger_uuid>/activate')
|
||||
|
@ -145,12 +142,12 @@ class BuildTriggerActivate(RepositoryParamResource):
|
|||
try:
|
||||
trigger = model.get_build_trigger(namespace, repository, trigger_uuid)
|
||||
except model.InvalidBuildTriggerException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
handler = BuildTrigger.get_trigger_for_service(trigger.service.name)
|
||||
existing_config_dict = json.loads(trigger.config)
|
||||
if handler.is_active(existing_config_dict):
|
||||
abort(400)
|
||||
raise InvalidRequest('Trigger config is not sufficient for activation.')
|
||||
|
||||
user_permission = UserPermission(trigger.connected_user.username)
|
||||
if user_permission.can():
|
||||
|
@ -173,7 +170,7 @@ class BuildTriggerActivate(RepositoryParamResource):
|
|||
trigger.auth_token, new_config_dict)
|
||||
except TriggerActivationException as exc:
|
||||
token.delete_instance()
|
||||
return request_error(message=exc.message)
|
||||
raise request_error(message=exc.message)
|
||||
|
||||
# Save the updated config.
|
||||
trigger.config = json.dumps(final_config)
|
||||
|
@ -189,7 +186,7 @@ class BuildTriggerActivate(RepositoryParamResource):
|
|||
|
||||
return trigger_view(trigger)
|
||||
else:
|
||||
abort(403)
|
||||
raise Unauthorized()
|
||||
|
||||
|
||||
@resource('/v1/repository/<path:repository>/trigger/<trigger_uuid>/start')
|
||||
|
@ -203,12 +200,12 @@ class ActivateBuildTrigger(RepositoryParamResource):
|
|||
try:
|
||||
trigger = model.get_build_trigger(namespace, repository, trigger_uuid)
|
||||
except model.InvalidBuildTriggerException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
handler = BuildTrigger.get_trigger_for_service(trigger.service.name)
|
||||
existing_config_dict = json.loads(trigger.config)
|
||||
if not handler.is_active(existing_config_dict):
|
||||
abort(400)
|
||||
raise InvalidRequest('Trigger is not active.')
|
||||
|
||||
specs = handler.manual_start(trigger.auth_token, json.loads(trigger.config))
|
||||
dockerfile_id, tags, name, subdir = specs
|
||||
|
@ -253,7 +250,7 @@ class BuildTriggerSources(RepositoryParamResource):
|
|||
try:
|
||||
trigger = model.get_build_trigger(namespace, repository, trigger_uuid)
|
||||
except model.InvalidBuildTriggerException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
user_permission = UserPermission(trigger.connected_user.username)
|
||||
if user_permission.can():
|
||||
|
@ -263,4 +260,4 @@ class BuildTriggerSources(RepositoryParamResource):
|
|||
'sources': trigger_handler.list_build_sources(trigger.auth_token)
|
||||
}
|
||||
else:
|
||||
abort(403)
|
||||
raise Unauthorized()
|
|
@ -2,13 +2,12 @@ import logging
|
|||
import stripe
|
||||
|
||||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
from flask.ext.login import logout_user
|
||||
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)
|
||||
log_action, internal_only, NotFound)
|
||||
from endpoints.api.subscribe import subscribe
|
||||
from endpoints.common import common_login
|
||||
from data import model
|
||||
|
@ -139,7 +138,7 @@ class User(ApiResource):
|
|||
new_email = user_data['email']
|
||||
if model.find_user_by_email(new_email):
|
||||
# Email already used.
|
||||
return request_error(message='E-mail address already used')
|
||||
raise request_error(message='E-mail address already used')
|
||||
|
||||
logger.debug('Sending email to change email address for user: %s',
|
||||
user.username)
|
||||
|
@ -147,7 +146,7 @@ class User(ApiResource):
|
|||
send_change_email(user.username, user_data['email'], code.code)
|
||||
|
||||
except model.InvalidPasswordException, ex:
|
||||
return request_error(exception=ex)
|
||||
raise request_error(exception=ex)
|
||||
|
||||
return user_view(user)
|
||||
|
||||
|
@ -160,7 +159,7 @@ class User(ApiResource):
|
|||
|
||||
existing_user = model.get_user(user_data['username'])
|
||||
if existing_user:
|
||||
return request_error(message='The username already exists')
|
||||
raise request_error(message='The username already exists')
|
||||
|
||||
try:
|
||||
new_user = model.create_user(user_data['username'], user_data['password'],
|
||||
|
@ -169,7 +168,7 @@ class User(ApiResource):
|
|||
send_confirmation_email(new_user.username, new_user.email, code.code)
|
||||
return 'Created', 201
|
||||
except model.DataModelException as ex:
|
||||
return request_error(exception=ex)
|
||||
raise request_error(exception=ex)
|
||||
|
||||
|
||||
@resource('/v1/user/private')
|
||||
|
@ -257,13 +256,13 @@ class ConvertToOrganization(ApiResource):
|
|||
# Ensure that the new admin user is the not user being converted.
|
||||
admin_username = convert_data['adminUser']
|
||||
if admin_username == user.username:
|
||||
return request_error(reason='invaliduser',
|
||||
raise request_error(reason='invaliduser',
|
||||
message='The admin user is not valid')
|
||||
|
||||
# Ensure that the sign in credentials work.
|
||||
admin_password = convert_data['adminPassword']
|
||||
if not model.verify_user(admin_username, admin_password):
|
||||
return request_error(reason='invaliduser',
|
||||
raise request_error(reason='invaliduser',
|
||||
message='The admin user credentials are not valid')
|
||||
|
||||
# Subscribe the organization to the new plan.
|
||||
|
@ -310,7 +309,7 @@ class Signin(ApiResource):
|
|||
""" Sign in the user with the specified credentials. """
|
||||
signin_data = request.get_json()
|
||||
if not signin_data:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
username = signin_data['username']
|
||||
password = signin_data['password']
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import json
|
||||
|
||||
from flask import request
|
||||
from flask.ext.restful import abort
|
||||
|
||||
from endpoints.api import (RepositoryParamResource, nickname, resource, require_repo_admin,
|
||||
log_action, validate_json_request, api)
|
||||
log_action, validate_json_request, api, NotFound)
|
||||
from data import model
|
||||
|
||||
|
||||
|
@ -63,7 +62,7 @@ class Webhook(RepositoryParamResource):
|
|||
try:
|
||||
webhook = model.get_webhook(namespace, repository, public_id)
|
||||
except model.InvalidWebhookException:
|
||||
abort(404)
|
||||
raise NotFound()
|
||||
|
||||
return webhook_view(webhook)
|
||||
|
||||
|
|
|
@ -77,12 +77,6 @@ def handle_dme(ex):
|
|||
return make_response(ex.message, 400)
|
||||
|
||||
|
||||
@app.errorhandler(KeyError)
|
||||
def handle_dme_key_error(ex):
|
||||
logger.exception(ex)
|
||||
return make_response('Invalid key: %s' % ex.message, 400)
|
||||
|
||||
|
||||
def generate_csrf_token():
|
||||
if '_csrf_token' not in session:
|
||||
session['_csrf_token'] = base64.b64encode(os.urandom(48))
|
||||
|
|
Reference in a new issue