144 lines
5.2 KiB
Python
144 lines
5.2 KiB
Python
#
|
|
# Copyright 2012 New Dream Network, LLC (DreamHost)
|
|
# Copyright 2013 IBM Corp.
|
|
# Copyright 2013 eNovance <licensing@enovance.com>
|
|
# Copyright Ericsson AB 2013. All rights reserved
|
|
# Copyright 2014 Hewlett-Packard Company
|
|
# Copyright 2015 Huawei Technologies Co., Ltd.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import functools
|
|
import pecan
|
|
import wsme
|
|
|
|
from panko.api.controllers.v2 import base
|
|
from panko.api import rbac
|
|
|
|
|
|
def get_auth_project(on_behalf_of=None):
|
|
auth_project = rbac.get_limited_to_project(pecan.request.headers)
|
|
created_by = pecan.request.headers.get('X-Project-Id')
|
|
is_admin = auth_project is None
|
|
|
|
if is_admin and on_behalf_of != created_by:
|
|
auth_project = on_behalf_of
|
|
return auth_project
|
|
|
|
|
|
# TODO(fabiog): this decorator should disappear and have a more unified
|
|
# way of controlling access and scope. Before messing with this, though
|
|
# I feel this file should be re-factored in smaller chunks one for each
|
|
# controller (e.g. meters and so on ...). Right now its size is
|
|
# overwhelming.
|
|
def requires_admin(func):
|
|
|
|
@functools.wraps(func)
|
|
def wrapped(*args, **kwargs):
|
|
usr_limit, proj_limit = rbac.get_limited_to(pecan.request.headers)
|
|
# If User and Project are None, you have full access.
|
|
if usr_limit and proj_limit:
|
|
# since this decorator get's called out of wsme context
|
|
# raising exception results internal error so call abort
|
|
# for handling the error
|
|
ex = base.ProjectNotAuthorized(proj_limit)
|
|
pecan.core.abort(status_code=ex.code, detail=ex.msg)
|
|
return func(*args, **kwargs)
|
|
|
|
return wrapped
|
|
|
|
|
|
def requires_context(func):
|
|
|
|
@functools.wraps(func)
|
|
def wrapped(*args, **kwargs):
|
|
req_usr = pecan.request.headers.get('X-User-Id')
|
|
proj_usr = pecan.request.headers.get('X-Project-Id')
|
|
if ((not req_usr) or (not proj_usr)):
|
|
pecan.core.abort(status_code=403,
|
|
detail='RBAC Authorization Failed')
|
|
return func(*args, **kwargs)
|
|
|
|
return wrapped
|
|
|
|
|
|
def set_pagination_options(sort, limit, marker, api_model):
|
|
"""Sets the options for pagination specifying query options
|
|
|
|
Arguments:
|
|
sort -- List of sorting criteria. Each sorting option has to format
|
|
<sort key>:<sort direction>
|
|
|
|
Valid sort keys: message_id, generated
|
|
(SUPPORT_SORT_KEYS in panko/event/storage/models.py)
|
|
Valid sort directions: asc (ascending), desc (descending)
|
|
(SUPPORT_DIRS in panko/event/storage/models.py)
|
|
This defaults to asc if unspecified
|
|
(DEFAULT_DIR in panko/event/storage/models.py)
|
|
|
|
impl_sqlalchemy.py:
|
|
(see _get_pagination_query)
|
|
If sort list is empty, this defaults to
|
|
['generated:asc', 'message_id:asc']
|
|
(DEFAULT_SORT in panko/event/storage/models.py)
|
|
|
|
limit -- Integer specifying maximum number of values to return
|
|
|
|
If unspecified, this defaults to
|
|
pecan.request.cfg.api.default_api_return_limit
|
|
|
|
marker -- If specified, assumed to be an integer and assumed to be the
|
|
message id of the last object on the previous page of the results
|
|
|
|
api_model -- Specifies the class implementing the api model to use for
|
|
this pagination. The class is expected to provide the
|
|
following members:
|
|
|
|
SUPPORT_DIRS
|
|
SUPPORT_SORT_KEYS
|
|
DEFAULT_DIR
|
|
DEFAULT_SORT
|
|
PRIMARY_KEY
|
|
"""
|
|
if limit and limit <= 0:
|
|
raise wsme.exc.InvalidInput('limit', limit,
|
|
'the limit should be a positive integer.')
|
|
if not limit:
|
|
limit = pecan.request.cfg.api.default_api_return_limit
|
|
|
|
sorts = list()
|
|
for s in sort or []:
|
|
sort_key, __, sort_dir = s.partition(':')
|
|
if sort_key not in api_model.SUPPORT_SORT_KEYS:
|
|
raise wsme.exc.InvalidInput(
|
|
'sort', s, "the sort parameter should be a pair of sort "
|
|
"key and sort dir combined with ':', or only"
|
|
" sort key specified and sort dir will be default "
|
|
"'%s', the supported sort keys are: %s" %
|
|
(str(api_model.DEFAULT_DIR),
|
|
str(api_model.SUPPORT_SORT_KEYS)))
|
|
if sort_dir and sort_dir not in api_model.SUPPORT_DIRS:
|
|
raise wsme.exc.InvalidInput(
|
|
'sort direction', s,
|
|
"the sort parameter should be a pair of sort "
|
|
"key and sort dir combined with ':', or only"
|
|
" sort key specified and sort dir will be default "
|
|
"'%s', the supported sort directions are: %s" %
|
|
(str(api_model.DEFAULT_DIR),
|
|
str(api_model.SUPPORT_DIRS)))
|
|
sorts.append((sort_key, sort_dir or api_model.DEFAULT_DIR))
|
|
|
|
return {'limit': limit,
|
|
'marker': marker,
|
|
'sort': sorts}
|