Ensure colorbars can't escape their containers. #352
[zzz-spline-users.git] / splinext / users / controllers / users.py
1 import logging
2 import unicodedata
3
4 from wtforms import Form, ValidationError, fields, validators, widgets
5
6 from pylons import config, request, response, session, tmpl_context as c, url
7 from pylons.controllers.util import abort, redirect
8 from pylons.decorators.secure import authenticate_form
9 from routes import request_config
10 from sqlalchemy.orm.exc import NoResultFound
11
12 from spline.model import meta
13 from spline.lib import helpers as h
14 from spline.lib.base import BaseController, render
15 from splinext.users import model as users_model
16
17 log = logging.getLogger(__name__)
18
19
20 class ProfileEditForm(Form):
21 name = fields.TextField(u'Display name', [validators.Required()])
22
23 def validate_name(form, field):
24 if not 1 < len(field.data) <= 20:
25 raise ValidationError("Name can't be longer than 20 characters")
26
27 any_real_characters = False
28 for char in field.data:
29 cat = unicodedata.category(char)
30
31 # Non-spacing marks and spaces don't count as letters
32 if cat not in ('Mn', 'Zs'):
33 any_real_characters = True
34
35 # Disallow control characters, format characters, non-assigned,
36 # private use, surrogates, spacing-combining marks (for Arabic,
37 # etc), enclosing marks (millions sign), line-spacing,
38 # paragraph-spacing.
39 # This also, thankfully, includes the RTL characters.
40 if cat in ('Cc', 'Cf', 'Cn', 'Co', 'Cs', 'Mc', 'Me', 'Zl', 'Zp'):
41 raise ValidationError("Please don't play stupid Unicode tricks")
42
43 class UsersController(BaseController):
44
45 def list(self):
46 c.users = meta.Session.query(users_model.User) \
47 .order_by(users_model.User.id.asc())
48 return render('/users/list.mako')
49
50 def profile(self, id, name=None):
51 """Main user profile.
52
53 URL is /users/id:name, where 'name' only exists for readability and is
54 entirely optional and ignored.
55 """
56
57 c.page_user = meta.Session.query(users_model.User).get(id)
58 if not c.page_user:
59 abort(404)
60
61 return render('/users/profile.mako')
62
63 def profile_edit(self, id, name=None):
64 """Main user profile editing."""
65 c.page_user = meta.Session.query(users_model.User).get(id)
66 if not c.page_user:
67 abort(404)
68
69 # XXX could use some real permissions
70 if c.page_user != c.user:
71 abort(403)
72
73 c.form = ProfileEditForm(request.params,
74 name=c.page_user.name,
75 )
76
77 return render('/users/profile_edit.mako')
78
79 @authenticate_form
80 def profile_edit_commit(self, id, name=None):
81 """Save profile changes."""
82 c.page_user = meta.Session.query(users_model.User).get(id)
83 if not c.page_user:
84 abort(404)
85
86 # XXX could use some real permissions
87 if c.page_user != c.user:
88 abort(403)
89
90 c.form = ProfileEditForm(request.params,
91 name=c.page_user.name,
92 )
93
94 if not c.form.validate():
95 return render('/users/profile_edit.mako')
96
97
98 c.page_user.name = c.form.name.data
99
100 meta.Session.add(c.page_user)
101 meta.Session.commit()
102
103 h.flash('Saved your profile.', icon='tick')
104
105 redirect(
106 url(controller='users', action='profile',
107 id=c.page_user.id, name=c.page_user.name),
108 code=303,
109 )