Move cached_endpoint, required_fields to flasktools.
This commit is contained in:
		
							parent
							
								
									e883409daf
								
							
						
					
					
						commit
						d4025e865b
					
				
					 6 changed files with 27 additions and 143 deletions
				
			
		|  | @ -1,93 +1,11 @@ | ||||||
| import flask; from flask import request | import flask; from flask import request | ||||||
| import functools | import functools | ||||||
| import time |  | ||||||
| import werkzeug.datastructures | import werkzeug.datastructures | ||||||
| 
 | 
 | ||||||
| from voussoirkit import dotdict |  | ||||||
| from voussoirkit import flasktools | from voussoirkit import flasktools | ||||||
| from voussoirkit import passwordy |  | ||||||
| from voussoirkit import sentinel |  | ||||||
| 
 | 
 | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| NOT_CACHED = sentinel.Sentinel('not cached', truthyness=False) |  | ||||||
| 
 |  | ||||||
| def cached_endpoint(max_age): |  | ||||||
|     ''' |  | ||||||
|     The cached_endpoint decorator can be used on slow endpoints that don't need |  | ||||||
|     to be constantly updated or endpoints that produce large, static responses. |  | ||||||
| 
 |  | ||||||
|     WARNING: The return value of the endpoint is shared with all users. |  | ||||||
|     You should never use this cache on an endpoint that provides private |  | ||||||
|     or personalized data, and you should not try to pass other headers through |  | ||||||
|     the response. |  | ||||||
| 
 |  | ||||||
|     When the function is run, its return value is stored and a random etag is |  | ||||||
|     generated so that subsequent runs can respond with 304. This way, large |  | ||||||
|     response bodies do not need to be transmitted often. |  | ||||||
| 
 |  | ||||||
|     Given a nonzero max_age, the endpoint will only be run once per max_age |  | ||||||
|     seconds on a global basis (not per-user). This way, you can prevent a slow |  | ||||||
|     function from being run very often. In-between requests will just receive |  | ||||||
|     the previous return value (still using 200 or 304 as appropriate for the |  | ||||||
|     client's provided etag). |  | ||||||
| 
 |  | ||||||
|     With max_age=0, the function will be run every time to check if the value |  | ||||||
|     has changed, but if it hasn't changed then we can still send a 304 response, |  | ||||||
|     saving bandwidth. |  | ||||||
| 
 |  | ||||||
|     An example use case would be large-sized data dumps that don't need to be |  | ||||||
|     precisely up to date every time. |  | ||||||
|     ''' |  | ||||||
|     if max_age < 0: |  | ||||||
|         raise ValueError(f'max_age should be positive, not {max_age}.') |  | ||||||
| 
 |  | ||||||
|     state = dotdict.DotDict({ |  | ||||||
|         'max_age': max_age, |  | ||||||
|         'stored_value': NOT_CACHED, |  | ||||||
|         'stored_etag': None, |  | ||||||
|         'headers': {'ETag': None, 'Cache-Control': f'max-age={max_age}'}, |  | ||||||
|         'last_run': 0, |  | ||||||
|     }) |  | ||||||
| 
 |  | ||||||
|     def wrapper(function): |  | ||||||
|         def get_value(*args, **kwargs): |  | ||||||
|             can_bail = ( |  | ||||||
|                 state.stored_value is not NOT_CACHED and |  | ||||||
|                 state.max_age != 0 and |  | ||||||
|                 (time.time() - state.last_run) < state.max_age |  | ||||||
|             ) |  | ||||||
|             if can_bail: |  | ||||||
|                 return state.stored_value |  | ||||||
| 
 |  | ||||||
|             value = function(*args, **kwargs) |  | ||||||
|             if isinstance(value, flask.Response): |  | ||||||
|                 if value.headers.get('Content-Type'): |  | ||||||
|                     state.headers['Content-Type'] = value.headers.get('Content-Type') |  | ||||||
|                 value = value.response |  | ||||||
| 
 |  | ||||||
|             if value != state.stored_value: |  | ||||||
|                 state.stored_value = value |  | ||||||
|                 state.stored_etag = passwordy.random_hex(20) |  | ||||||
|                 state.headers['ETag'] = state.stored_etag |  | ||||||
| 
 |  | ||||||
|             state.last_run = time.time() |  | ||||||
|             return value |  | ||||||
| 
 |  | ||||||
|         @functools.wraps(function) |  | ||||||
|         def wrapped(*args, **kwargs): |  | ||||||
|             value = get_value(*args, **kwargs) |  | ||||||
| 
 |  | ||||||
|             client_etag = request.headers.get('If-None-Match', None) |  | ||||||
|             if client_etag == state.stored_etag: |  | ||||||
|                 response = flask.Response(status=304, headers=state.headers) |  | ||||||
|             else: |  | ||||||
|                 response = flask.Response(value, status=200, headers=state.headers) |  | ||||||
| 
 |  | ||||||
|             return response |  | ||||||
|         return wrapped |  | ||||||
|     return wrapper |  | ||||||
| 
 |  | ||||||
| def catch_etiquette_exception(function): | def catch_etiquette_exception(function): | ||||||
|     ''' |     ''' | ||||||
|     If an EtiquetteException is raised, automatically catch it and convert it |     If an EtiquetteException is raised, automatically catch it and convert it | ||||||
|  | @ -128,32 +46,3 @@ def give_theme_cookie(function): | ||||||
| 
 | 
 | ||||||
|         return response |         return response | ||||||
|     return wrapped |     return wrapped | ||||||
| 
 |  | ||||||
| def required_fields(fields, forbid_whitespace=False): |  | ||||||
|     ''' |  | ||||||
|     Declare that the endpoint requires certain POST body fields. Without them, |  | ||||||
|     we respond with 400 and a message. |  | ||||||
| 
 |  | ||||||
|     forbid_whitespace: |  | ||||||
|         If True, then providing the field is not good enough. It must also |  | ||||||
|         contain at least some non-whitespace characters. |  | ||||||
|     ''' |  | ||||||
|     def wrapper(function): |  | ||||||
|         @functools.wraps(function) |  | ||||||
|         def wrapped(*args, **kwargs): |  | ||||||
|             for requirement in fields: |  | ||||||
|                 missing = ( |  | ||||||
|                     requirement not in request.form or |  | ||||||
|                     (forbid_whitespace and request.form[requirement].strip() == '') |  | ||||||
|                 ) |  | ||||||
|                 if missing: |  | ||||||
|                     response = { |  | ||||||
|                         'error_type': 'MISSING_FIELDS', |  | ||||||
|                         'error_message': 'Required fields: %s' % ', '.join(fields), |  | ||||||
|                     } |  | ||||||
|                     response = flasktools.make_json_response(response, status=400) |  | ||||||
|                     return response |  | ||||||
| 
 |  | ||||||
|             return function(*args, **kwargs) |  | ||||||
|         return wrapped |  | ||||||
|     return wrapper |  | ||||||
|  |  | ||||||
|  | @ -9,7 +9,6 @@ from voussoirkit import stringtools | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| from .. import common | from .. import common | ||||||
| from .. import decorators |  | ||||||
| 
 | 
 | ||||||
| site = common.site | site = common.site | ||||||
| session_manager = common.session_manager | session_manager = common.session_manager | ||||||
|  | @ -57,7 +56,7 @@ def get_album_zip(album_id): | ||||||
|     return flask.Response(streamed_zip, headers=outgoing_headers) |     return flask.Response(streamed_zip, headers=outgoing_headers) | ||||||
| 
 | 
 | ||||||
| @site.route('/album/<album_id>/add_child', methods=['POST']) | @site.route('/album/<album_id>/add_child', methods=['POST']) | ||||||
| @decorators.required_fields(['child_id'], forbid_whitespace=True) | @flasktools.required_fields(['child_id'], forbid_whitespace=True) | ||||||
| def post_album_add_child(album_id): | def post_album_add_child(album_id): | ||||||
|     album = common.P_album(album_id, response_type='json') |     album = common.P_album(album_id, response_type='json') | ||||||
| 
 | 
 | ||||||
|  | @ -69,7 +68,7 @@ def post_album_add_child(album_id): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/album/<album_id>/remove_child', methods=['POST']) | @site.route('/album/<album_id>/remove_child', methods=['POST']) | ||||||
| @decorators.required_fields(['child_id'], forbid_whitespace=True) | @flasktools.required_fields(['child_id'], forbid_whitespace=True) | ||||||
| def post_album_remove_child(album_id): | def post_album_remove_child(album_id): | ||||||
|     album = common.P_album(album_id, response_type='json') |     album = common.P_album(album_id, response_type='json') | ||||||
| 
 | 
 | ||||||
|  | @ -98,7 +97,7 @@ def post_album_refresh_directories(album_id): | ||||||
|     return flasktools.make_json_response({}) |     return flasktools.make_json_response({}) | ||||||
| 
 | 
 | ||||||
| @site.route('/album/<album_id>/set_thumbnail_photo', methods=['POST']) | @site.route('/album/<album_id>/set_thumbnail_photo', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_id'], forbid_whitespace=True) | @flasktools.required_fields(['photo_id'], forbid_whitespace=True) | ||||||
| def post_album_set_thumbnail_photo(album_id): | def post_album_set_thumbnail_photo(album_id): | ||||||
|     album = common.P_album(album_id, response_type='json') |     album = common.P_album(album_id, response_type='json') | ||||||
|     photo = common.P_photo(request.form['photo_id'], response_type='json') |     photo = common.P_photo(request.form['photo_id'], response_type='json') | ||||||
|  | @ -109,7 +108,7 @@ def post_album_set_thumbnail_photo(album_id): | ||||||
| # Album photo operations ########################################################################### | # Album photo operations ########################################################################### | ||||||
| 
 | 
 | ||||||
| @site.route('/album/<album_id>/add_photo', methods=['POST']) | @site.route('/album/<album_id>/add_photo', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_id'], forbid_whitespace=True) | @flasktools.required_fields(['photo_id'], forbid_whitespace=True) | ||||||
| def post_album_add_photo(album_id): | def post_album_add_photo(album_id): | ||||||
|     ''' |     ''' | ||||||
|     Add a photo or photos to this album. |     Add a photo or photos to this album. | ||||||
|  | @ -123,7 +122,7 @@ def post_album_add_photo(album_id): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/album/<album_id>/remove_photo', methods=['POST']) | @site.route('/album/<album_id>/remove_photo', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_id'], forbid_whitespace=True) | @flasktools.required_fields(['photo_id'], forbid_whitespace=True) | ||||||
| def post_album_remove_photo(album_id): | def post_album_remove_photo(album_id): | ||||||
|     ''' |     ''' | ||||||
|     Remove a photo or photos from this album. |     Remove a photo or photos from this album. | ||||||
|  | @ -195,7 +194,7 @@ def post_album_show_in_folder(album_id): | ||||||
| # Album listings ################################################################################### | # Album listings ################################################################################### | ||||||
| 
 | 
 | ||||||
| @site.route('/all_albums.json') | @site.route('/all_albums.json') | ||||||
| @decorators.cached_endpoint(max_age=15) | @flasktools.cached_endpoint(max_age=15) | ||||||
| def get_all_album_names(): | def get_all_album_names(): | ||||||
|     all_albums = {album.id: album.display_name for album in common.P.get_albums()} |     all_albums = {album.id: album.display_name for album in common.P.get_albums()} | ||||||
|     response = {'albums': all_albums} |     response = {'albums': all_albums} | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ from voussoirkit import flasktools | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| from .. import common | from .. import common | ||||||
| from .. import decorators |  | ||||||
| 
 | 
 | ||||||
| site = common.site | site = common.site | ||||||
| session_manager = common.session_manager | session_manager = common.session_manager | ||||||
|  | @ -45,7 +44,7 @@ def get_bookmarks_json(): | ||||||
| # Bookmark create and delete ####################################################################### | # Bookmark create and delete ####################################################################### | ||||||
| 
 | 
 | ||||||
| @site.route('/bookmarks/create_bookmark', methods=['POST']) | @site.route('/bookmarks/create_bookmark', methods=['POST']) | ||||||
| @decorators.required_fields(['url'], forbid_whitespace=True) | @flasktools.required_fields(['url'], forbid_whitespace=True) | ||||||
| def post_bookmark_create(): | def post_bookmark_create(): | ||||||
|     url = request.form['url'] |     url = request.form['url'] | ||||||
|     title = request.form.get('title', None) |     title = request.form.get('title', None) | ||||||
|  |  | ||||||
|  | @ -10,7 +10,6 @@ from voussoirkit import stringtools | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| from .. import common | from .. import common | ||||||
| from .. import decorators |  | ||||||
| from .. import helpers | from .. import helpers | ||||||
| 
 | 
 | ||||||
| site = common.site | site = common.site | ||||||
|  | @ -98,7 +97,7 @@ def post_photo_add_remove_tag_core(photo_ids, tagname, add_or_remove): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/photo/<photo_id>/add_tag', methods=['POST']) | @site.route('/photo/<photo_id>/add_tag', methods=['POST']) | ||||||
| @decorators.required_fields(['tagname'], forbid_whitespace=True) | @flasktools.required_fields(['tagname'], forbid_whitespace=True) | ||||||
| def post_photo_add_tag(photo_id): | def post_photo_add_tag(photo_id): | ||||||
|     ''' |     ''' | ||||||
|     Add a tag to this photo. |     Add a tag to this photo. | ||||||
|  | @ -111,7 +110,7 @@ def post_photo_add_tag(photo_id): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/photo/<photo_id>/copy_tags', methods=['POST']) | @site.route('/photo/<photo_id>/copy_tags', methods=['POST']) | ||||||
| @decorators.required_fields(['other_photo'], forbid_whitespace=True) | @flasktools.required_fields(['other_photo'], forbid_whitespace=True) | ||||||
| def post_photo_copy_tags(photo_id): | def post_photo_copy_tags(photo_id): | ||||||
|     ''' |     ''' | ||||||
|     Copy the tags from another photo. |     Copy the tags from another photo. | ||||||
|  | @ -123,7 +122,7 @@ def post_photo_copy_tags(photo_id): | ||||||
|     return flasktools.make_json_response([tag.jsonify(minimal=True) for tag in photo.get_tags()]) |     return flasktools.make_json_response([tag.jsonify(minimal=True) for tag in photo.get_tags()]) | ||||||
| 
 | 
 | ||||||
| @site.route('/photo/<photo_id>/remove_tag', methods=['POST']) | @site.route('/photo/<photo_id>/remove_tag', methods=['POST']) | ||||||
| @decorators.required_fields(['tagname'], forbid_whitespace=True) | @flasktools.required_fields(['tagname'], forbid_whitespace=True) | ||||||
| def post_photo_remove_tag(photo_id): | def post_photo_remove_tag(photo_id): | ||||||
|     ''' |     ''' | ||||||
|     Remove a tag from this photo. |     Remove a tag from this photo. | ||||||
|  | @ -136,7 +135,7 @@ def post_photo_remove_tag(photo_id): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/add_tag', methods=['POST']) | @site.route('/batch/photos/add_tag', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True) | ||||||
| def post_batch_photos_add_tag(): | def post_batch_photos_add_tag(): | ||||||
|     response = post_photo_add_remove_tag_core( |     response = post_photo_add_remove_tag_core( | ||||||
|         photo_ids=request.form['photo_ids'], |         photo_ids=request.form['photo_ids'], | ||||||
|  | @ -146,7 +145,7 @@ def post_batch_photos_add_tag(): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/remove_tag', methods=['POST']) | @site.route('/batch/photos/remove_tag', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids', 'tagname'], forbid_whitespace=True) | ||||||
| def post_batch_photos_remove_tag(): | def post_batch_photos_remove_tag(): | ||||||
|     response = post_photo_add_remove_tag_core( |     response = post_photo_add_remove_tag_core( | ||||||
|         photo_ids=request.form['photo_ids'], |         photo_ids=request.form['photo_ids'], | ||||||
|  | @ -194,7 +193,7 @@ def post_photo_refresh_metadata(photo_id): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/refresh_metadata', methods=['POST']) | @site.route('/batch/photos/refresh_metadata', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids'], forbid_whitespace=True) | ||||||
| def post_batch_photos_refresh_metadata(): | def post_batch_photos_refresh_metadata(): | ||||||
|     response = post_photo_refresh_metadata_core(photo_ids=request.form['photo_ids']) |     response = post_photo_refresh_metadata_core(photo_ids=request.form['photo_ids']) | ||||||
|     return response |     return response | ||||||
|  | @ -238,14 +237,14 @@ def post_photo_show_in_folder(photo_id): | ||||||
|     flask.abort(501) |     flask.abort(501) | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/set_searchhidden', methods=['POST']) | @site.route('/batch/photos/set_searchhidden', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids'], forbid_whitespace=True) | ||||||
| def post_batch_photos_set_searchhidden(): | def post_batch_photos_set_searchhidden(): | ||||||
|     photo_ids = request.form['photo_ids'] |     photo_ids = request.form['photo_ids'] | ||||||
|     response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=True) |     response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=True) | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/unset_searchhidden', methods=['POST']) | @site.route('/batch/photos/unset_searchhidden', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids'], forbid_whitespace=True) | ||||||
| def post_batch_photos_unset_searchhidden(): | def post_batch_photos_unset_searchhidden(): | ||||||
|     photo_ids = request.form['photo_ids'] |     photo_ids = request.form['photo_ids'] | ||||||
|     response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=False) |     response = post_batch_photos_searchhidden_core(photo_ids=photo_ids, searchhidden=False) | ||||||
|  | @ -258,7 +257,7 @@ def get_clipboard_page(): | ||||||
|     return common.render_template(request, 'clipboard.html') |     return common.render_template(request, 'clipboard.html') | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos', methods=['POST']) | @site.route('/batch/photos', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids'], forbid_whitespace=True) | ||||||
| def post_batch_photos(): | def post_batch_photos(): | ||||||
|     ''' |     ''' | ||||||
|     Return a list of photo.jsonify() for each requested photo id. |     Return a list of photo.jsonify() for each requested photo id. | ||||||
|  | @ -273,7 +272,7 @@ def post_batch_photos(): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/photo_card', methods=['POST']) | @site.route('/batch/photos/photo_card', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids'], forbid_whitespace=True) | ||||||
| def post_batch_photos_photo_cards(): | def post_batch_photos_photo_cards(): | ||||||
|     photo_ids = request.form['photo_ids'] |     photo_ids = request.form['photo_ids'] | ||||||
| 
 | 
 | ||||||
|  | @ -328,7 +327,7 @@ def get_batch_photos_download_zip(zip_token): | ||||||
|     return flask.Response(streamed_zip, headers=outgoing_headers) |     return flask.Response(streamed_zip, headers=outgoing_headers) | ||||||
| 
 | 
 | ||||||
| @site.route('/batch/photos/download_zip', methods=['POST']) | @site.route('/batch/photos/download_zip', methods=['POST']) | ||||||
| @decorators.required_fields(['photo_ids'], forbid_whitespace=True) | @flasktools.required_fields(['photo_ids'], forbid_whitespace=True) | ||||||
| def post_batch_photos_download_zip(): | def post_batch_photos_download_zip(): | ||||||
|     ''' |     ''' | ||||||
|     Initiating file downloads via POST requests is a bit clunky and unreliable, |     Initiating file downloads via POST requests is a bit clunky and unreliable, | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ from voussoirkit import flasktools | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| from .. import common | from .. import common | ||||||
| from .. import decorators |  | ||||||
| 
 | 
 | ||||||
| site = common.site | site = common.site | ||||||
| session_manager = common.session_manager | session_manager = common.session_manager | ||||||
|  | @ -57,7 +56,7 @@ def post_tag_edit(tagname): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/tag/<tagname>/add_child', methods=['POST']) | @site.route('/tag/<tagname>/add_child', methods=['POST']) | ||||||
| @decorators.required_fields(['child_name'], forbid_whitespace=True) | @flasktools.required_fields(['child_name'], forbid_whitespace=True) | ||||||
| def post_tag_add_child(tagname): | def post_tag_add_child(tagname): | ||||||
|     parent = common.P_tag(tagname, response_type='json') |     parent = common.P_tag(tagname, response_type='json') | ||||||
|     child = common.P_tag(request.form['child_name'], response_type='json') |     child = common.P_tag(request.form['child_name'], response_type='json') | ||||||
|  | @ -66,7 +65,7 @@ def post_tag_add_child(tagname): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/tag/<tagname>/add_synonym', methods=['POST']) | @site.route('/tag/<tagname>/add_synonym', methods=['POST']) | ||||||
| @decorators.required_fields(['syn_name'], forbid_whitespace=True) | @flasktools.required_fields(['syn_name'], forbid_whitespace=True) | ||||||
| def post_tag_add_synonym(tagname): | def post_tag_add_synonym(tagname): | ||||||
|     syn_name = request.form['syn_name'] |     syn_name = request.form['syn_name'] | ||||||
| 
 | 
 | ||||||
|  | @ -77,7 +76,7 @@ def post_tag_add_synonym(tagname): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/tag/<tagname>/remove_child', methods=['POST']) | @site.route('/tag/<tagname>/remove_child', methods=['POST']) | ||||||
| @decorators.required_fields(['child_name'], forbid_whitespace=True) | @flasktools.required_fields(['child_name'], forbid_whitespace=True) | ||||||
| def post_tag_remove_child(tagname): | def post_tag_remove_child(tagname): | ||||||
|     parent = common.P_tag(tagname, response_type='json') |     parent = common.P_tag(tagname, response_type='json') | ||||||
|     child = common.P_tag(request.form['child_name'], response_type='json') |     child = common.P_tag(request.form['child_name'], response_type='json') | ||||||
|  | @ -86,7 +85,7 @@ def post_tag_remove_child(tagname): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/tag/<tagname>/remove_synonym', methods=['POST']) | @site.route('/tag/<tagname>/remove_synonym', methods=['POST']) | ||||||
| @decorators.required_fields(['syn_name'], forbid_whitespace=True) | @flasktools.required_fields(['syn_name'], forbid_whitespace=True) | ||||||
| def post_tag_remove_synonym(tagname): | def post_tag_remove_synonym(tagname): | ||||||
|     syn_name = request.form['syn_name'] |     syn_name = request.form['syn_name'] | ||||||
| 
 | 
 | ||||||
|  | @ -99,7 +98,7 @@ def post_tag_remove_synonym(tagname): | ||||||
| # Tag listings ##################################################################################### | # Tag listings ##################################################################################### | ||||||
| 
 | 
 | ||||||
| @site.route('/all_tags.json') | @site.route('/all_tags.json') | ||||||
| @decorators.cached_endpoint(max_age=15) | @flasktools.cached_endpoint(max_age=15) | ||||||
| def get_all_tag_names(): | def get_all_tag_names(): | ||||||
|     all_tags = list(common.P.get_all_tag_names()) |     all_tags = list(common.P.get_all_tag_names()) | ||||||
|     all_synonyms = common.P.get_all_synonyms() |     all_synonyms = common.P.get_all_synonyms() | ||||||
|  | @ -158,7 +157,7 @@ def get_tags_json(): | ||||||
| # Tag create and delete ############################################################################ | # Tag create and delete ############################################################################ | ||||||
| 
 | 
 | ||||||
| @site.route('/tags/create_tag', methods=['POST']) | @site.route('/tags/create_tag', methods=['POST']) | ||||||
| @decorators.required_fields(['name'], forbid_whitespace=True) | @flasktools.required_fields(['name'], forbid_whitespace=True) | ||||||
| def post_tag_create(): | def post_tag_create(): | ||||||
|     name = request.form['name'] |     name = request.form['name'] | ||||||
|     description = request.form.get('description', None) |     description = request.form.get('description', None) | ||||||
|  | @ -168,7 +167,7 @@ def post_tag_create(): | ||||||
|     return flasktools.make_json_response(response) |     return flasktools.make_json_response(response) | ||||||
| 
 | 
 | ||||||
| @site.route('/tags/easybake', methods=['POST']) | @site.route('/tags/easybake', methods=['POST']) | ||||||
| @decorators.required_fields(['easybake_string'], forbid_whitespace=True) | @flasktools.required_fields(['easybake_string'], forbid_whitespace=True) | ||||||
| def post_tag_easybake(): | def post_tag_easybake(): | ||||||
|     easybake_string = request.form['easybake_string'] |     easybake_string = request.form['easybake_string'] | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ from voussoirkit import flasktools | ||||||
| import etiquette | import etiquette | ||||||
| 
 | 
 | ||||||
| from .. import common | from .. import common | ||||||
| from .. import decorators |  | ||||||
| from .. import sessions | from .. import sessions | ||||||
| 
 | 
 | ||||||
| site = common.site | site = common.site | ||||||
|  | @ -67,7 +66,7 @@ def get_login(): | ||||||
|     return response |     return response | ||||||
| 
 | 
 | ||||||
| @site.route('/login', methods=['POST']) | @site.route('/login', methods=['POST']) | ||||||
| @decorators.required_fields(['username', 'password']) | @flasktools.required_fields(['username', 'password']) | ||||||
| def post_login(): | def post_login(): | ||||||
|     session = session_manager.get(request) |     session = session_manager.get(request) | ||||||
|     if session.user: |     if session.user: | ||||||
|  | @ -107,7 +106,7 @@ def get_register(): | ||||||
|     return flask.redirect('/login') |     return flask.redirect('/login') | ||||||
| 
 | 
 | ||||||
| @site.route('/register', methods=['POST']) | @site.route('/register', methods=['POST']) | ||||||
| @decorators.required_fields(['username', 'password_1', 'password_2']) | @flasktools.required_fields(['username', 'password_1', 'password_2']) | ||||||
| def post_register(): | def post_register(): | ||||||
|     session = session_manager.get(request) |     session = session_manager.get(request) | ||||||
|     if session.user: |     if session.user: | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue