self.search_base = self.settings.get("ldap_search_base")
def __len__(self):
- count = self.memcache.get("accounts:count")
-
- if count is None:
- count = self._count("(objectClass=person)")
-
- self.memcache.set("accounts:count", count, 300)
-
- return count
+ return self._count("(objectClass=person)")
def __iter__(self):
accounts = self._search("(objectClass=person)")
# Avatar
- def has_avatar(self):
- has_avatar = self.memcache.get("accounts:%s:has-avatar" % self.uid)
- if has_avatar is None:
- has_avatar = True if self.get_avatar() else False
+ @property
+ def avatar_hash(self):
+ payload = (
+ self.uid,
+ "%s" % self.modified_at,
+ )
+
+ # String the payload together
+ payload = "-".join(payload)
- # Cache avatar status for up to 24 hours
- self.memcache.set("accounts:%s:has-avatar" % self.uid, has_avatar, 3600 * 24)
+ # Run MD5() over the payload
+ h = hashlib.new("md5", payload.encode())
- return has_avatar
+ return h.hexdigest()[:7]
def avatar_url(self, size=None, absolute=False):
+ # This cannot be async because we are calling it from the template engine
url = "/users/%s.jpg?h=%s" % (self.uid, self.avatar_hash)
# Return an absolute URL
return url
- def get_avatar(self, size=None):
+ async def get_avatar(self, size=None):
photo = self._get_bytes("jpegPhoto")
# Exit if no avatar is available
return photo
# Try to retrieve something from the cache
- avatar = self.memcache.get("accounts:%s:avatar:%s" % (self.dn, size))
+ avatar = await self.backend.cache.get("accounts:%s:avatar:%s" % (self.dn, size))
if avatar:
return avatar
avatar = util.generate_thumbnail(photo, size, square=True)
# Save to cache for 15m
- self.memcache.set("accounts:%s:avatar:%s" % (self.dn, size), avatar, 900)
+ await self.backend.cache.set("accounts:%s:avatar:%s" % (self.dn, size), avatar, 900)
return avatar
- @property
- def avatar_hash(self):
- hash = self.memcache.get("accounts:%s:avatar-hash" % self.dn)
- if not hash:
- h = hashlib.new("md5")
- h.update(self.get_avatar() or b"")
- hash = h.hexdigest()[:7]
-
- self.memcache.set("accounts:%s:avatar-hash" % self.dn, hash, 86400)
-
- return hash
-
def upload_avatar(self, avatar):
self._set("jpegPhoto", avatar)
- # Delete cached avatar status
- self.memcache.delete("accounts:%s:has-avatar" % self.dn)
-
- # Delete avatar hash
- self.memcache.delete("accounts:%s:avatar-hash" % self.dn)
-
# Consent to promotional emails
def get_consents_to_promotional_emails(self):
class AvatarHandler(base.BaseHandler):
- def get(self, uid):
+ async def get(self, uid):
# Get the desired size of the avatar file
size = self.get_argument("size", None)
self.set_expires(31536000)
# Resize avatar
- avatar = account.get_avatar(size)
+ avatar = await account.get_avatar(size)
# If there is no avatar, we serve a default image
if not avatar:
logging.debug("No avatar uploaded for %s" % account)
# Generate a random avatar with only one letter
- avatar = self._get_avatar(account, size=size)
+ avatar = await self._get_avatar(account, size=size)
# Guess content type
type = imghdr.what(None, avatar)
# Deliver payload
self.finish(avatar)
- def _get_avatar(self, account, size=None, **args):
+ async def _get_avatar(self, account, size=None, **args):
letter = ("%s" % account)[0].upper()
if size is None:
key = "avatar:letter:%s:%s" % (letter, size)
# Fetch avatar from the cache
- avatar = self.memcached.get(key)
+ avatar = await self.backend.cache.get(key)
if not avatar:
avatar = self._make_avatar(letter, size=size, **args)
# Cache for forever
- self.memcached.set(key, avatar)
+ await self.backend.cache.set(key, avatar)
return avatar
self.render("users/edit.html", account=account, countries=countries.get_all())
@tornado.web.authenticated
- def post(self, uid):
+ async def post(self, uid):
account = self.backend.accounts.get_by_uid(uid)
if not account:
raise tornado.web.HTTPError(404, "Could not find account %s" % uid)