aboutsummaryrefslogtreecommitdiff
path: root/src/web/views/api/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/web/views/api/common.py')
-rw-r--r--src/web/views/api/common.py218
1 files changed, 0 insertions, 218 deletions
diff --git a/src/web/views/api/common.py b/src/web/views/api/common.py
deleted file mode 100644
index ace6ba3a..00000000
--- a/src/web/views/api/common.py
+++ /dev/null
@@ -1,218 +0,0 @@
-"""For a given resources, classes in the module intend to create the following
-routes :
- GET resource/<id>
- -> to retrieve one
- POST resource
- -> to create one
- PUT resource/<id>
- -> to update one
- DELETE resource/<id>
- -> to delete one
-
- GET resources
- -> to retrieve several
- POST resources
- -> to create several
- PUT resources
- -> to update several
- DELETE resources
- -> to delete several
-"""
-import logging
-from functools import wraps
-from werkzeug.exceptions import Unauthorized, BadRequest, Forbidden, NotFound
-from flask import request
-from flask.ext.restful import Resource, reqparse
-from flask.ext.login import current_user
-
-from web.views.common import admin_permission, api_permission, \
- login_user_bundle, jsonify
-from web.controllers import UserController
-
-logger = logging.getLogger(__name__)
-
-
-def authenticate(func):
- @wraps(func)
- def wrapper(*args, **kwargs):
- if request.authorization:
- ucontr = UserController()
- try:
- user = ucontr.get(login=request.authorization.username)
- except NotFound:
- raise Forbidden("Couldn't authenticate your user")
- if not ucontr.check_password(user, request.authorization.password):
- raise Forbidden("Couldn't authenticate your user")
- if not user.is_active:
- raise Forbidden("User is desactivated")
- login_user_bundle(user)
- if current_user.is_authenticated:
- return func(*args, **kwargs)
- raise Unauthorized()
- return wrapper
-
-
-class PyAggAbstractResource(Resource):
- method_decorators = [authenticate, jsonify]
- controller_cls = None
- attrs = None
-
- @property
- def controller(self):
- if admin_permission.can():
- return self.controller_cls()
- return self.controller_cls(current_user.id)
-
- def reqparse_args(self, right, req=None, strict=False, default=True,
- allow_empty=False):
- """
- strict: bool
- if True will throw 400 error if args are defined and not in request
- default: bool
- if True, won't return defaults
- args: dict
- the args to parse, if None, self.attrs will be used
- """
- try:
- in_values = req.json if req else (request.json or {})
- if not in_values and allow_empty:
- return {}
- except BadRequest:
- if allow_empty:
- return {}
- raise
- parser = reqparse.RequestParser()
- if self.attrs is not None:
- attrs = self.attrs
- elif admin_permission.can():
- attrs = self.controller_cls._get_attrs_desc('admin')
- elif api_permission.can():
- attrs = self.controller_cls._get_attrs_desc('api', right)
- else:
- attrs = self.controller_cls._get_attrs_desc('base', right)
- assert attrs, "No defined attrs for %s" % self.__class__.__name__
-
- for attr_name, attr in attrs.items():
- if not default and attr_name not in in_values:
- continue
- else:
- parser.add_argument(attr_name, location='json', **attr)
- return parser.parse_args(req=req, strict=strict)
-
-
-class PyAggResourceNew(PyAggAbstractResource):
-
- @api_permission.require(http_exception=403)
- def post(self):
- """Create a single new object"""
- return self.controller.create(**self.reqparse_args(right='write')), 201
-
-
-class PyAggResourceExisting(PyAggAbstractResource):
-
- def get(self, obj_id=None):
- """Retreive a single object"""
- return self.controller.get(id=obj_id)
-
- def put(self, obj_id=None):
- """update an object, new attrs should be passed in the payload"""
- args = self.reqparse_args(right='write', default=False)
- if not args:
- raise BadRequest()
- return self.controller.update({'id': obj_id}, args), 200
-
- def delete(self, obj_id=None):
- """delete a object"""
- self.controller.delete(obj_id)
- return None, 204
-
-
-class PyAggResourceMulti(PyAggAbstractResource):
-
- def get(self):
- """retrieve several objects. filters can be set in the payload on the
- different fields of the object, and a limit can be set in there as well
- """
- try:
- limit = request.json.pop('limit', 10)
- order_by = request.json.pop('order_by', None)
- args = self.reqparse_args(right='read', default=False)
- except BadRequest:
- limit, order_by, args = 10, None, {}
- query = self.controller.read(**args)
- if order_by:
- query = query.order_by(order_by)
- if limit:
- query = query.limit(limit)
- return [res for res in query]
-
- @api_permission.require(http_exception=403)
- def post(self):
- """creating several objects. payload should be:
- >>> payload
- [{attr1: val1, attr2: val2}, {attr1: val1, attr2: val2}]
- """
- assert 'application/json' in request.headers.get('Content-Type')
- status, fail_count, results = 200, 0, []
-
- class Proxy:
- pass
- for attrs in request.json:
- try:
- Proxy.json = attrs
- args = self.reqparse_args('write', req=Proxy, default=False)
- obj = self.controller.create(**args)
- results.append(obj)
- except Exception as error:
- fail_count += 1
- results.append(str(error))
- if fail_count == len(results): # all failed => 500
- status = 500
- elif fail_count: # some failed => 206
- status = 206
- return results, status
-
- def put(self):
- """updating several objects. payload should be:
- >>> payload
- [[obj_id1, {attr1: val1, attr2: val2}]
- [obj_id2, {attr1: val1, attr2: val2}]]
- """
- assert 'application/json' in request.headers.get('Content-Type')
- status, results = 200, []
-
- class Proxy:
- pass
- for obj_id, attrs in request.json:
- try:
- Proxy.json = attrs
- args = self.reqparse_args('write', req=Proxy, default=False)
- result = self.controller.update({'id': obj_id}, args)
- if result:
- results.append('ok')
- else:
- results.append('nok')
- except Exception as error:
- results.append(str(error))
- if results.count('ok') == 0: # all failed => 500
- status = 500
- elif results.count('ok') != len(results): # some failed => 206
- status = 206
- return results, status
-
- def delete(self):
- """will delete several objects,
- a list of their ids should be in the payload"""
- assert 'application/json' in request.headers.get('Content-Type')
- status, results = 204, []
- for obj_id in request.json:
- try:
- self.controller.delete(obj_id)
- results.append('ok')
- except Exception as error:
- status = 206
- results.append(error)
- # if no operation succeded, it's not partial anymore, returning err 500
- if status == 206 and results.count('ok') == 0:
- status = 500
- return results, status
bgstack15