19
19
request , Response , url_for )
20
20
from ..utils import is_collection
21
21
from ..auth import current_auth , add_auth_attribute
22
- from .misc import jsonp as render_jsonp
22
+ from .misc import jsonp
23
23
24
24
__all__ = [
25
25
'RequestTypeError' , 'RequestValueError' ,
26
26
'requestargs' , 'requestform' , 'requestquery' ,
27
27
'load_model' , 'load_models' ,
28
- 'render_with' , 'cors' ,
28
+ 'render_with' , 'cors' , 'requires_permission' ,
29
29
]
30
30
31
31
@@ -108,7 +108,7 @@ def datasource():
108
108
return request .values if request else {}
109
109
110
110
@wraps (f )
111
- def decorated_function (** kw ):
111
+ def decorated_function (* args , * *kw ):
112
112
values = datasource ()
113
113
for name , filt , is_list in namefilt :
114
114
# Process name if
@@ -123,7 +123,7 @@ def decorated_function(**kw):
123
123
except ValueError as e :
124
124
raise RequestValueError (e )
125
125
try :
126
- return f (** kw )
126
+ return f (* args , * *kw )
127
127
except TypeError as e :
128
128
raise RequestTypeError (e )
129
129
return decorated_function
@@ -236,7 +236,7 @@ def show_page(folder, page):
236
236
"""
237
237
def inner (f ):
238
238
@wraps (f )
239
- def decorated_function (** kw ):
239
+ def decorated_function (* args , * *kw ):
240
240
permissions = None
241
241
permission_required = kwargs .get ('permission' )
242
242
url_check_attributes = kwargs .get ('urlcheck' , [])
@@ -316,14 +316,13 @@ def decorated_function(**kw):
316
316
if permission_required and not (permission_required & permissions ):
317
317
abort (403 )
318
318
if kwargs .get ('kwargs' ):
319
- return f (kwargs = kw , ** result )
319
+ return f (* args , kwargs = kw , ** result )
320
320
else :
321
- return f (** result )
321
+ return f (* args , * *result )
322
322
return decorated_function
323
323
return inner
324
324
325
325
326
-
327
326
def _best_mimetype_match (available_list , accept_mimetypes , default = None ):
328
327
for use_mimetype , quality in accept_mimetypes :
329
328
for mimetype in available_list :
@@ -332,7 +331,21 @@ def _best_mimetype_match(available_list, accept_mimetypes, default=None):
332
331
return default
333
332
334
333
335
- def render_with (template , json = False , jsonp = False ):
334
+ def dict_jsonify (param ):
335
+ """Convert the parameter into a dictionary before calling jsonify, if it's not already one"""
336
+ if not isinstance (param , dict ):
337
+ param = dict (param )
338
+ return jsonify (param )
339
+
340
+
341
+ def dict_jsonp (param ):
342
+ """Convert the parameter into a dictionary before calling jsonp, if it's not already one"""
343
+ if not isinstance (param , dict ):
344
+ param = dict (param )
345
+ return jsonp (param )
346
+
347
+
348
+ def render_with (template = None , json = False , jsonp = False ):
336
349
"""
337
350
Decorator to render the wrapped function with the given template (or dictionary
338
351
of mimetype keys to templates, where the template is a string name of a template
@@ -393,30 +406,29 @@ def myview():
393
406
"""
394
407
if jsonp :
395
408
templates = {
396
- 'application/json' : render_jsonp ,
397
- 'text/json' : render_jsonp ,
398
- 'text/x-json' : render_jsonp ,
409
+ 'application/json' : dict_jsonp ,
410
+ 'application/javascript' : dict_jsonp ,
399
411
}
400
412
elif json :
401
413
templates = {
402
- 'application/json' : jsonify ,
403
- 'text/json' : jsonify ,
404
- 'text/x-json' : jsonify ,
414
+ 'application/json' : dict_jsonify ,
405
415
}
406
416
else :
407
417
templates = {}
408
418
if isinstance (template , six .string_types ):
409
419
templates ['text/html' ] = template
410
420
elif isinstance (template , dict ):
411
421
templates .update (template )
422
+ elif template is None and (json or jsonp ):
423
+ pass
412
424
else : # pragma: no cover
413
425
raise ValueError ("Expected string or dict for template" )
414
426
415
427
default_mimetype = '*/*'
416
428
if '*/*' not in templates :
417
429
templates ['*/*' ] = six .text_type
418
430
default_mimetype = 'text/plain'
419
- for mimetype in ('text/html' , 'text/plain' , 'application/json' , 'text/json' , 'text/x-json' ):
431
+ for mimetype in ('text/html' , 'text/plain' , 'application/json' ):
420
432
if mimetype in templates :
421
433
templates ['*/*' ] = templates [mimetype ]
422
434
default_mimetype = mimetype # Remember which mimetype's handler is serving for */*
@@ -582,3 +594,31 @@ def wrapper(*args, **kwargs):
582
594
return resp
583
595
return wrapper
584
596
return inner
597
+
598
+
599
+ def requires_permission (permission ):
600
+ """
601
+ View decorator that requires a certain permission to be present in
602
+ ``current_auth.permissions`` before the view is allowed to proceed.
603
+ Aborts with ``403 Forbidden`` if the permission is not present.
604
+
605
+ :param permission: Permission that is required. If an iterable is provided,
606
+ any one permission must be available
607
+ """
608
+ def inner (f ):
609
+ @wraps (f )
610
+ def wrapper (* args , ** kwargs ):
611
+ add_auth_attribute ('login_required' , True )
612
+ if not hasattr (current_auth , 'permissions' ):
613
+ test = False
614
+ elif is_collection (permission ):
615
+ test = bool (current_auth .permissions .intersection (permission ))
616
+ else :
617
+ test = permission in current_auth .permissions
618
+ if not test :
619
+ abort (403 )
620
+ return f (* args , ** kwargs )
621
+
622
+ wrapper .requires_permission = permission
623
+ return wrapper
624
+ return inner
0 commit comments