-
Ambrus Simon authoredAmbrus Simon authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
api.py 12.65 KiB
import webapp2
import webapp2_extras.routes
from .centralclient import CentralClient
from .download import Download
from .handlers.collectionshandler import CollectionsHandler
from .handlers.confighandler import Config, Version
from .handlers.containerhandler import ContainerHandler
from .handlers.devicehandler import DeviceHandler
from .handlers.grouphandler import GroupHandler
from .handlers.listhandler import AnalysesHandler, ListHandler, FileListHandler, NotesListHandler, PermissionsListHandler, TagsListHandler
from .handlers.reporthandler import ReportHandler
from .handlers.resolvehandler import ResolveHandler
from .handlers.roothandler import RootHandler
from .handlers.schemahandler import SchemaHandler
from .handlers.searchhandler import SearchHandler
from .handlers.userhandler import UserHandler
from .jobs.handlers import BatchHandler, JobsHandler, JobHandler, GearsHandler, GearHandler, RulesHandler
from .upload import Upload
from .web.base import RequestHandler
from . import config
log = config.log
routing_regexes = {
# Group ID: 2-32 characters of form [0-9a-z.@_-]. Start and ends with alphanum.
'gid': '[0-9a-z][0-9a-z.@_-]{0,30}[0-9a-z]',
# Container ID: 24-character hex
'cid': '[0-9a-f]{24}',
# Site ID: <= 24-character alphanum
'sid': '[0-9a-z_]{0,24}',
# User ID: any length, [0-9a-z.@_-]
'uid': '[0-9a-zA-Z.@_-]*',
# Container name
'cname': 'projects|sessions|acquisitions|collections',
# Tag name
'tag': '[^/]{1,32}',
# Filename
'fname': '[^/]+',
# Note ID
'nid': '[0-9a-f]{24}',
# Schema path
'schema': r'[^/.]{3,60}/[^/.]{3,60}\.json'
}
def route(path, target, h=None, m=None, name=None):
# https://webapp2.readthedocs.io/en/latest/api/webapp2.html#webapp2.Route
return webapp2.Route(
# re.compile(path)
path.format(**routing_regexes),
target,
handler_method=h,
methods=m,
name=name
)
def prefix(path, routes):
# https://webapp2.readthedocs.io/en/latest/api/webapp2_extras/routes.html#webapp2_extras.routes.PathPrefixRoute
return webapp2_extras.routes.PathPrefixRoute(
path.format(**routing_regexes),
routes
)
endpoints = [
route('/api', RootHandler),
prefix('/api', [
# System configuration
route('/config', Config, m=['GET']),
route('/config.js', Config, h='get_js', m=['GET']),
route('/version', Version, m=['GET']),
# General-purpose upload & download
route('/download', Download, h='download', m=['GET', 'POST']),
route('/upload/<strategy:label|uid|uid-match>', Upload, h='upload', m=['POST']),
route('/clean-packfiles', Upload, h='clean_packfile_tokens', m=['POST']),
route('/engine', Upload, h='engine', m=['POST']),
# Top-level endpoints
route('/login', RequestHandler, h='log_in', m=['POST']),
route('/logout', RequestHandler, h='log_out', m=['POST']),
route('/resolve', ResolveHandler, h='resolve', m=['POST']),
route('/schemas/<schema:{schema}>', SchemaHandler, m=['GET']),
route('/report/<report_type:site|project>', ReportHandler, m=['GET']),
# Search
route('/search', SearchHandler, h='advanced_search', m=['POST']),
route('/search/field', SearchHandler, h='get_terms_for_field', m=['POST']),
route('/search/files', SearchHandler, h='get_datatree', m=['GET']),
route('/search/<cont_name:{cname}>', SearchHandler, m=['GET']),
# Users
route( '/users', UserHandler, h='get_all', m=['GET']),
route( '/users', UserHandler, m=['POST']),
prefix('/users', [
route('/self', UserHandler, h='self', m=['GET']),
route('/self/avatar', UserHandler, h='self_avatar', m=['GET']),
route('/self/key', UserHandler, h='generate_api_key',m=['POST']),
route('/<_id:{uid}>', UserHandler),
route('/<uid:{uid}>/groups', GroupHandler, h='get_all', m=['GET']),
route('/<uid:{uid}>/avatar', UserHandler, h='avatar', m=['GET']),
route('/<uid:{uid}>/reset-registration', UserHandler, h='reset_registration', m=['POST']),
route('/<uid:{uid}>/<cont_name:{cname}>', ContainerHandler, h='get_all_for_user', m=['GET']),
]),
# Jobs & gears
route( '/jobs', JobsHandler),
prefix('/jobs', [
route('/next', JobsHandler, h='next', m=['GET']),
route('/stats', JobsHandler, h='stats', m=['GET']),
route('/reap', JobsHandler, h='reap_stale', m=['POST']),
route('/add', JobsHandler, h='add', m=['POST']),
route('/<:[^/]+>', JobHandler),
route('/<:[^/]+>/config.json', JobHandler, h='get_config'),
route('/<:[^/]+>/retry', JobHandler, h='retry', m=['POST']),
]),
route('/gears', GearsHandler),
prefix('/gears', [
route('/<:[^/]+>', GearHandler),
route('/<:[^/]+>/invocation', GearHandler, h='get_invocation'),
route('/<:[^/]+>/suggest/<:[^/]+>/<:[^/]+>', GearHandler, h='suggest'),
]),
route('/rules', RulesHandler),
# Batch jobs
route('/batch', BatchHandler, h='get_all', m=['GET']),
route('/batch', BatchHandler, m=['POST']),
prefix('/batch', [
route('/<:[^/]+>', BatchHandler, h='get', m=['GET']),
route('/<:[^/]+>/run', BatchHandler, h='run', m=['POST']),
route('/<:[^/]+>/cancel', BatchHandler, h='cancel', m=['POST']),
route('/<:[^/]+>/jobs', BatchHandler, h='get_jobs', m=['GET'])
]),
# Devices
route( '/devices', DeviceHandler, h='get_all', m=['GET']),
route( '/devices', DeviceHandler, m=['POST']),
prefix('/devices', [
route('/status', DeviceHandler, h='get_status', m=['GET']),
route('/self', DeviceHandler, h='get_self', m=['GET']),
route('/<device_id:[^/]+>', DeviceHandler, m=['GET']),
]),
# Groups
route('/groups', GroupHandler, h='get_all', m=['GET']),
route('/groups', GroupHandler, m=['POST']),
route('/groups/<_id:{gid}>', GroupHandler, m=['GET', 'DELETE', 'PUT']),
prefix('/<cont_name:groups>', [
route('/<cid:{gid}>/<list_name:roles>', ListHandler, m=['POST']),
route('/<cid:{gid}>/<list_name:roles>/<site:{sid}>/<_id:{uid}>', ListHandler, m=['GET', 'PUT', 'DELETE']),
route('/<cid:{gid}>/<list_name:tags>', TagsListHandler, m=['POST']),
route('/<cid:{gid}>/<list_name:tags>/<value:{tag}>', TagsListHandler, m=['GET', 'PUT', 'DELETE']),
]),
# Projects
prefix('/projects', [
route('/groups', ContainerHandler, h='get_groups_with_project', m=['GET']),
route('/recalc', ContainerHandler, h='calculate_project_compliance', m=['POST']),
route('/<cid:{cid}>/template', ContainerHandler, h='set_project_template', m=['POST']),
route('/<cid:{cid}>/template', ContainerHandler, h='delete_project_template', m=['DELETE']),
route('/<cid:{cid}>/recalc', ContainerHandler, h='calculate_project_compliance', m=['POST']),
]),
# Sessions
prefix('/sessions', [
route('/<cid:{cid}>/jobs', ContainerHandler, h='get_jobs', m=['GET']),
route('/<cid:{cid}>/subject', ContainerHandler, h='get_subject', m=['GET']),
]),
# Collections
route( '/collections', CollectionsHandler, h='get_all', m=['GET']),
route( '/collections', CollectionsHandler, m=['POST']),
prefix('/collections', [
route('/curators', CollectionsHandler, h='curators', m=['GET']),
route('/<cid:{cid}>', CollectionsHandler, m=['GET', 'PUT', 'DELETE']),
route('/<cid:{cid}>/sessions', CollectionsHandler, h='get_sessions', m=['GET']),
route('/<cid:{cid}>/acquisitions', CollectionsHandler, h='get_acquisitions', m=['GET']),
]),
# Collections / Projects
prefix('/<cont_name:collections|projects>', [
prefix('/<cid:{cid}>', [
route('/<list_name:permissions>', PermissionsListHandler, m=['POST']),
route('/<list_name:permissions>/<site:{sid}>/<_id:{uid}>', PermissionsListHandler, m=['GET', 'PUT', 'DELETE']),
]),
]),
# Containers
route('/<cont_name:{cname}>', ContainerHandler, name='cont_list', h='get_all', m=['GET']),
route('/<cont_name:{cname}>', ContainerHandler, m=['POST']),
prefix('/<cont_name:{cname}>', [
route('/<cid:{cid}>', ContainerHandler, m=['GET','PUT','DELETE']),
prefix('/<cid:{cid}>', [
route('/<list_name:tags>', TagsListHandler, m=['POST']),
route('/<list_name:tags>/<value:{tag}>', TagsListHandler, m=['GET', 'PUT', 'DELETE']),
route('/packfile-start', FileListHandler, h='packfile_start', m=['POST']),
route('/packfile', FileListHandler, h='packfile', m=['POST']),
route('/packfile-end', FileListHandler, h='packfile_end'),
route('/<list_name:files>', FileListHandler, m=['POST']),
route('/<list_name:files>/<name:{fname}>', FileListHandler, m=['GET', 'DELETE']),
route('/<list_name:files>/<name:{fname}>/info', FileListHandler, h='get_info', m=['GET']),
route('/<list_name:analyses>', AnalysesHandler, m=['POST']),
# Could be in a prefix. Had weird syntax highlighting issues so leaving for another day
route('/<list_name:analyses>/<_id:{cid}>', AnalysesHandler, m=['GET', 'DELETE']),
route('/<list_name:analyses>/<_id:{cid}>/files', AnalysesHandler, h='download', m=['GET']),
route('/<list_name:analyses>/<_id:{cid}>/files/<name:{fname}>', AnalysesHandler, h='download', m=['GET']),
route('/<list_name:analyses>/<_id:{cid}>/notes', AnalysesHandler, h='add_note', m=['POST']),
route('/<list_name:analyses>/<_id:{cid}>/notes/<note_id:{cid}>', AnalysesHandler, h='delete_note', m=['DELETE']),
route('/<list_name:notes>', NotesListHandler, m=['POST']),
route('/<list_name:notes>/<_id:{nid}>', NotesListHandler, name='notes', m=['GET', 'PUT', 'DELETE']),
])
]),
# Misc (to be cleaned up later)
route('/<par_cont_name:groups>/<par_id:{gid}>/<cont_name:projects>', ContainerHandler, h='get_all', m=['GET']),
route('/<par_cont_name:{cname}>/<par_id:{cid}>/<cont_name:{cname}>', ContainerHandler, h='get_all', m=['GET']),
# Multi - site
route('/sites', CentralClient, h='sites', m=['GET']),
route('/register', CentralClient, h='register', m=['POST']),
]),
]