CSRF protection. #361 veekun-promotions/2010112001
authorEevee <git@veekun.com>
Mon, 8 Nov 2010 07:29:35 +0000 (23:29 -0800)
committerEevee <git@veekun.com>
Mon, 8 Nov 2010 07:29:35 +0000 (23:29 -0800)
splinext/users/__init__.py
splinext/users/controllers/accounts.py
splinext/users/controllers/users.py
splinext/users/templates/users/profile_edit.mako
splinext/users/templates/widgets/user_state.mako

index e395542..8839e9d 100644 (file)
@@ -12,12 +12,8 @@ from splinext.users import model as users_model
 
 def add_routes_hook(map, *args, **kwargs):
     """Hook to inject some of our behavior into the routes configuration."""
-    def id_is_numeric(environ, result):
-        try:
-            int(result['id'])
-            return True
-        except (KeyError, ValueError):
-            return False
+    require_GET = dict(conditions=dict(method=['GET']))
+    require_POST = dict(conditions=dict(method=['POST']))
 
     # Login, logout
     map.connect('/accounts/login', controller='accounts', action='login')
@@ -26,15 +22,13 @@ def add_routes_hook(map, *args, **kwargs):
     map.connect('/accounts/logout', controller='accounts', action='logout')
 
     # Self-admin
-    map.connect('/users/{id};{name}/edit', controller='users', action='profile_edit',
-        conditions=dict(function=id_is_numeric))
+    map.connect(r'/users/{id:\d+};{name}/edit', controller='users', action='profile_edit', **require_GET)
+    map.connect(r'/users/{id:\d+};{name}/edit', controller='users', action='profile_edit_commit', **require_POST)
 
     # Public user pages
     map.connect('/users', controller='users', action='list')
-    map.connect('/users/{id};{name}', controller='users', action='profile',
-        conditions=dict(function=id_is_numeric))
-    map.connect('/users/{id}', controller='users', action='profile',
-        conditions=dict(function=id_is_numeric))
+    map.connect(r'/users/{id:\d+};{name}', controller='users', action='profile')
+    map.connect(r'/users/{id:\d+}', controller='users', action='profile')
 
     # Big-boy admin
     map.connect('/admin/users/permissions', controller='admin_users', action='permissions')
index 45d3b1e..55b6319 100644 (file)
@@ -7,6 +7,7 @@ from sqlalchemy.orm.exc import NoResultFound
 
 from pylons import config, request, response, session, tmpl_context as c, url
 from pylons.controllers.util import abort, redirect
+from pylons.decorators.secure import authenticate_form
 from routes import request_config
 
 from spline.model import meta
@@ -108,6 +109,7 @@ class AccountsController(BaseController):
 
         redirect(url('/'), code=303)
 
+    @authenticate_form
     def logout(self):
         """Logs the user out."""
 
index 5e3826c..4f46179 100644 (file)
@@ -5,6 +5,7 @@ from wtforms import Form, ValidationError, fields, validators, widgets
 
 from pylons import config, request, response, session, tmpl_context as c, url
 from pylons.controllers.util import abort, redirect
+from pylons.decorators.secure import authenticate_form
 from routes import request_config
 from sqlalchemy.orm.exc import NoResultFound
 
@@ -73,7 +74,24 @@ class UsersController(BaseController):
             name=c.page_user.name,
         )
 
-        if request.method != 'POST' or not c.form.validate():
+        return render('/users/profile_edit.mako')
+
+    @authenticate_form
+    def profile_edit_commit(self, id, name=None):
+        """Save profile changes."""
+        c.page_user = meta.Session.query(users_model.User).get(id)
+        if not c.page_user:
+            abort(404)
+
+        # XXX could use some real permissions
+        if c.page_user != c.user:
+            abort(403)
+
+        c.form = ProfileEditForm(request.params,
+            name=c.page_user.name,
+        )
+
+        if not c.form.validate():
             return render('/users/profile_edit.mako')
 
 
index 0f81df0..b70cebe 100644 (file)
@@ -7,7 +7,7 @@
 
 <h1>Edit ${c.page_user.name}'s profile</h1>
 
-${h.form(url.current())}
+${h.secure_form(url.current(controller='users', action='profile_edit_commit'))}
 <dl>
     <dt>Color ID</dt>
     <dd>${userlib.color_bar(c.page_user)}</dd>
index adf816b..58be697 100644 (file)
@@ -1,6 +1,6 @@
 <%namespace name="userlib" file="/users/lib.mako" />
 % if c.user:
-${h.form(url(controller='accounts', action='logout'), id='user')}
+${h.secure_form(url(controller='accounts', action='logout'), id='user')}
     Logged in as <a href="${url(controller='users', action='profile', id=c.user.id, name=c.user.name)}">${userlib.color_bar(c.user)} ${c.user.name}</a>.
     <input type="submit" value="Log out">
 ${h.end_form()}