|
|
|
@ -5,7 +5,7 @@ import mongoengine |
|
|
|
|
from flask import jsonify, request |
|
|
|
|
from flask_views.base import View |
|
|
|
|
from mongoengine import ValidationError, DoesNotExist, InvalidQueryError |
|
|
|
|
from werkzeug.exceptions import Unauthorized, NotFound |
|
|
|
|
from werkzeug.exceptions import Unauthorized, NotFound, Forbidden |
|
|
|
|
|
|
|
|
|
from restapi.resource import Resource |
|
|
|
|
|
|
|
|
@ -14,7 +14,7 @@ class ApiView(View): |
|
|
|
|
model = None |
|
|
|
|
authentication_methods = [] |
|
|
|
|
|
|
|
|
|
def __init__(self, model,authentication_methods): |
|
|
|
|
def __init__(self, model, authentication_methods): |
|
|
|
|
self.start = time.time() |
|
|
|
|
self.model = model |
|
|
|
|
self.resource = Resource(self.model) |
|
|
|
@ -28,22 +28,28 @@ class ApiView(View): |
|
|
|
|
|
|
|
|
|
def _dispatch_request(self, *args, **kwargs): |
|
|
|
|
authorized = True if len(self.authentication_methods) == 0 else False |
|
|
|
|
autherror = None |
|
|
|
|
for authentication_method in self.authentication_methods: |
|
|
|
|
if authentication_method().authorized(): |
|
|
|
|
authclass = authentication_method() |
|
|
|
|
if authclass.authorized(): |
|
|
|
|
authorized = True |
|
|
|
|
else: |
|
|
|
|
autherror = authclass.get_error() |
|
|
|
|
if not authorized: |
|
|
|
|
return {'error': 'Unauthorized'}, '401 Unauthorized' |
|
|
|
|
return {'error': 'Unauthorized', "message": str(autherror), "status": False}, '401 Unauthorized' |
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
return super(ApiView, self).dispatch_request(*args, **kwargs) |
|
|
|
|
except mongoengine.queryset.DoesNotExist as e: |
|
|
|
|
return {'error': 'Empty query: ' + str(e)}, '404 Not Found' |
|
|
|
|
return {'error': 'empty_query', "message": str(e), "status": False}, '404 Not Found' |
|
|
|
|
except ValidationError as e: |
|
|
|
|
return e.args[0], '400 Bad Request' |
|
|
|
|
return {"error": "bad_request", "message": e.args, "status": False}, '400 Bad Request' |
|
|
|
|
except Unauthorized: |
|
|
|
|
return {'error': 'Unauthorized'}, '401 Unauthorized' |
|
|
|
|
return {'error': 'Unauthorized', "status": False}, '401 Unauthorized' |
|
|
|
|
except Forbidden: |
|
|
|
|
return {'error': 'Access_Denied', "status": False}, '403 Access Denied' |
|
|
|
|
except NotFound as e: |
|
|
|
|
return {'error': str(e)}, '404 Not Found' |
|
|
|
|
return {'error': str(e), "status": False}, '404 Not Found' |
|
|
|
|
|
|
|
|
|
def get(self, *args, **kwargs): |
|
|
|
|
""" |
|
|
|
@ -55,7 +61,8 @@ class ApiView(View): |
|
|
|
|
if 'pk' in kwargs: |
|
|
|
|
try: |
|
|
|
|
qs = self.resource.to_qs(pk=kwargs.get('pk')) |
|
|
|
|
count, data = self.resource.to_json(pk=kwargs.get('pk')) |
|
|
|
|
qs = self.has_read_permission(qs) |
|
|
|
|
count, data = self.resource.to_json(pk=kwargs.get('pk'), qs=qs) |
|
|
|
|
response = { |
|
|
|
|
'response': data, |
|
|
|
|
'status': True, |
|
|
|
@ -73,7 +80,9 @@ class ApiView(View): |
|
|
|
|
if "query" in request.args and self.model._meta.get('can_query'): |
|
|
|
|
self.resource.external_query(json.loads(request.args.get('query'))) |
|
|
|
|
qs = self.resource.to_qs() |
|
|
|
|
count, data = self.resource.to_json() |
|
|
|
|
qs = self.has_read_permission(qs) |
|
|
|
|
|
|
|
|
|
count, data = self.resource.to_json(qs=qs) |
|
|
|
|
response = { |
|
|
|
|
'response': data, |
|
|
|
|
'info': { |
|
|
|
@ -89,8 +98,6 @@ class ApiView(View): |
|
|
|
|
|
|
|
|
|
def post(self, *args, **kwargs): |
|
|
|
|
""" |
|
|
|
|
TODO: check permissions |
|
|
|
|
|
|
|
|
|
:param args: |
|
|
|
|
:param kwargs: |
|
|
|
|
:return: |
|
|
|
@ -109,8 +116,20 @@ class ApiView(View): |
|
|
|
|
'status': False, |
|
|
|
|
'errors': str(e) |
|
|
|
|
}), 400 |
|
|
|
|
resp, obj = self.has_add_permission(item) |
|
|
|
|
from flask import current_app |
|
|
|
|
|
|
|
|
|
if resp: |
|
|
|
|
try: |
|
|
|
|
item = obj |
|
|
|
|
data = item.save() |
|
|
|
|
return self.get(pk=data.id, code=201) |
|
|
|
|
except Exception as e: |
|
|
|
|
current_app.logger.error(e) |
|
|
|
|
current_app.logger.info(item.pk) |
|
|
|
|
|
|
|
|
|
return self.get(pk=item.pk, code=201) |
|
|
|
|
else: |
|
|
|
|
raise Forbidden() |
|
|
|
|
|
|
|
|
|
def put(self, *args, **kwargs): |
|
|
|
|
""" |
|
|
|
@ -127,7 +146,15 @@ class ApiView(View): |
|
|
|
|
}), 403 |
|
|
|
|
else: |
|
|
|
|
try: |
|
|
|
|
self.model.objects(id=kwargs.get('pk')).update(**request.json) |
|
|
|
|
item = self.model.objects.get(id=kwargs.get('pk')) |
|
|
|
|
updata = request.json |
|
|
|
|
resp, obj = self.has_change_permission(item, updata) |
|
|
|
|
from flask import current_app |
|
|
|
|
if resp: |
|
|
|
|
updata = obj |
|
|
|
|
item.update(**updata) |
|
|
|
|
else: |
|
|
|
|
raise Forbidden() |
|
|
|
|
return self.get(pk=kwargs.get('pk')) |
|
|
|
|
except ValidationError as v: |
|
|
|
|
print(v.__dict__) |
|
|
|
@ -141,16 +168,31 @@ class ApiView(View): |
|
|
|
|
'errors': str(e) |
|
|
|
|
}), 400 |
|
|
|
|
|
|
|
|
|
def has_read_permission(self, request, qs): |
|
|
|
|
def has_read_permission(self, qs): |
|
|
|
|
for authentication_method in self.authentication_methods: |
|
|
|
|
authclass = authentication_method() |
|
|
|
|
qs = authclass.has_model_read_permission(qs) |
|
|
|
|
return qs |
|
|
|
|
|
|
|
|
|
def has_add_permission(self, request, obj): |
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
def has_change_permission(self, request, obj): |
|
|
|
|
return True |
|
|
|
|
def has_add_permission(self, obj): |
|
|
|
|
has_ret = False |
|
|
|
|
for authentication_method in self.authentication_methods: |
|
|
|
|
authclass = authentication_method() |
|
|
|
|
resp, obj = authclass.has_model_write_permission(obj) |
|
|
|
|
if resp: |
|
|
|
|
has_ret = True |
|
|
|
|
return has_ret, obj |
|
|
|
|
|
|
|
|
|
def has_change_permission(self, obj, update): |
|
|
|
|
has_ret = False |
|
|
|
|
for authentication_method in self.authentication_methods: |
|
|
|
|
authclass = authentication_method() |
|
|
|
|
resp, obj = authclass.has_model_update_permission(obj, update) |
|
|
|
|
if resp: |
|
|
|
|
has_ret = True |
|
|
|
|
return has_ret, update |
|
|
|
|
|
|
|
|
|
def has_delete_permission(self, request, obj): |
|
|
|
|
def has_delete_permission(self, obj): |
|
|
|
|
return True |
|
|
|
|
|
|
|
|
|
def delete(self, *args, **kwargs): |
|
|
|
|