Very simple profile editing.
authorEevee <git@veekun.com>
Wed, 5 May 2010 06:47:17 +0000 (23:47 -0700)
committerEevee <git@veekun.com>
Thu, 6 May 2010 07:03:59 +0000 (00:03 -0700)
spline/plugins/users/__init__.py
spline/plugins/users/controllers/users.py
spline/plugins/users/templates/users/profile.mako [new file with mode: 0644]
spline/plugins/users/templates/users/profile_edit.mako [new file with mode: 0644]
spline/plugins/users/templates/users/view.mako [deleted file]
spline/plugins/users/templates/widgets/user_state.mako

index 5e006cf..4ce4465 100644 (file)
@@ -13,12 +13,17 @@ import spline.plugins.users.model
 
 def add_routes_hook(map, *args, **kwargs):
     """Hook to inject some of our behavior into the routes configuration."""
 
 def add_routes_hook(map, *args, **kwargs):
     """Hook to inject some of our behavior into the routes configuration."""
+    # Login, logout
     map.connect('/accounts/login_begin', controller='accounts', action='login_begin')
     map.connect('/accounts/login_finish', controller='accounts', action='login_finish')
     map.connect('/accounts/logout', controller='accounts', action='logout')
 
     map.connect('/accounts/login_begin', controller='accounts', action='login_begin')
     map.connect('/accounts/login_finish', controller='accounts', action='login_finish')
     map.connect('/accounts/logout', controller='accounts', action='logout')
 
-    map.connect('/users/{id};{name}', controller='users', action='view')
-    map.connect('/users/{id}', controller='users', action='view')
+    # Self-admin
+    map.connect('/users/{id};{name}/edit', controller='users', action='profile_edit')
+
+    # Public per-user pages
+    map.connect('/users/{id};{name}', controller='users', action='profile')
+    map.connect('/users/{id}', controller='users', action='profile')
 
 def check_userid_hook(action, **params):
     """Hook to see if a user is logged in and, if so, stick a user object in
 
 def check_userid_hook(action, **params):
     """Hook to see if a user is logged in and, if so, stick a user object in
index d64d39f..6cb36d5 100644 (file)
@@ -1,4 +1,7 @@
 import logging
 import logging
+import unicodedata
+
+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_to
 
 from pylons import config, request, response, session, tmpl_context as c, url
 from pylons.controllers.util import abort, redirect_to
@@ -12,6 +15,30 @@ from spline.lib.base import BaseController, render
 
 log = logging.getLogger(__name__)
 
 
 log = logging.getLogger(__name__)
 
+
+class ProfileEditForm(Form):
+    name = fields.TextField(u'Display name', [validators.Required()])
+
+    def validate_name(form, field):
+        if not 1 < len(field.data) <= 20:
+            raise ValidationError("Name can't be longer than 20 characters")
+
+        any_real_characters = False
+        for char in field.data:
+            cat = unicodedata.category(char)
+
+            # Non-spacing marks and spaces don't count as letters
+            if cat not in ('Mn', 'Zs'):
+                any_real_characters = True
+
+            # Disallow control characters, format characters, non-assigned,
+            # private use, surrogates, spacing-combining marks (for Arabic,
+            # etc), enclosing marks (millions sign), line-spacing,
+            # paragraph-spacing.
+            # This also, thankfully, includes the RTL characters.
+            if cat in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Mc', 'Me', 'Zl', 'Zp'):
+                raise ValidationError("Please don't play stupid Unicode tricks")
+
 class UsersController(BaseController):
 
     def index(self):
 class UsersController(BaseController):
 
     def index(self):
@@ -20,8 +47,8 @@ class UsersController(BaseController):
         # or, Return a response
         return 'stub'
 
         # or, Return a response
         return 'stub'
 
-    def view(self, id, name=None):
-        """User page.
+    def profile(self, id, name=None):
+        """Main user profile.
 
         URL is /users/id:name, where 'name' only exists for readability and is
         entirely optional and ignored.
 
         URL is /users/id:name, where 'name' only exists for readability and is
         entirely optional and ignored.
@@ -31,4 +58,33 @@ class UsersController(BaseController):
         if not c.page_user:
             abort(404)
 
         if not c.page_user:
             abort(404)
 
-        return render('/users/view.mako')
+        return render('/users/profile.mako')
+
+    def profile_edit(self, id, name=None):
+        """Main user profile editing."""
+        c.page_user = meta.Session.query(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 request.method != 'POST' or not c.form.validate():
+            return render('/users/profile_edit.mako')
+
+
+        c.page_user.name = c.form.name.data
+
+        meta.Session.add(c.page_user)
+        meta.Session.commit()
+
+        h.flash('Saved your profile.', icon='tick')
+
+        redirect_to(controller='users', action='profile',
+                    id=c.page_user.id, name=c.page_user.name.lower(),
+                    _code=303)
diff --git a/spline/plugins/users/templates/users/profile.mako b/spline/plugins/users/templates/users/profile.mako
new file mode 100644 (file)
index 0000000..bf0a630
--- /dev/null
@@ -0,0 +1,16 @@
+<%inherit file="/base.mako" />
+<%namespace name="userlib" file="/users/lib.mako" />
+
+<%def name="title()">${c.page_user.name} - Users</%def>
+
+<h1>${c.page_user.name}'s profile</h1>
+
+<p>
+    Profile for ${c.page_user.name} ${userlib.color_bar(c.page_user)}.
+    % if c.page_user == c.user:
+    <a href="${url(controller='users', action='profile_edit', id=c.page_user.id, name=c.page_user.name.lower())}">
+        <img src="${h.static_uri('spline', 'icons/user--pencil.png')}" alt="">
+        Edit
+    </a>
+    % endif
+</p>
diff --git a/spline/plugins/users/templates/users/profile_edit.mako b/spline/plugins/users/templates/users/profile_edit.mako
new file mode 100644 (file)
index 0000000..0f81df0
--- /dev/null
@@ -0,0 +1,18 @@
+<%inherit file="/base.mako" />
+<%namespace name="lib" file="/lib.mako" />
+<%namespace name="userlib" file="/users/lib.mako" />
+
+<%def name="title()">${c.page_user.name} - Users</%def>
+<%def name="title_in_page()">User: ${c.page_user.name}</%def>
+
+<h1>Edit ${c.page_user.name}'s profile</h1>
+
+${h.form(url.current())}
+<dl>
+    <dt>Color ID</dt>
+    <dd>${userlib.color_bar(c.page_user)}</dd>
+    ${lib.field('name')}
+
+    <dd><button type="submit">Save</button></dd>
+</dl>
+${h.end_form()}
diff --git a/spline/plugins/users/templates/users/view.mako b/spline/plugins/users/templates/users/view.mako
deleted file mode 100644 (file)
index 6462646..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<%inherit file="/base.mako" />
-<%def name="title()">${c.page_user.name} - Users</%def>
-<%def name="title_in_page()">User: ${c.page_user.name}</%def>
-
-<h1>${c.page_user.name}</h1>
-
-A user!
index 47c36f1..06c6e70 100644 (file)
@@ -1,7 +1,7 @@
 <%namespace name="userlib" file="/users/lib.mako" />
 % if c.user:
 ${h.form(url(controller='accounts', action='logout'), id='user')}
 <%namespace name="userlib" file="/users/lib.mako" />
 % if c.user:
 ${h.form(url(controller='accounts', action='logout'), id='user')}
-    Logged in as ${c.user.name} ${userlib.color_bar(c.user)}.
+    Logged in as <a href="${url(controller='users', action='profile', id=c.user.id, name=c.user.name)}">${c.user.name}</a> ${userlib.color_bar(c.user)}.
     <input type="submit" value="Log out">
 ${h.end_form()}
 % else:
     <input type="submit" value="Log out">
 ${h.end_form()}
 % else: