Switch the Python side to Swagger v2
This commit is contained in:
parent
86f400fdf5
commit
0bc1c29dff
21 changed files with 217 additions and 138 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
""" Billing information, subscriptions, and plan information. """
|
||||||
|
|
||||||
import stripe
|
import stripe
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
@ -352,7 +354,7 @@ class UserInvoiceList(ApiResource):
|
||||||
@path_param('orgname', 'The name of the organization')
|
@path_param('orgname', 'The name of the organization')
|
||||||
@related_user_resource(UserInvoiceList)
|
@related_user_resource(UserInvoiceList)
|
||||||
@show_if(features.BILLING)
|
@show_if(features.BILLING)
|
||||||
class OrgnaizationInvoiceList(ApiResource):
|
class OrganizationInvoiceList(ApiResource):
|
||||||
""" Resource for listing an orgnaization's invoices. """
|
""" Resource for listing an orgnaization's invoices. """
|
||||||
@require_scope(scopes.ORG_ADMIN)
|
@require_scope(scopes.ORG_ADMIN)
|
||||||
@nickname('listOrgInvoices')
|
@nickname('listOrgInvoices')
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Create, list, cancel and get status/logs of repository builds. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
@ -165,7 +167,8 @@ class RepositoryBuildList(RepositoryParamResource):
|
||||||
},
|
},
|
||||||
'docker_tags': {
|
'docker_tags': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'description': 'The tags to which the built images will be pushed',
|
'description': 'The tags to which the built images will be pushed. ' +
|
||||||
|
'If none specified, "latest" is used.',
|
||||||
'items': {
|
'items': {
|
||||||
'type': 'string'
|
'type': 'string'
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
""" API discovery information. """
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
from flask.ext.restful import reqparse
|
from flask.ext.restful import reqparse
|
||||||
|
|
||||||
|
@ -7,7 +10,7 @@ from endpoints.api import (ApiResource, resource, method_metadata, nickname, tru
|
||||||
parse_args, query_param)
|
parse_args, query_param)
|
||||||
from app import app
|
from app import app
|
||||||
from auth import scopes
|
from auth import scopes
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -32,162 +35,195 @@ def fully_qualified_name(method_view_class):
|
||||||
|
|
||||||
|
|
||||||
def swagger_route_data(include_internal=False, compact=False):
|
def swagger_route_data(include_internal=False, compact=False):
|
||||||
apis = []
|
|
||||||
|
def swagger_parameter(name, description, kind='path', param_type='string', required=True,
|
||||||
|
enum=None, schema=None):
|
||||||
|
# https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#parameterObject
|
||||||
|
parameter_info = {
|
||||||
|
'name': name,
|
||||||
|
'in': kind,
|
||||||
|
'required': required
|
||||||
|
}
|
||||||
|
|
||||||
|
if not compact:
|
||||||
|
parameter_info['description'] = description or ''
|
||||||
|
|
||||||
|
if schema:
|
||||||
|
parameter_info['schema'] = {
|
||||||
|
'$ref': '#/definitions/%s' % schema
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
parameter_info['type'] = param_type
|
||||||
|
|
||||||
|
if enum is not None and len(list(enum)) > 0:
|
||||||
|
parameter_info['enum'] = list(enum)
|
||||||
|
|
||||||
|
return parameter_info
|
||||||
|
|
||||||
|
|
||||||
|
paths = {}
|
||||||
models = {}
|
models = {}
|
||||||
|
tags = []
|
||||||
|
tags_added = set()
|
||||||
|
|
||||||
for rule in app.url_map.iter_rules():
|
for rule in app.url_map.iter_rules():
|
||||||
endpoint_method = app.view_functions[rule.endpoint]
|
endpoint_method = app.view_functions[rule.endpoint]
|
||||||
|
|
||||||
if 'view_class' in dir(endpoint_method):
|
# Verify that we have a view class for this API method.
|
||||||
view_class = endpoint_method.view_class
|
if not 'view_class' in dir(endpoint_method):
|
||||||
|
continue
|
||||||
|
|
||||||
param_data_map = {}
|
view_class = endpoint_method.view_class
|
||||||
if '__api_path_params' in dir(view_class):
|
|
||||||
param_data_map = view_class.__api_path_params
|
|
||||||
|
|
||||||
operations = []
|
# Hide the class if it is internal.
|
||||||
|
internal = method_metadata(view_class, 'internal')
|
||||||
|
if not include_internal and internal:
|
||||||
|
continue
|
||||||
|
|
||||||
method_names = list(rule.methods.difference(['HEAD', 'OPTIONS']))
|
# Build the tag.
|
||||||
for method_name in method_names:
|
parts = fully_qualified_name(view_class).split('.')
|
||||||
method = getattr(view_class, method_name.lower(), None)
|
tag_name = parts[-2]
|
||||||
|
if not tag_name in tags_added:
|
||||||
|
tags_added.add(tag_name)
|
||||||
|
tags.append({
|
||||||
|
'name': tag_name,
|
||||||
|
'description': (sys.modules[view_class.__module__].__doc__ or '').strip()
|
||||||
|
})
|
||||||
|
|
||||||
parameters = []
|
# Build the Swagger data for the path.
|
||||||
|
swagger_path = PARAM_REGEX.sub(r'{\2}', rule.rule)
|
||||||
|
path_swagger = {
|
||||||
|
'name': fully_qualified_name(view_class),
|
||||||
|
'tag': tag_name
|
||||||
|
}
|
||||||
|
|
||||||
for param in rule.arguments:
|
paths[swagger_path] = path_swagger
|
||||||
parameters.append({
|
|
||||||
'paramType': 'path',
|
|
||||||
'name': param,
|
|
||||||
'dataType': 'string',
|
|
||||||
'description': param_data_map.get(param, {'description': ''})['description'],
|
|
||||||
'required': True,
|
|
||||||
})
|
|
||||||
|
|
||||||
if method is None:
|
# Add any global path parameters.
|
||||||
logger.debug('Unable to find method for %s in class %s', method_name, view_class)
|
param_data_map = view_class.__api_path_params if '__api_path_params' in dir(view_class) else {}
|
||||||
else:
|
if param_data_map:
|
||||||
req_schema_name = method_metadata(method, 'request_schema')
|
path_parameters_swagger = []
|
||||||
if req_schema_name:
|
for path_parameter in param_data_map:
|
||||||
parameters.append({
|
description = param_data_map[path_parameter].get('description')
|
||||||
'paramType': 'body',
|
path_parameters_swagger.append(swagger_parameter(path_parameter, description))
|
||||||
'name': 'body',
|
|
||||||
'description': 'Request body contents.',
|
|
||||||
'dataType': req_schema_name,
|
|
||||||
'required': True,
|
|
||||||
})
|
|
||||||
|
|
||||||
schema = view_class.schemas[req_schema_name]
|
path_swagger['parameters'] = path_parameters_swagger
|
||||||
models[req_schema_name] = schema
|
|
||||||
|
|
||||||
if '__api_query_params' in dir(method):
|
# Add the individual HTTP operations.
|
||||||
for param_spec in method.__api_query_params:
|
method_names = list(rule.methods.difference(['HEAD', 'OPTIONS']))
|
||||||
new_param = {
|
for method_name in method_names:
|
||||||
'paramType': 'query',
|
# https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operation-object
|
||||||
'name': param_spec['name'],
|
method = getattr(view_class, method_name.lower(), None)
|
||||||
'description': param_spec['help'],
|
if method is None:
|
||||||
'dataType': TYPE_CONVERTER[param_spec['type']],
|
logger.debug('Unable to find method for %s in class %s', method_name, view_class)
|
||||||
'required': param_spec['required'],
|
continue
|
||||||
}
|
|
||||||
|
|
||||||
if len(param_spec['choices']) > 0:
|
operation_swagger = {
|
||||||
new_param['enum'] = list(param_spec['choices'])
|
'operationId': method_metadata(method, 'nickname') or 'unnamed',
|
||||||
|
'parameters': [],
|
||||||
parameters.append(new_param)
|
|
||||||
|
|
||||||
new_operation = {
|
|
||||||
'method': method_name,
|
|
||||||
'nickname': method_metadata(method, 'nickname') or '(unnamed)'
|
|
||||||
}
|
|
||||||
|
|
||||||
if not compact:
|
|
||||||
response_type = 'void'
|
|
||||||
res_schema_name = method_metadata(method, 'response_schema')
|
|
||||||
if res_schema_name:
|
|
||||||
models[res_schema_name] = view_class.schemas[res_schema_name]
|
|
||||||
response_type = res_schema_name
|
|
||||||
|
|
||||||
new_operation.update({
|
|
||||||
'type': response_type,
|
|
||||||
'summary': method.__doc__.strip() if method.__doc__ else '',
|
|
||||||
'parameters': parameters,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
scope = method_metadata(method, 'oauth2_scope')
|
|
||||||
if scope and not compact:
|
|
||||||
new_operation['authorizations'] = {
|
|
||||||
'oauth2': [
|
|
||||||
{
|
|
||||||
'scope': scope.scope
|
|
||||||
}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
internal = method_metadata(method, 'internal')
|
|
||||||
if internal is not None:
|
|
||||||
new_operation['internal'] = True
|
|
||||||
|
|
||||||
if include_internal:
|
|
||||||
requires_fresh_login = method_metadata(method, 'requires_fresh_login')
|
|
||||||
if requires_fresh_login is not None:
|
|
||||||
new_operation['requires_fresh_login'] = True
|
|
||||||
|
|
||||||
if not internal or (internal and include_internal):
|
|
||||||
# Swagger requires valid nicknames on all operations.
|
|
||||||
if new_operation.get('nickname'):
|
|
||||||
operations.append(new_operation)
|
|
||||||
else:
|
|
||||||
logger.debug('Operation missing nickname: %s' % method)
|
|
||||||
|
|
||||||
swagger_path = PARAM_REGEX.sub(r'{\2}', rule.rule)
|
|
||||||
new_resource = {
|
|
||||||
'path': swagger_path,
|
|
||||||
'description': view_class.__doc__.strip() if view_class.__doc__ else "",
|
|
||||||
'operations': operations,
|
|
||||||
'name': fully_qualified_name(view_class),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
related_user_res = method_metadata(view_class, 'related_user_resource')
|
if not compact:
|
||||||
if related_user_res is not None:
|
operation_swagger.update({
|
||||||
new_resource['quayUserRelated'] = fully_qualified_name(related_user_res)
|
'description': method.__doc__.strip() if method.__doc__ else '',
|
||||||
|
'tags': [tag_name]
|
||||||
|
})
|
||||||
|
|
||||||
internal = method_metadata(view_class, 'internal')
|
# Mark the method as internal.
|
||||||
|
internal = method_metadata(method, 'internal')
|
||||||
if internal is not None:
|
if internal is not None:
|
||||||
new_resource['internal'] = True
|
operation_swagger['internal'] = True
|
||||||
|
|
||||||
|
if include_internal:
|
||||||
|
requires_fresh_login = method_metadata(method, 'requires_fresh_login')
|
||||||
|
if requires_fresh_login is not None:
|
||||||
|
operation_swagger['requires_fresh_login'] = True
|
||||||
|
|
||||||
|
related_user_res = method_metadata(view_class, 'related_user_resource')
|
||||||
|
if related_user_res is not None:
|
||||||
|
operation_swagger['quayUserRelated'] = fully_qualified_name(related_user_res)
|
||||||
|
|
||||||
|
# Add the path parameters.
|
||||||
|
if rule.arguments:
|
||||||
|
for path_parameter in rule.arguments:
|
||||||
|
description = param_data_map.get(path_parameter, {}).get('description')
|
||||||
|
operation_swagger['parameters'].append(swagger_parameter(path_parameter, description))
|
||||||
|
|
||||||
|
# Add the query parameters.
|
||||||
|
if '__api_query_params' in dir(method):
|
||||||
|
for query_parameter_info in method.__api_query_params:
|
||||||
|
name = query_parameter_info['name']
|
||||||
|
description = query_parameter_info['help']
|
||||||
|
param_type = TYPE_CONVERTER[query_parameter_info['type']]
|
||||||
|
required = query_parameter_info['required']
|
||||||
|
|
||||||
|
operation_swagger['parameters'].append(
|
||||||
|
swagger_parameter(name, description, kind='query',
|
||||||
|
param_type=param_type,
|
||||||
|
required=required,
|
||||||
|
enum=query_parameter_info['choices']))
|
||||||
|
|
||||||
|
# Add the OAuth security block.
|
||||||
|
# https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#securityRequirementObject
|
||||||
|
scope = method_metadata(method, 'oauth2_scope')
|
||||||
|
if scope and not compact:
|
||||||
|
operation_swagger['security'] = [{'oauth2_implicit': scope.scope}]
|
||||||
|
|
||||||
|
# TODO: Add the responses block.
|
||||||
|
# https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#responsesObject
|
||||||
|
response_schema_name = method_metadata(method, 'response_schema')
|
||||||
|
if response_schema_name and not compact:
|
||||||
|
models[response_schema_name] = view_class.schemas[response_schema_name]
|
||||||
|
response_type = response_schema_name
|
||||||
|
|
||||||
|
# Add the request block.
|
||||||
|
request_schema_name = method_metadata(method, 'request_schema')
|
||||||
|
if request_schema_name and not compact:
|
||||||
|
models[request_schema_name] = view_class.schemas[request_schema_name]
|
||||||
|
|
||||||
|
operation_swagger['parameters'].append(
|
||||||
|
swagger_parameter('body', 'Request body contents.', kind='body',
|
||||||
|
schema=request_schema_name))
|
||||||
|
|
||||||
|
# Add the operation to the parent path.
|
||||||
if not internal or (internal and include_internal):
|
if not internal or (internal and include_internal):
|
||||||
apis.append(new_resource)
|
path_swagger[method_name.lower()] = operation_swagger
|
||||||
|
|
||||||
|
tags.sort(key=lambda t: t['name'])
|
||||||
|
paths = OrderedDict(sorted(paths.items(), key=lambda p: p[1]['tag']))
|
||||||
|
|
||||||
# If compact form was requested, simply return the APIs.
|
|
||||||
if compact:
|
if compact:
|
||||||
return {'apis': apis}
|
return {'paths': paths}
|
||||||
|
|
||||||
swagger_data = {
|
swagger_data = {
|
||||||
'apiVersion': 'v1',
|
'swagger': '2.0',
|
||||||
'swaggerVersion': '1.2',
|
'host': SERVER_HOSTNAME,
|
||||||
'basePath': '%s://%s' % (PREFERRED_URL_SCHEME, SERVER_HOSTNAME),
|
'basePath': '/',
|
||||||
'resourcePath': '/',
|
'schemes': [
|
||||||
|
PREFERRED_URL_SCHEME
|
||||||
|
],
|
||||||
'info': {
|
'info': {
|
||||||
'title': 'Quay.io API',
|
'version': 'v1',
|
||||||
|
'title': 'Quay.io Frontend',
|
||||||
'description': ('This API allows you to perform many of the operations required to work '
|
'description': ('This API allows you to perform many of the operations required to work '
|
||||||
'with Quay.io repositories, users, and organizations. You can find out more '
|
'with Quay.io repositories, users, and organizations. You can find out more '
|
||||||
'at <a href="https://quay.io">Quay.io</a>.'),
|
'at <a href="https://quay.io">Quay.io</a>.'),
|
||||||
'termsOfServiceUrl': 'https://quay.io/tos',
|
'termsOfService': 'https://quay.io/tos',
|
||||||
'contact': 'support@quay.io',
|
'contact': {
|
||||||
|
'email': 'support@quay.io'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'authorizations': {
|
'securityDefinitions': {
|
||||||
'oauth2': {
|
'oauth2_implicit': {
|
||||||
'scopes': [scope._asdict() for scope in scopes.ALL_SCOPES.values()],
|
"type": "oauth2",
|
||||||
'grantTypes': {
|
"flow": "implicit",
|
||||||
"implicit": {
|
"authorizationUrl": "%s://%s/oauth/authorize" % (PREFERRED_URL_SCHEME, SERVER_HOSTNAME),
|
||||||
"tokenName": "access_token",
|
'scopes': {scope.scope:scope.description for scope in scopes.ALL_SCOPES.values()},
|
||||||
"loginEndpoint": {
|
|
||||||
"url": "%s://%s/oauth/authorize" % (PREFERRED_URL_SCHEME, SERVER_HOSTNAME),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'apis': apis,
|
'paths': paths,
|
||||||
'models': models,
|
'definitions': models,
|
||||||
|
'tags': tags
|
||||||
}
|
}
|
||||||
|
|
||||||
return swagger_data
|
return swagger_data
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" List and lookup repository images, and download image diffs. """
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Acces usage logs for organizations or repositories. """
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage organizations, members and OAuth applications. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
@ -333,7 +335,7 @@ def app_view(application):
|
||||||
@resource('/v1/organization/<orgname>/applications')
|
@resource('/v1/organization/<orgname>/applications')
|
||||||
@path_param('orgname', 'The name of the organization')
|
@path_param('orgname', 'The name of the organization')
|
||||||
class OrganizationApplications(ApiResource):
|
class OrganizationApplications(ApiResource):
|
||||||
""" Resource for managing applications defined by an organizations. """
|
""" Resource for managing applications defined by an organization. """
|
||||||
schemas = {
|
schemas = {
|
||||||
'NewApp': {
|
'NewApp': {
|
||||||
'id': 'NewApp',
|
'id': 'NewApp',
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage repository permissions. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage default permissions added to repositories. """
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Authorize repository to send e-mail notifications. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from flask import request, abort
|
from flask import request, abort
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" List, create and manage repositories. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import datetime
|
import datetime
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" List, create and manage repository events/notifications. """
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
from flask import request, abort
|
from flask import request, abort
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage repository access tokens (DEPRECATED). """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage user and organization robot accounts. """
|
||||||
|
|
||||||
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, require_user_admin, internal_only, require_scope,
|
Unauthorized, require_user_admin, internal_only, require_scope,
|
||||||
path_param, parse_args, truthy_bool, query_param)
|
path_param, parse_args, truthy_bool, query_param)
|
||||||
|
@ -68,7 +70,6 @@ def robots_list(prefix, include_permissions=False):
|
||||||
return {'robots': robots.values()}
|
return {'robots': robots.values()}
|
||||||
|
|
||||||
@resource('/v1/user/robots')
|
@resource('/v1/user/robots')
|
||||||
@internal_only
|
|
||||||
class UserRobotList(ApiResource):
|
class UserRobotList(ApiResource):
|
||||||
""" Resource for listing user robots. """
|
""" Resource for listing user robots. """
|
||||||
@require_user_admin
|
@require_user_admin
|
||||||
|
@ -85,7 +86,6 @@ class UserRobotList(ApiResource):
|
||||||
|
|
||||||
@resource('/v1/user/robots/<robot_shortname>')
|
@resource('/v1/user/robots/<robot_shortname>')
|
||||||
@path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix')
|
@path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix')
|
||||||
@internal_only
|
|
||||||
class UserRobot(ApiResource):
|
class UserRobot(ApiResource):
|
||||||
""" Resource for managing a user's robots. """
|
""" Resource for managing a user's robots. """
|
||||||
@require_user_admin
|
@require_user_admin
|
||||||
|
@ -181,7 +181,6 @@ class OrgRobot(ApiResource):
|
||||||
|
|
||||||
@resource('/v1/user/robots/<robot_shortname>/permissions')
|
@resource('/v1/user/robots/<robot_shortname>/permissions')
|
||||||
@path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix')
|
@path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix')
|
||||||
@internal_only
|
|
||||||
class UserRobotPermissions(ApiResource):
|
class UserRobotPermissions(ApiResource):
|
||||||
""" Resource for listing the permissions a user's robot has in the system. """
|
""" Resource for listing the permissions a user's robot has in the system. """
|
||||||
@require_user_admin
|
@require_user_admin
|
||||||
|
@ -222,7 +221,6 @@ class OrgRobotPermissions(ApiResource):
|
||||||
|
|
||||||
@resource('/v1/user/robots/<robot_shortname>/regenerate')
|
@resource('/v1/user/robots/<robot_shortname>/regenerate')
|
||||||
@path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix')
|
@path_param('robot_shortname', 'The short name for the robot, without any user or organization prefix')
|
||||||
@internal_only
|
|
||||||
class RegenerateUserRobot(ApiResource):
|
class RegenerateUserRobot(ApiResource):
|
||||||
""" Resource for regenerate an organization's robot's token. """
|
""" Resource for regenerate an organization's robot's token. """
|
||||||
@require_user_admin
|
@require_user_admin
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Conduct searches against all registry context. """
|
||||||
|
|
||||||
from endpoints.api import (ApiResource, parse_args, query_param, truthy_bool, nickname, resource,
|
from endpoints.api import (ApiResource, parse_args, query_param, truthy_bool, nickname, resource,
|
||||||
require_scope, path_param)
|
require_scope, path_param)
|
||||||
from data import model
|
from data import model
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Subscribe to plans. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import stripe
|
import stripe
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Superuser Config API. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Superuser API. """
|
||||||
|
|
||||||
import string
|
import string
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage the tags of a repository. """
|
||||||
|
|
||||||
from flask import request, abort
|
from flask import request, abort
|
||||||
|
|
||||||
from endpoints.api import (resource, nickname, require_repo_read, require_repo_write,
|
from endpoints.api import (resource, nickname, require_repo_read, require_repo_write,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Create, list and manage an organization's teams. """
|
||||||
|
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
from endpoints.api import (resource, nickname, ApiResource, validate_json_request, request_error,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Create, list and manage build triggers. """
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
@ -397,7 +399,7 @@ class ActivateBuildTrigger(RepositoryParamResource):
|
||||||
'properties': {
|
'properties': {
|
||||||
'branch_name': {
|
'branch_name': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'description': '(GitHub Only) If specified, the name of the GitHub branch to build.'
|
'description': '(SCM only) If specified, the name of the branch to build.'
|
||||||
},
|
},
|
||||||
'commit_sha': {
|
'commit_sha': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
""" Manage the current user. """
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
@ -182,11 +184,17 @@ class User(ApiResource):
|
||||||
},
|
},
|
||||||
'organizations': {
|
'organizations': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'description': 'Information about the organizations in which the user is a member'
|
'description': 'Information about the organizations in which the user is a member',
|
||||||
|
'items': {
|
||||||
|
'type': 'object'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'logins': {
|
'logins': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'description': 'The list of external login providers against which the user has authenticated'
|
'description': 'The list of external login providers against which the user has authenticated',
|
||||||
|
'items': {
|
||||||
|
'type': 'object'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'can_create_repo': {
|
'can_create_repo': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
|
@ -794,10 +802,10 @@ class StarredRepositoryList(ApiResource):
|
||||||
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
|
||||||
class StarredRepository(RepositoryParamResource):
|
class StarredRepository(RepositoryParamResource):
|
||||||
""" Operations for managing a specific starred repository. """
|
""" Operations for managing a specific starred repository. """
|
||||||
|
|
||||||
@nickname('deleteStar')
|
@nickname('deleteStar')
|
||||||
@require_user_admin
|
@require_user_admin
|
||||||
def delete(self, namespace, repository):
|
def delete(self, namespace, repository):
|
||||||
|
""" Removes a star from a repository. """
|
||||||
user = get_authenticated_user()
|
user = get_authenticated_user()
|
||||||
repo = model.get_repository(namespace, repository)
|
repo = model.get_repository(namespace, repository)
|
||||||
|
|
||||||
|
|
Reference in a new issue