web: Move path parameter validation to resources
This commit is contained in:
parent
e25b3d7c4b
commit
36dd519b34
2 changed files with 36 additions and 32 deletions
|
|
@ -36,7 +36,7 @@ from .filters.utils import FilterContext
|
|||
from .autocomplete import AutocompleteResource
|
||||
from .api import ApiIdentGetterResource
|
||||
from .query import get_query
|
||||
from .web_utils import FamilyConverter, ProjectConverter, VersionConverter, IdentConverter, FamilyConverter
|
||||
from .web_utils import ProjectConverter, IdentConverter, validate_version, validate_project, validate_ident
|
||||
|
||||
VERSION_CACHE_DURATION_SECONDS = 2 * 60 # 2 minutes
|
||||
|
||||
|
|
@ -56,6 +56,21 @@ def get_error_page(ctx, title, details=None):
|
|||
template = ctx.jinja_env.get_template('error.html')
|
||||
return template.render(template_ctx)
|
||||
|
||||
def validate_project_and_version(ctx, project, version):
|
||||
project = validate_project(parse.unquote(project))
|
||||
if project is None:
|
||||
raise falcon.HTTPBadRequest('Error', 'Invalid project name')
|
||||
|
||||
query = get_query(ctx.config.project_dir, project)
|
||||
if not query:
|
||||
raise falcon.HTTPNotFound('Error', 'Unknown project')
|
||||
|
||||
version = validate_version(parse.unquote(version))
|
||||
if version is None:
|
||||
raise falcon.HTTPBadRequest('Error', 'Invalid version name')
|
||||
|
||||
return project, version, query
|
||||
|
||||
|
||||
# Returns base url of source pages
|
||||
# project and version assumed unquoted
|
||||
|
|
@ -73,6 +88,8 @@ def stringify_source_path(project, version, path):
|
|||
# Path parameters are asssumed to be unquoted by converters
|
||||
class SourceResource:
|
||||
def on_get(self, req, resp, project, version, path):
|
||||
project, version, query = validate_project_and_version(req.context, project, version)
|
||||
|
||||
if not path.startswith('/') and len(path) != 0:
|
||||
path = f'/{ path }'
|
||||
|
||||
|
|
@ -81,10 +98,6 @@ class SourceResource:
|
|||
resp.location = stringify_source_path(project, version, path)
|
||||
return
|
||||
|
||||
query = get_query(req.context.config.project_dir, project)
|
||||
if not query:
|
||||
raise falcon.HTTPNotFound('Error', 'Unknown project')
|
||||
|
||||
# Check if path contains only allowed characters
|
||||
if not search('^[A-Za-z0-9_/.,+-]*$', path):
|
||||
raise falcon.HTTPBadRequest('Error', 'Path contains characters that are not allowed')
|
||||
|
|
@ -129,6 +142,8 @@ def stringify_ident_path(project, version, family, ident):
|
|||
# Handles redirect on a POST to ident resource
|
||||
class IdentPostRedirectResource:
|
||||
def on_post(self, req, resp, project, version, family=None, ident=None):
|
||||
project, version, _ = validate_project_and_version(req.context, project, version)
|
||||
|
||||
form = req.get_media()
|
||||
post_ident = form.get('i')
|
||||
post_family = form.get('f')
|
||||
|
|
@ -148,9 +163,17 @@ class IdentPostRedirectResource:
|
|||
# Path parameters are asssumed to be unquoted by converters
|
||||
class IdentResource(IdentPostRedirectResource):
|
||||
def on_get(self, req, resp, project, version, family, ident):
|
||||
query = get_query(req.context.config.project_dir, project)
|
||||
if not query:
|
||||
raise falcon.HTTPNotFound('Error', 'Unknown project')
|
||||
project, version, query = validate_project_and_version(req.context, project, version)
|
||||
|
||||
family = parse.unquote(family)
|
||||
if not validFamily(family):
|
||||
family = 'C'
|
||||
|
||||
validated_ident = validate_ident(ident)
|
||||
if validated_ident is None:
|
||||
raise falcon.HTTPBadRequest('Error', 'Invalid identifier')
|
||||
|
||||
ident = validated_ident
|
||||
|
||||
if version == 'latest':
|
||||
version = parse.quote(query.query('latest'))
|
||||
|
|
@ -609,17 +632,15 @@ def get_application():
|
|||
])
|
||||
|
||||
app.router_options.converters['project'] = ProjectConverter
|
||||
app.router_options.converters['version'] = VersionConverter
|
||||
app.router_options.converters['ident'] = IdentConverter
|
||||
app.router_options.converters['family'] = FamilyConverter
|
||||
|
||||
app.set_error_serializer(error_serializer)
|
||||
|
||||
app.add_route('/{project:project}/{version:version}/source/{path:path}', SourceResource())
|
||||
app.add_route('/{project:project}/{version:version}/source', SourceWithoutPathResource())
|
||||
app.add_route('/{project:project}/{version:version}/ident', IdentPostRedirectResource())
|
||||
app.add_route('/{project:project}/{version:version}/ident/{ident:ident}', IdentWithoutFamilyResource())
|
||||
app.add_route('/{project:project}/{version:version}/{family:family}/ident/{ident:ident}', IdentResource())
|
||||
app.add_route('/{project}/{version}/source/{path:path}', SourceResource())
|
||||
app.add_route('/{project}/{version}/source', SourceWithoutPathResource())
|
||||
app.add_route('/{project}/{version}/ident', IdentPostRedirectResource())
|
||||
app.add_route('/{project}/{version}/ident/{ident}', IdentWithoutFamilyResource())
|
||||
app.add_route('/{project}/{version}/{family}/ident/{ident}', IdentResource())
|
||||
|
||||
app.add_route('/acp', AutocompleteResource())
|
||||
app.add_route('/api/ident/{project:project}/{ident:ident}', ApiIdentGetterResource())
|
||||
|
|
|
|||
|
|
@ -21,15 +21,6 @@ def validate_version(version):
|
|||
if version is not None and re.match(r'^[a-zA-Z0-9_.,:/-]+$', version):
|
||||
return version.strip()
|
||||
|
||||
# Validates and unquotes version parameter
|
||||
class VersionConverter(falcon.routing.BaseConverter):
|
||||
def convert(self, value: str):
|
||||
value = parse.unquote(value)
|
||||
version = validate_version(value)
|
||||
if version is None:
|
||||
raise falcon.HTTPBadRequest('Error', 'Invalid version name')
|
||||
return version
|
||||
|
||||
def validate_ident(ident):
|
||||
if ident is not None and re.match(r'^[A-Za-z0-9_,.+?#-]+$', ident):
|
||||
return ident.strip()
|
||||
|
|
@ -40,11 +31,3 @@ class IdentConverter(falcon.routing.BaseConverter):
|
|||
value = parse.unquote(value)
|
||||
return validate_ident(value)
|
||||
|
||||
# Returns default family if family is not valid
|
||||
class FamilyConverter(falcon.routing.BaseConverter):
|
||||
def convert(self, value: str):
|
||||
value = parse.unquote(value)
|
||||
if not validFamily(value):
|
||||
value = 'C'
|
||||
return value
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue