]>
git.ipfire.org Git - people/shoehn/ipfire.org.git/blob - webapp/backend/accounts.py
e52b1899f99ffcdf61199376758cb681486d2d41
11 from misc
import Object
13 class Accounts(Object
):
16 if not hasattr(self
, "_ldap"):
17 # Connect to LDAP server
18 ldap_uri
= self
.settings
.get("ldap_uri")
19 self
._ldap
= ldap
.initialize(ldap_uri
)
21 # Bind with username and password
22 bind_dn
= self
.settings
.get("ldap_bind_dn")
24 bind_pw
= self
.settings
.get("ldap_bind_pw", "")
25 self
._ldap
.simple_bind(bind_dn
, bind_pw
)
29 def _search(self
, query
, attrlist
=None, limit
=0):
30 logging
.debug("Performing LDAP query: %s" % query
)
32 search_base
= self
.settings
.get("ldap_search_base")
33 results
= self
.ldap
.search_ext_s(search_base
, ldap
.SCOPE_SUBTREE
,
34 query
, attrlist
=attrlist
, sizelimit
=limit
)
38 def search(self
, query
, limit
=0):
39 results
= self
._search
(query
, limit
=limit
)
42 for dn
, attrs
in results
:
43 account
= Account(self
.backend
, dn
, attrs
)
44 accounts
.append(account
)
46 return sorted(accounts
)
48 def search_one(self
, query
):
49 result
= self
.search(query
, limit
=1)
50 assert len(result
) <= 1
56 # Only return developers (group with ID 500)
57 return self
.search("(&(objectClass=posixAccount)(gidNumber=500))")
61 def get_by_uid(self
, uid
):
62 return self
.search_one("(&(objectClass=posixAccount)(uid=%s))" % uid
)
64 def get_by_mail(self
, mail
):
65 return self
.search_one("(&(objectClass=posixAccount)(mail=%s))" % mail
)
69 def find_account(self
, s
):
70 account
= self
.get_by_uid(s
)
74 return self
.get_by_mail(s
)
76 def get_by_sip_id(self
, sip_id
):
77 return self
.search_one("(|(&(objectClass=sipUser)(sipAuthenticationUser=%s)) \
78 (&(objectClass=sipRoutingObject)(sipLocalAddress=%s)))" % (sip_id
, sip_id
))
82 def _cleanup_expired_sessions(self
):
83 self
.db
.execute("DELETE FROM sessions WHERE time_expires <= NOW()")
85 def create_session(self
, account
, host
):
86 self
._cleanup
_expired
_sessions
()
88 res
= self
.db
.get("INSERT INTO sessions(host, uid) VALUES(%s, %s) \
89 RETURNING session_id, time_expires", host
, account
.uid
)
91 # Session could not be created
95 logging
.info("Created session %s for %s which expires %s" \
96 % (res
.session_id
, account
, res
.time_expires
))
97 return res
.session_id
, res
.time_expires
99 def destroy_session(self
, session_id
, host
):
100 logging
.info("Destroying session %s" % session_id
)
102 self
.db
.execute("DELETE FROM sessions \
103 WHERE session_id = %s AND host = %s", session_id
, host
)
104 self
._cleanup
_expired
_sessions
()
106 def get_by_session(self
, session_id
, host
):
107 logging
.debug("Looking up session %s" % session_id
)
109 res
= self
.db
.get("SELECT uid FROM sessions WHERE session_id = %s \
110 AND host = %s AND NOW() BETWEEN time_created AND time_expires",
113 # Session does not exist or has expired
117 # Update the session expiration time
118 self
.db
.execute("UPDATE sessions SET time_expires = NOW() + INTERVAL '14 days' \
119 WHERE session_id = %s AND host = %s", session_id
, host
)
121 return self
.get_by_uid(res
.uid
)
124 class Account(Object
):
125 def __init__(self
, backend
, dn
, attrs
=None):
126 Object
.__init
__(self
, backend
)
129 self
.__attrs
= attrs
or {}
132 return "<%s %s>" % (self
.__class
__.__name
__, self
.dn
)
134 def __cmp__(self
, other
):
135 return cmp(self
.name
, other
.name
)
139 return self
.accounts
.ldap
142 def attributes(self
):
145 def _get_first_attribute(self
, attr
, default
=None):
146 if not self
.attributes
.has_key(attr
):
149 res
= self
.attributes
.get(attr
, [])
155 attribute
= self
.attributes
[key
]
157 raise AttributeError(key
)
159 if len(attribute
) == 1:
164 def check_password(self
, password
):
166 Bind to the server with given credentials and return
167 true if password is corrent and false if not.
169 Raises exceptions from the server on any other errors.
172 logging
.debug("Checking credentials for %s" % self
.dn
)
174 self
.ldap
.simple_bind_s(self
.dn
, password
.encode("utf-8"))
175 except ldap
.INVALID_CREDENTIALS
:
176 logging
.debug("Account credentials are invalid.")
179 logging
.debug("Successfully authenticated.")
183 return "admins" in self
.groups
185 def is_talk_enabled(self
):
186 return "sipUser" in self
.classes
or "sipRoutingObject" in self
.classes
190 return self
.attributes
.get("objectClass", [])
194 return self
._get
_first
_attribute
("uid")
198 return self
._get
_first
_attribute
("cn")
201 def first_name(self
):
202 return self
._get
_first
_attribute
("givenName")
206 if not hasattr(self
, "_groups"):
209 res
= self
.accounts
._search
("(&(objectClass=posixGroup) \
210 (memberUid=%s))" % self
.uid
, ["cn"])
212 for dn
, attrs
in res
:
213 cns
= attrs
.get("cn")
215 self
._groups
.append(cns
[0])
221 address
= self
._get
_first
_attribute
("homePostalAddress", "")
222 address
= address
.replace(", ", "\n")
228 name
= self
.name
.lower()
229 name
= name
.replace(" ", ".")
230 name
= name
.replace("Ä", "Ae")
231 name
= name
.replace("Ö", "Oe")
232 name
= name
.replace("Ü", "Ue")
233 name
= name
.replace("ä", "ae")
234 name
= name
.replace("ö", "oe")
235 name
= name
.replace("ü", "ue")
237 for mail
in self
.attributes
.get("mail", []):
238 if mail
.startswith("%s@ipfire.org" % name
):
241 # If everything else fails, we will go with the UID
242 return "%s@ipfire.org" % self
.uid
246 if "sipUser" in self
.classes
:
247 return self
._get
_first
_attribute
("sipAuthenticationUser")
249 if "sipRoutingObject" in self
.classes
:
250 return self
._get
_first
_attribute
("sipLocalAddress")
253 def sip_password(self
):
254 return self
._get
_first
_attribute
("sipPassword")
258 return "%s@ipfire.org" % self
.sip_id
260 def uses_sip_forwarding(self
):
261 if self
.sip_routing_url
:
267 def sip_routing_url(self
):
268 if "sipRoutingObject" in self
.classes
:
269 return self
._get
_first
_attribute
("sipRoutingAddress")
271 def sip_is_online(self
):
274 if not hasattr(self
, "_is_online"):
275 self
._is
_online
= self
.backend
.talk
.user_is_online(self
.sip_id
)
277 return self
._is
_online
280 def telephone_numbers(self
):
281 return self
.attributes
.get("telephoneNumber")
283 def avatar_url(self
, size
=None):
284 if self
.backend
.debug
:
285 hostname
= "accounts.dev.ipfire.org"
287 hostname
= "accounts.ipfire.org"
289 url
= "http://%s/avatar/%s.jpg" % (hostname
, self
.uid
)
292 url
+= "?size=%s" % size
296 gravatar_icon
= avatar_url
298 def get_avatar(self
, size
=None):
299 avatar
= self
._get
_first
_attribute
("jpegPhoto")
306 return self
._resize
_avatar
(avatar
, size
)
308 def _resize_avatar(self
, image
, size
):
309 image
= StringIO
.StringIO(image
)
310 image
= PIL
.Image
.open(image
)
312 # Resize the image to the desired resolution
313 image
.thumbnail((size
, size
), PIL
.Image
.ANTIALIAS
)
315 f
= StringIO
.StringIO()
317 # If writing out the image does not work with optimization,
318 # we try to write it out without any optimization.
320 image
.save(f
, "JPEG", optimize
=True)
322 image
.save(f
, "JPEG")
326 def get_gravatar_url(self
, size
=128):
328 gravatar_email
= self
.email
.lower()
330 gravatar_email
= "nobody@ipfire.org"
333 gravatar_url
= "http://www.gravatar.com/avatar/" + \
334 hashlib
.md5(gravatar_email
).hexdigest() + "?"
335 gravatar_url
+= urllib
.urlencode({'d': "mm", 's': str(size
)})
340 if __name__
== "__main__":