]>
git.ipfire.org Git - ipfire.org.git/blob - src/web/users.py
6dee34b9585074a06373bf9799862d1800d5ada4
11 from .. import countries
14 from . import ui_modules
16 COLOUR_LIGHT
= (237,232,232)
17 COLOUR_DARK
= (49,53,60)
19 class IndexHandler(base
.BaseHandler
):
20 @tornado.web
.authenticated
25 q
= self
.get_argument("q", None)
29 results
= self
.backend
.accounts
.search(q
)
31 self
.render("users/index.html", q
=q
, results
=results
)
34 class ShowHandler(base
.BaseHandler
):
35 @tornado.web
.authenticated
37 account
= self
.backend
.accounts
.get_by_uid(uid
)
39 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
41 self
.render("users/show.html", account
=account
)
44 class AvatarHandler(base
.BaseHandler
):
46 # Get the desired size of the avatar file
47 size
= self
.get_argument("size", None)
51 except (TypeError, ValueError):
54 logging
.debug("Querying for avatar of %s" % uid
)
57 account
= self
.backend
.accounts
.get_by_uid(uid
)
59 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
61 # Allow downstream to cache this for a year
62 self
.set_expires(31536000)
65 avatar
= account
.get_avatar(size
)
67 # If there is no avatar, we serve a default image
69 logging
.debug("No avatar uploaded for %s" % account
)
71 # Generate a random avatar with only one letter
72 avatar
= self
._get
_avatar
(account
, size
=size
)
75 type = imghdr
.what(None, avatar
)
77 # If we could not guess the type, we will try something else
79 # Could this be an SVG file?
80 if avatar
.startswith(b
"<"):
83 # Set headers about content
84 self
.set_header("Content-Disposition", "inline; filename=\"%s.%s\"" % (account
.uid
, type))
86 self
.set_header("Content-Type", "image/%s" % type)
91 def _get_avatar(self
, account
, size
=None, **args
):
92 letter
= ("%s" % account
)[0].upper()
97 # The generated avatar cannot be larger than 1024px
102 key
= "avatar:letter:%s:%s" % (letter
, size
)
104 # Fetch avatar from the cache
105 avatar
= self
.memcached
.get(key
)
107 avatar
= self
._make
_avatar
(letter
, size
=size
, **args
)
110 self
.memcached
.set(key
, avatar
)
114 def _make_avatar(self
, letter
, format
="PNG", size
=None, **args
):
115 # Generate an image of the correct size
116 image
= PIL
.Image
.new("RGBA", (size
, size
), COLOUR_LIGHT
)
119 draw
= PIL
.ImageDraw
.Draw(image
)
122 font
= PIL
.ImageFont
.truetype(os
.path
.join(
123 self
.application
.settings
.get("static_path", ""),
124 "fonts/Prompt-Bold.ttf"
125 ), size
, encoding
="unic")
127 # Determine size of the printed letter
128 w
, h
= font
.getsize(letter
)
130 # Mukta seems to be very broken and the height needs to be corrected
133 # Draw the letter in the center
134 draw
.text(((size
- w
) / 2, (size
- h
) / 2), letter
,
135 font
=font
, fill
=COLOUR_DARK
)
137 with io
.BytesIO() as f
:
138 # If writing out the image does not work with optimization,
139 # we try to write it out without any optimization.
141 image
.save(f
, format
, optimize
=True, **args
)
143 image
.save(f
, format
, **args
)
148 class EditHandler(base
.BaseHandler
):
149 @tornado.web
.authenticated
151 account
= self
.backend
.accounts
.get_by_uid(uid
)
153 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
155 # Check for permissions
156 if not account
.can_be_managed_by(self
.current_user
):
157 raise tornado
.web
.HTTPError(403, "%s cannot manage %s" % (self
.current_user
, account
))
159 self
.render("users/edit.html", account
=account
, countries
=countries
.get_all())
161 @tornado.web
.authenticated
163 account
= self
.backend
.accounts
.get_by_uid(uid
)
165 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
167 # Check for permissions
168 if not account
.can_be_managed_by(self
.current_user
):
169 raise tornado
.web
.HTTPError(403, "%s cannot manage %s" % (self
.current_user
, account
))
171 # Unfortunately this cannot be wrapped into a transaction
173 account
.first_name
= self
.get_argument("first_name")
174 account
.last_name
= self
.get_argument("last_name")
175 account
.nickname
= self
.get_argument("nickname", None)
176 account
.street
= self
.get_argument("street", None)
177 account
.city
= self
.get_argument("city", None)
178 account
.postal_code
= self
.get_argument("postal_code", None)
179 account
.country_code
= self
.get_argument("country_code", None)
180 account
.description
= self
.get_argument("description", None)
184 filename
, data
, mimetype
= self
.get_file("avatar")
186 if not mimetype
.startswith("image/"):
187 raise tornado
.web
.HTTPError(400, "Avatar is not an image file: %s" % mimetype
)
189 account
.upload_avatar(data
)
194 account
.mail_routing_address
= self
.get_argument("mail_routing_address", None)
197 account
.phone_numbers
= self
.get_argument("phone_numbers", "").splitlines()
198 account
.sip_routing_address
= self
.get_argument("sip_routing_address", None)
199 except ldap
.STRONG_AUTH_REQUIRED
as e
:
200 raise tornado
.web
.HTTPError(403, "%s" % e
) from e
202 # Redirect back to user page
203 self
.redirect("/users/%s" % account
.uid
)
206 class DeleteHandler(base
.BaseHandler
):
207 @tornado.web
.authenticated
209 account
= self
.backend
.accounts
.get_by_uid(uid
)
211 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
213 # Check for permissions
214 if not account
.can_be_deleted_by(self
.current_user
):
215 raise tornado
.web
.HTTPError(403, "%s cannot delete %s" % (self
.current_user
, account
))
217 self
.render("users/delete.html", account
=account
)
219 @tornado.web
.authenticated
220 async def post(self
, uid
):
221 account
= self
.backend
.accounts
.get_by_uid(uid
)
223 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
225 # Check for permissions
226 if not account
.can_be_deleted_by(self
.current_user
):
227 raise tornado
.web
.HTTPError(403, "%s cannot delete %s" % (self
.current_user
, account
))
230 with self
.db
.transaction():
231 await account
.delete(self
.current_user
)
233 self
.render("users/deleted.html", account
=account
)
236 class PasswdHandler(base
.BaseHandler
):
237 @tornado.web
.authenticated
239 account
= self
.backend
.accounts
.get_by_uid(uid
)
241 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
243 # Check for permissions
244 if not account
.can_be_managed_by(self
.current_user
):
245 raise tornado
.web
.HTTPError(403, "%s cannot manage %s" % (self
.current_user
, account
))
247 self
.render("users/passwd.html", account
=account
)
249 @tornado.web
.authenticated
251 account
= self
.backend
.accounts
.get_by_uid(uid
)
253 raise tornado
.web
.HTTPError(404, "Could not find account %s" % uid
)
255 # Check for permissions
256 if not account
.can_be_managed_by(self
.current_user
):
257 raise tornado
.web
.HTTPError(403, "%s cannot manage %s" % (self
.current_user
, account
))
259 # Get current password
260 password
= self
.get_argument("password")
263 password1
= self
.get_argument("password1")
264 password2
= self
.get_argument("password2")
266 # Passwords must match
267 if not password1
== password2
:
268 raise tornado
.web
.HTTPError(400, "Passwords do not match")
270 # XXX Check password complexity
272 # Check if old password matches
273 if not account
.check_password(password
):
274 raise tornado
.web
.HTTPError(403, "Incorrect password for %s" % account
)
277 account
.passwd(password1
)
279 # Redirect back to user's page
280 self
.redirect("/users/%s" % account
.uid
)
283 class GroupIndexHandler(base
.BaseHandler
):
284 @tornado.web
.authenticated
286 # Only staff can see other groups
287 if not self
.current_user
.is_staff():
288 raise tornado
.web
.HTTPError(403)
290 self
.render("users/groups/index.html")
293 class GroupShowHandler(base
.BaseHandler
):
294 @tornado.web
.authenticated
296 # Only staff can see other groups
297 if not self
.current_user
.is_staff():
298 raise tornado
.web
.HTTPError(403)
301 group
= self
.backend
.groups
.get_by_gid(gid
)
303 raise tornado
.web
.HTTPError(404, "Could not find group %s" % gid
)
305 self
.render("users/groups/show.html", group
=group
)
308 class ListModule(ui_modules
.UIModule
):
309 def render(self
, accounts
, show_created_at
=False):
310 return self
.render_string("users/modules/list.html", accounts
=accounts
,
311 show_created_at
=show_created_at
)