]> ToastFreeware Gitweb - philipp/winterrodeln/wradmin.git/blob - wradmin/wradmin/lib/mediawiki.py
378dd808365903224fd8131d74aad29d46fcb26b
[philipp/winterrodeln/wradmin.git] / wradmin / wradmin / lib / mediawiki.py
1 "MediaWiki communication functions"
2
3 from authkit.users import UsersReadOnly, md5
4 import datetime
5 import wradmin.model as model
6 import wradmin.model.validators
7 import formencode, formencode.national
8
9 import logging
10 log = logging.getLogger(__name__)
11
12
13 # Converter functions
14 # -------------------
15
16 def to_bool(value):
17     return model.validators.GermanBool().to_python(value)
18
19
20 def to_unsigned(value):
21     "Requires a positive number"
22     return formencode.validators.Int(min=0).to_python(value)
23
24
25 def to_date(value):
26     "Parses a date in the form 'yyy-mm-dd'"
27     return model.validators.DateConverter().to_python(value)
28
29
30 def to_geo(value):
31     "Formats to coordinates '47.076207 N 11.453553 E' to the (latitude, longitude) tuplet."
32     return model.validators.Geo().to_python(value)
33
34
35 def to_title(value):
36     """Line 2237 of includes/Title.php says: $this->mTextform = str_replace( '_', ' ', $dbkey );
37     No not check for None because a missing title is an error"""
38     return value.replace(u'_', u' ')
39
40
41 def to_tristate(value):
42     """Does the following conversion:
43     None         -> (None, None)
44     u'Ja'        -> (True, False)
45     u'Teilweise' -> (True,  True)
46     u'Nein'      -> (False, True)"""
47     return model.validators.GermanTristate().to_python(value)
48
49
50 def to_email(value):
51     return formencode.validators.Email().to_python(value)
52
53
54 def to_url(value):
55     return formencode.validators.URL().to_python(value)
56
57
58 def to_phone(value):
59     return model.validators.AustrianPhoneNumber(messages={'phoneFormat': u"Telefonnummer %%(value)s muss das Format 0123/456789 oder +43/123/456789 haben"}).to_python(value)
60
61
62 def to_phone_info(value):
63     return model.validators.PhoneInfo(messages={'phoneInfo': u"Bitte verwenden Sie ein Format wie '0512/123456 (Schnee Alm)'."}).to_python(value)
64
65
66 def conv(fnct, value, fieldname):
67     "Like one of the to_xxx functions (e.g. to_bool), but adds the field name to the error message"
68     try: return fnct(value)
69     except formencode.Invalid, e: raise formencode.Invalid(u"Conversion error in field '%s': %s" % (fieldname, unicode_e(e)), e.value, e.state)
70
71
72 def unicode_e(exception):
73     """Does "unicode(exception)" as it should be. This is a workaround for bug http://bugs.python.org/issue2517
74     that is not fixed in python 2.5.2.
75     Details of bug: "unicode(Exception(u'\xe4'))" raises an UnicodeEncodeError exception."""
76     if exception.message: return unicode(exception.message)
77     return unicode(exception)
78
79
80 # User management
81 # ---------------
82
83 class MediaWikiUsers(UsersReadOnly):
84     def __init__(self, data=None, encrypt=None):
85         UsersReadOnly.__init__(self, data, encrypt)
86
87         # Initialize class fields
88         self.usernames = []
89         self.passwords = {}
90         self.roles = {}
91         self.groups = {}
92         self.user_ids = {} # MediaWiki user_id field of the database
93         self.real_names = {} # Real names of the users
94         self.emails = {} # E-Mail addresses of the users
95         
96         # Query database
97         con = model.meta.engine.connect()
98         sql = "SELECT user_id, user_name, user_real_name, user_password, user_email FROM user, user_groups WHERE ug_user=user_id AND ug_group='beauftragte'"
99         result = con.execute(sql)
100         for row in result:
101             user_id, username, real_name, password, email = row
102             username = username.lower()
103             role = []
104             group = None
105             
106             self.usernames.append(username)
107             self.passwords[username] = password
108             self.roles[username] = role
109             self.groups[username] = group
110             self.user_ids[username] = user_id
111             self.real_names[username] = real_name
112             self.emails[username] = email
113         con.close()
114         log.info("%d users loaded from the MediaWiki database" % len(self.usernames))
115     
116     
117     def user_has_password(self, username, password):
118         """
119         Passwords are case sensitive.
120         Returns ``True`` if the user has the password specified, ``False`` otherwise. 
121         Raises an exception if the user doesn't exist.
122         
123         See http://www.winterrodeln.org/trac/wiki/MediaWikiAuthorization
124         """
125         pwd = self.user_password(username)
126         # Example: pwd = ':B:d25b2886:41e46c952790b1b442aac4f24f7ea7a8'
127         pwd_parts = pwd.split(':') # password_parts = ['', 'B', 'd25b2886', '41e46c952790b1b442aac4f24f7ea7a8']
128         if len(pwd_parts) == 4 and pwd_parts[1] == 'B':
129             salt, pwd_md5 = tuple(pwd_parts[2:4]) # salt = 'd25b2886'; pwd_md5 = '41e46c952790b1b442aac4f24f7ea7a8'
130         else:
131             raise AuthKitError("Password in the MediaWiki database format has an unexpected format ('%s' instead of e.g. ':B:d25b2886:41e46c952790b1b442aac4f24f7ea7a8')" % pwd)
132         # log.info("user: '%s'; md5 of salt+' '+entered_pwd: '%s'; md5-part of DB-pwd: %s" % (username, md5(salt + '-' + md5(password)), pwd_md5))
133         return md5(salt + '-' + md5(password)) == pwd_md5