diff options
author | Joar Wandborg <git@wandborg.com> | 2012-09-29 21:07:15 +0200 |
---|---|---|
committer | Joar Wandborg <git@wandborg.com> | 2012-09-29 21:08:20 +0200 |
commit | 111a609df526bd3690fc03e623eaf5826f33f4d2 (patch) | |
tree | 87029ee907afd4f35896ddfe582437b59747dccc /mediagoblin | |
parent | a6ec38c3c1caf4735f2da45a12fb2d0a5861d830 (diff) | |
download | mediagoblin-111a609df526bd3690fc03e623eaf5826f33f4d2.tar.lz mediagoblin-111a609df526bd3690fc03e623eaf5826f33f4d2.tar.xz mediagoblin-111a609df526bd3690fc03e623eaf5826f33f4d2.zip |
Replaced all request.POST with request.form, ...
- Fixed error handling in OAuth plugin
- Changed request.POST file fields to request.files
Diffstat (limited to 'mediagoblin')
-rw-r--r-- | mediagoblin/app.py | 1 | ||||
-rw-r--r-- | mediagoblin/auth/views.py | 30 | ||||
-rw-r--r-- | mediagoblin/edit/views.py | 60 | ||||
-rw-r--r-- | mediagoblin/meddleware/csrf.py | 2 | ||||
-rw-r--r-- | mediagoblin/plugins/api/views.py | 27 | ||||
-rw-r--r-- | mediagoblin/plugins/oauth/README.rst | 6 | ||||
-rw-r--r-- | mediagoblin/plugins/oauth/views.py | 58 | ||||
-rw-r--r-- | mediagoblin/submit/views.py | 16 | ||||
-rw-r--r-- | mediagoblin/tests/test_http_callback.py | 25 | ||||
-rw-r--r-- | mediagoblin/tools/translate.py | 2 | ||||
-rw-r--r-- | mediagoblin/user_pages/views.py | 22 |
11 files changed, 144 insertions, 105 deletions
diff --git a/mediagoblin/app.py b/mediagoblin/app.py index 30ac3e01..08515df9 100644 --- a/mediagoblin/app.py +++ b/mediagoblin/app.py @@ -130,7 +130,6 @@ class MediaGoblinApp(object): ## Compatibility webob -> werkzeug request.GET = request.args - request.POST = request.form request.accept_language = request.accept_languages request.accept = request.accept_mimetypes diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py index 71a5f379..5b77c122 100644 --- a/mediagoblin/auth/views.py +++ b/mediagoblin/auth/views.py @@ -55,12 +55,12 @@ def register(request): _('Sorry, registration is disabled on this instance.')) return redirect(request, "index") - register_form = auth_forms.RegistrationForm(request.POST) + register_form = auth_forms.RegistrationForm(request.form) if request.method == 'POST' and register_form.validate(): # TODO: Make sure the user doesn't exist already - username = unicode(request.POST['username'].lower()) - em_user, em_dom = unicode(request.POST['email']).split("@", 1) + username = unicode(request.form['username'].lower()) + em_user, em_dom = unicode(request.form['email']).split("@", 1) em_dom = em_dom.lower() email = em_user + "@" + em_dom users_with_username = request.db.User.find( @@ -85,7 +85,7 @@ def register(request): user.username = username user.email = email user.pw_hash = auth_lib.bcrypt_gen_password_hash( - request.POST['password']) + request.form['password']) user.verification_key = unicode(uuid.uuid4()) user.save(validate=True) @@ -115,21 +115,21 @@ def login(request): If you provide the POST with 'next', it'll redirect to that view. """ - login_form = auth_forms.LoginForm(request.POST) + login_form = auth_forms.LoginForm(request.form) login_failed = False if request.method == 'POST' and login_form.validate(): user = request.db.User.find_one( - {'username': request.POST['username'].lower()}) + {'username': request.form['username'].lower()}) - if user and user.check_login(request.POST['password']): + if user and user.check_login(request.form['password']): # set up login in session request.session['user_id'] = unicode(user._id) request.session.save() - if request.POST.get('next'): - return exc.HTTPFound(location=request.POST['next']) + if request.form.get('next'): + return exc.HTTPFound(location=request.form['next']) else: return redirect(request, "index") @@ -143,7 +143,7 @@ def login(request): request, 'mediagoblin/auth/login.html', {'login_form': login_form, - 'next': request.GET.get('next') or request.POST.get('next'), + 'next': request.GET.get('next') or request.form.get('next'), 'login_failed': login_failed, 'allow_registration': mg_globals.app_config["allow_registration"]}) @@ -236,17 +236,17 @@ def forgot_password(request): Sends an email with an url to renew forgotten password """ - fp_form = auth_forms.ForgotPassForm(request.POST, + fp_form = auth_forms.ForgotPassForm(request.form, username=request.GET.get('username')) if request.method == 'POST' and fp_form.validate(): # '$or' not available till mongodb 1.5.3 user = request.db.User.find_one( - {'username': request.POST['username']}) + {'username': request.form['username']}) if not user: user = request.db.User.find_one( - {'email': request.POST['username']}) + {'email': request.form['username']}) if user: if user.email_verified and user.status == 'active': @@ -322,7 +322,7 @@ def verify_forgot_password(request): if request.method == 'POST' and cp_form.validate(): user.pw_hash = auth_lib.bcrypt_gen_password_hash( - request.POST['password']) + request.form['password']) user.fp_verification_key = None user.fp_token_expire = None user.save() @@ -355,7 +355,7 @@ def _process_for_token(request): if request.method == 'GET': formdata_vars = request.GET else: - formdata_vars = request.POST + formdata_vars = request.form formdata = { 'vars': formdata_vars, diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py index f96301fa..61b2cb82 100644 --- a/mediagoblin/edit/views.py +++ b/mediagoblin/edit/views.py @@ -51,27 +51,27 @@ def edit_media(request, media): license=media.license) form = forms.EditForm( - request.POST, + request.form, **defaults) if request.method == 'POST' and form.validate(): # Make sure there isn't already a MediaEntry with such a slug # and userid. slug_used = check_media_slug_used(request.db, media.uploader, - request.POST['slug'], media.id) + request.form['slug'], media.id) if slug_used: form.slug.errors.append( _(u'An entry with that slug already exists for this user.')) else: - media.title = unicode(request.POST['title']) - media.description = unicode(request.POST.get('description')) + media.title = unicode(request.form['title']) + media.description = unicode(request.form.get('description')) media.tags = convert_to_tag_list_of_dicts( - request.POST.get('tags')) + request.form.get('tags')) - media.license = unicode(request.POST.get('license', '')) or None + media.license = unicode(request.form.get('license', '')) or None - media.slug = unicode(request.POST['slug']) + media.slug = unicode(request.form['slug']) media.save() @@ -106,9 +106,9 @@ def edit_attachments(request, media): form = forms.EditAttachmentsForm() # Add any attachements - if ('attachment_file' in request.POST - and isinstance(request.POST['attachment_file'], FieldStorage) - and request.POST['attachment_file'].file): + if ('attachment_file' in request.form + and isinstance(request.form['attachment_file'], FieldStorage) + and request.form['attachment_file'].file): # Security measure to prevent attachments from being served as # text/html, which will be parsed by web clients and pose an XSS @@ -121,13 +121,13 @@ def edit_attachments(request, media): # machine parsing the upload form, and not necessarily the machine # serving the attachments. if mimetypes.guess_type( - request.POST['attachment_file'].filename)[0] in \ + request.form['attachment_file'].filename)[0] in \ UNSAFE_MIMETYPES: public_filename = secure_filename('{0}.notsafe'.format( - request.POST['attachment_file'].filename)) + request.form['attachment_file'].filename)) else: public_filename = secure_filename( - request.POST['attachment_file'].filename) + request.form['attachment_file'].filename) attachment_public_filepath \ = mg_globals.public_store.get_unique_filepath( @@ -139,13 +139,13 @@ def edit_attachments(request, media): try: attachment_public_file.write( - request.POST['attachment_file'].file.read()) + request.form['attachment_file'].file.read()) finally: - request.POST['attachment_file'].file.close() + request.form['attachment_file'].file.close() media.attachment_files.append(dict( - name=request.POST['attachment_name'] \ - or request.POST['attachment_file'].filename, + name=request.form['attachment_name'] \ + or request.form['attachment_file'].filename, filepath=attachment_public_filepath, created=datetime.utcnow(), )) @@ -155,8 +155,8 @@ def edit_attachments(request, media): messages.add_message( request, messages.SUCCESS, "You added the attachment %s!" \ - % (request.POST['attachment_name'] - or request.POST['attachment_file'].filename)) + % (request.form['attachment_name'] + or request.form['attachment_file'].filename)) return exc.HTTPFound( location=media.url_for_self(request.urlgen)) @@ -183,13 +183,13 @@ def edit_profile(request): else: user = request.user - form = forms.EditProfileForm(request.POST, + form = forms.EditProfileForm(request.form, url=user.get('url'), bio=user.get('bio')) if request.method == 'POST' and form.validate(): - user.url = unicode(request.POST['url']) - user.bio = unicode(request.POST['bio']) + user.url = unicode(request.form['url']) + user.bio = unicode(request.form['bio']) user.save() @@ -210,7 +210,7 @@ def edit_profile(request): @require_active_login def edit_account(request): user = request.user - form = forms.EditAccountForm(request.POST, + form = forms.EditAccountForm(request.form, wants_comment_notification=user.get('wants_comment_notification')) if request.method == 'POST': @@ -268,32 +268,32 @@ def edit_collection(request, collection): description=collection.description) form = forms.EditCollectionForm( - request.POST, + request.form, **defaults) if request.method == 'POST' and form.validate(): # Make sure there isn't already a Collection with such a slug # and userid. slug_used = check_collection_slug_used(request.db, collection.creator, - request.POST['slug'], collection.id) + request.form['slug'], collection.id) # Make sure there isn't already a Collection with this title existing_collection = request.db.Collection.find_one({ 'creator': request.user._id, - 'title':request.POST['title']}) + 'title':request.form['title']}) if existing_collection and existing_collection.id != collection.id: messages.add_message( request, messages.ERROR, _('You already have a collection called "%s"!') % \ - request.POST['title']) + request.form['title']) elif slug_used: form.slug.errors.append( _(u'A collection with that slug already exists for this user.')) else: - collection.title = unicode(request.POST['title']) - collection.description = unicode(request.POST.get('description')) - collection.slug = unicode(request.POST['slug']) + collection.title = unicode(request.form['title']) + collection.description = unicode(request.form.get('description')) + collection.slug = unicode(request.form['slug']) collection.save() diff --git a/mediagoblin/meddleware/csrf.py b/mediagoblin/meddleware/csrf.py index 74502dc4..1488e6d9 100644 --- a/mediagoblin/meddleware/csrf.py +++ b/mediagoblin/meddleware/csrf.py @@ -132,7 +132,7 @@ class CsrfMeddleware(BaseMeddleware): return HTTPForbidden() # get the form token and confirm it matches - form = CsrfForm(request.POST) + form = CsrfForm(request.form) if form.validate(): form_token = form.csrf_token.data diff --git a/mediagoblin/plugins/api/views.py b/mediagoblin/plugins/api/views.py index 5f38f8d2..a1b1bcac 100644 --- a/mediagoblin/plugins/api/views.py +++ b/mediagoblin/plugins/api/views.py @@ -20,8 +20,8 @@ import uuid from os.path import splitext from webob import exc, Response -from cgi import FieldStorage from werkzeug.utils import secure_filename +from werkzeug.datastructures import FileStorage from celery import registry from mediagoblin.db.util import ObjectId @@ -29,13 +29,10 @@ from mediagoblin.decorators import require_active_login from mediagoblin.processing import mark_entry_failed from mediagoblin.processing.task import ProcessMedia from mediagoblin.meddleware.csrf import csrf_exempt -from mediagoblin.media_types import sniff_media, InvalidFileType, \ - FileTypeNotSupported +from mediagoblin.media_types import sniff_media from mediagoblin.plugins.api.tools import api_auth, get_entry_serializable, \ json_response -from mediagoblin.plugins.api import config - _log = logging.getLogger(__name__) @@ -52,24 +49,24 @@ def post_entry(request): _log.debug('Must POST against post_entry') return exc.HTTPBadRequest() - if not 'file' in request.POST \ - or not isinstance(request.POST['file'], FieldStorage) \ - or not request.POST['file'].file: + if not 'file' in request.files \ + or not isinstance(request.files['file'], FileStorage) \ + or not request.files['file'].stream: _log.debug('File field not found') return exc.HTTPBadRequest() - media_file = request.POST['file'] + media_file = request.files['file'] media_type, media_manager = sniff_media(media_file) entry = request.db.MediaEntry() entry.id = ObjectId() entry.media_type = unicode(media_type) - entry.title = unicode(request.POST.get('title') + entry.title = unicode(request.form.get('title') or splitext(media_file.filename)[0]) - entry.description = unicode(request.POST.get('description')) - entry.license = unicode(request.POST.get('license', '')) + entry.description = unicode(request.form.get('description')) + entry.license = unicode(request.form.get('license', '')) entry.uploader = request.user.id @@ -88,7 +85,7 @@ def post_entry(request): queue_filepath, 'wb') with queue_file: - queue_file.write(request.POST['file'].file.read()) + queue_file.write(request.files['file'].stream.read()) # Add queued filename to the entry entry.queued_media_file = queue_filepath @@ -98,10 +95,10 @@ def post_entry(request): # Save now so we have this data before kicking off processing entry.save(validate=True) - if request.POST.get('callback_url'): + if request.form.get('callback_url'): metadata = request.db.ProcessingMetaData() metadata.media_entry = entry - metadata.callback_url = unicode(request.POST['callback_url']) + metadata.callback_url = unicode(request.form['callback_url']) metadata.save() # Pass off to processing diff --git a/mediagoblin/plugins/oauth/README.rst b/mediagoblin/plugins/oauth/README.rst index 0c278e3e..405a67e2 100644 --- a/mediagoblin/plugins/oauth/README.rst +++ b/mediagoblin/plugins/oauth/README.rst @@ -133,10 +133,12 @@ Incapabilities ============== - Only `bearer tokens`_ are issued. -- `Access Token Scope`_ - `Implicit Grant`_ +- `Force TLS for token endpoint`_ - This one is up the the siteadmin +- Authorization `scope`_ and `state` - ... .. _`bearer tokens`: http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-08 -.. _`Access Token Scope`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.3 +.. _`scope`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.3 .. _`Implicit Grant`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-4.2 +.. _`Force TLS for token endpoint`: http://tools.ietf.org/html/draft-ietf-oauth-v2-25#section-3.2 diff --git a/mediagoblin/plugins/oauth/views.py b/mediagoblin/plugins/oauth/views.py index 1c0d7f86..cf605fd2 100644 --- a/mediagoblin/plugins/oauth/views.py +++ b/mediagoblin/plugins/oauth/views.py @@ -41,15 +41,15 @@ def register_client(request): ''' Register an OAuth client ''' - form = ClientRegistrationForm(request.POST) + form = ClientRegistrationForm(request.form) if request.method == 'POST' and form.validate(): client = OAuthClient() - client.name = unicode(request.POST['name']) - client.description = unicode(request.POST['description']) - client.type = unicode(request.POST['type']) + client.name = unicode(request.form['name']) + client.description = unicode(request.form['description']) + client.type = unicode(request.form['type']) client.owner_id = request.user.id - client.redirect_uri = unicode(request.POST['redirect_uri']) + client.redirect_uri = unicode(request.form['redirect_uri']) client.generate_identifier() client.generate_secret() @@ -86,7 +86,7 @@ def list_connections(request): @require_active_login def authorize_client(request): - form = AuthorizationForm(request.POST) + form = AuthorizationForm(request.form) client = OAuthClient.query.filter(OAuthClient.id == form.client_id.data).first() @@ -169,7 +169,7 @@ def authorize(request, client): # code parameter # - on deny: send the user agent back to the redirect uri with error # information - form = AuthorizationForm(request.POST) + form = AuthorizationForm(request.form) form.client_id.data = client.id form.next.data = request.url return render_to_response( @@ -185,6 +185,31 @@ def access_token(request): request.GET.get('code')).first() if code: + if code.client.type == u'confidential': + client_identifier = request.GET.get('client_id') + + if not client_identifier: + return json_response({ + 'error': 'invalid_request', + 'error_description': + 'Missing client_id in request'}) + + client_secret = request.GET.get('client_secret') + + if not client_secret: + return json_response({ + 'error': 'invalid_request', + 'error_description': + 'Missing client_secret in request'}) + + if not client_secret == code.client.secret or \ + not client_identifier == code.client.identifier: + return json_response({ + 'error': 'invalid_client', + 'error_description': + 'The client_id or client_secret does not match the' + ' code'}) + token = OAuthToken() token.token = unicode(uuid4()) token.user = code.user @@ -194,10 +219,17 @@ def access_token(request): access_token_data = { 'access_token': token.token, 'token_type': 'bearer', - 'expires_in': - (token.expires - datetime.now()).total_seconds()} + 'expires_in': int( + round( + (token.expires - datetime.now()).total_seconds()))} return json_response(access_token_data, _disable_cors=True) - - error_data = { - 'error': 'Incorrect code'} - return Response(json.dumps(error_data)) + else: + return json_response({ + 'error': 'invalid_request', + 'error_description': + 'Invalid code'}) + else: + return json_response({ + 'error': 'invalid_request', + 'error_descriptin': + 'Missing `code` parameter in request'}) diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py index 7974bec0..02026f45 100644 --- a/mediagoblin/submit/views.py +++ b/mediagoblin/submit/views.py @@ -47,7 +47,7 @@ def submit_start(request): """ First view for submitting a file. """ - submit_form = submit_forms.SubmitStartForm(request.POST) + submit_form = submit_forms.SubmitStartForm(request.form) if request.method == 'POST' and submit_form.validate(): if not ('file' in request.files @@ -69,18 +69,18 @@ def submit_start(request): entry.id = ObjectId() entry.media_type = unicode(media_type) entry.title = ( - unicode(request.POST['title']) + unicode(request.form['title']) or unicode(splitext(filename)[0])) - entry.description = unicode(request.POST.get('description')) + entry.description = unicode(request.form.get('description')) - entry.license = unicode(request.POST.get('license', "")) or None + entry.license = unicode(request.form.get('license', "")) or None entry.uploader = request.user._id # Process the user's folksonomy "tags" entry.tags = convert_to_tag_list_of_dicts( - request.POST.get('tags')) + request.form.get('tags')) # Generate a slug from the title entry.generate_slug() @@ -188,16 +188,16 @@ def add_collection(request, media=None): """ View to create a new collection """ - submit_form = submit_forms.AddCollectionForm(request.POST) + submit_form = submit_forms.AddCollectionForm(request.form) if request.method == 'POST' and submit_form.validate(): try: collection = request.db.Collection() collection.id = ObjectId() - collection.title = unicode(request.POST['title']) + collection.title = unicode(request.form['title']) - collection.description = unicode(request.POST.get('description')) + collection.description = unicode(request.form.get('description')) collection.creator = request.user._id collection.generate_slug() diff --git a/mediagoblin/tests/test_http_callback.py b/mediagoblin/tests/test_http_callback.py index bce479ca..9e48d056 100644 --- a/mediagoblin/tests/test_http_callback.py +++ b/mediagoblin/tests/test_http_callback.py @@ -32,8 +32,6 @@ class TestHTTPCallback(object): self.user_password = 'secret' self.user = fixture_add_user('call_back', self.user_password) - self.oauth = oauth.TestOAuth() - self.oauth.setUp() self.login() @@ -42,10 +40,11 @@ class TestHTTPCallback(object): 'username': self.user.username, 'password': self.user_password}) - def get_access_token(self, client_id, code): + def get_access_token(self, client_id, client_secret, code): response = self.app.get('/oauth/access_token', { 'code': code, - 'client_id': client_id}) + 'client_id': client_id, + 'client_secret': client_secret}) response_data = json.loads(response.body) @@ -53,18 +52,28 @@ class TestHTTPCallback(object): def test_callback(self): ''' Test processing HTTP callback ''' + + self.oauth = oauth.TestOAuth() + self.oauth.setUp() + redirect, client_id = self.oauth.test_4_authorize_confidential_client() code = parse_qs(urlparse(redirect.location).query)['code'][0] - access_token = self.get_access_token(client_id, code) + client = self.db.OAuthClient.query.filter( + self.db.OAuthClient.identifier == unicode(client_id)).first() + + client_secret = client.secret + + access_token = self.get_access_token(client_id, client_secret, code) callback_url = 'https://foo.example?secrettestmediagoblinparam' - res = self.app.post('/api/submit?client_id={0}&access_token={1}'\ - .format( + res = self.app.post('/api/submit?client_id={0}&access_token={1}\ +&client_secret={2}'.format( client_id, - access_token), { + access_token, + client_secret), { 'title': 'Test', 'callback_url': callback_url}, upload_files=[('file', GOOD_PNG)]) diff --git a/mediagoblin/tools/translate.py b/mediagoblin/tools/translate.py index 71c3b793..cdc827a0 100644 --- a/mediagoblin/tools/translate.py +++ b/mediagoblin/tools/translate.py @@ -60,7 +60,7 @@ def get_locale_from_request(request): Figure out what target language is most appropriate based on the request """ - request_form = request.GET or request.POST + request_form = request.GET or request.form if request_form.has_key('lang'): return locale_to_lower_upper(request_form['lang']) diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index e5131b02..c26bd340 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -126,7 +126,7 @@ def media_home(request, media, page, **kwargs): comments = pagination() - comment_form = user_forms.MediaCommentForm(request.POST) + comment_form = user_forms.MediaCommentForm(request.form) media_template_name = get_media_manager( media.media_type)['display_template'] @@ -152,7 +152,7 @@ def media_post_comment(request, media): comment = request.db.MediaComment() comment.media_entry = media.id comment.author = request.user.id - comment.content = unicode(request.POST['comment_content']) + comment.content = unicode(request.form['comment_content']) if not comment.content.strip(): messages.add_message( @@ -180,7 +180,7 @@ def media_post_comment(request, media): @require_active_login def media_collect(request, media): - form = user_forms.MediaCollectForm(request.POST) + form = user_forms.MediaCollectForm(request.form) filt = (request.db.Collection.creator == request.user.id) form.collection.query = request.db.Collection.query.filter( filt).order_by(request.db.Collection.title) @@ -192,15 +192,15 @@ def media_collect(request, media): collection_item = request.db.CollectionItem() # If the user is adding a new collection, use that - if request.POST['collection_title']: + if request.form['collection_title']: collection = request.db.Collection() collection.id = ObjectId() collection.title = ( - unicode(request.POST['collection_title'])) + unicode(request.form['collection_title'])) collection.description = unicode( - request.POST.get('collection_description')) + request.form.get('collection_description')) collection.creator = request.user._id collection.generate_slug() @@ -225,7 +225,7 @@ def media_collect(request, media): # Otherwise, use the collection selected from the drop-down else: collection = request.db.Collection.find_one({ - '_id': request.POST.get('collection')}) + '_id': request.form.get('collection')}) collection_item.collection = collection.id # Make sure the user actually selected a collection @@ -244,7 +244,7 @@ def media_collect(request, media): else: collection_item.media_entry = media.id collection_item.author = request.user.id - collection_item.note = unicode(request.POST['note']) + collection_item.note = unicode(request.form['note']) collection_item.save(validate=True) collection.items = collection.items + 1 @@ -277,7 +277,7 @@ def media_collect(request, media): @user_may_delete_media def media_confirm_delete(request, media): - form = user_forms.ConfirmDeleteForm(request.POST) + form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): if form.confirm.data is True: @@ -360,7 +360,7 @@ def user_collection(request, page): @user_may_alter_collection def collection_item_confirm_remove(request, collection_item): - form = user_forms.ConfirmCollectionItemRemoveForm(request.POST) + form = user_forms.ConfirmCollectionItemRemoveForm(request.form) if request.method == 'POST' and form.validate(): username = collection_item.in_collection.get_creator.username @@ -405,7 +405,7 @@ def collection_item_confirm_remove(request, collection_item): @user_may_alter_collection def collection_confirm_delete(request, collection): - form = user_forms.ConfirmDeleteForm(request.POST) + form = user_forms.ConfirmDeleteForm(request.form) if request.method == 'POST' and form.validate(): |