Add a hint option to the mysql_login auth backend.
[matthijs/projects/wipi.git] / conf / auth / mysql_login.py
1 # -*- coding: iso-8859-1 -*-
2 """
3     MoinMoin - auth plugin doing a check against MySQL db
4
5     @copyright: 2008 Matthijs Kooijman
6     @license: GNU GPL, see COPYING for details.
7 """
8
9 import MySQLdb
10 import md5
11 from MoinMoin import user
12 from MoinMoin.auth import BaseAuth, ContinueLogin
13
14 class mysql_login(BaseAuth):
15     logout_possible = True
16     login_inputs    = ['username', 'password']
17     
18     def __init__(self, name='mysql', dbhost=None, dbuser=None, dbpass=None, dbname=None, dbport=None, verbose=False, hint=None):
19         """
20             Authenticate using credentials from a mysql database
21
22             The name parameter should be unique among all authentication methods.
23
24             The hint parameter is a snippet of HTML that is displayed below the login form.
25         """
26         self.verbose = verbose
27         self.dbhost  = dbhost
28         self.dbuser  = dbuser
29         self.dbpass  = dbpass
30         self.dbname  = dbname
31         self.dbport  = dbport
32         self.name    = name
33         self.hint    = hint
34     
35     def check_login(self, request, username, password):
36         """ Checks the given username password combination. Returns the
37         corresponding emailaddress, or False if authentication failed.
38         """
39         conn = self.connect(request)
40
41         if not conn:
42             return False
43
44         # Get some data
45         cursor = conn.cursor ()
46         cursor.execute ("SELECT user_password,user_email FROM lex_users WHERE username=%s", username)
47
48         # No data? No login.
49         if (cursor.rowcount == 0):
50             conn.close()
51             return False
52        
53         # Check password
54         row = cursor.fetchone()
55         conn.close()
56
57         if (md5.new(password).hexdigest() == row[0]):
58             return row[1]
59         else:
60             return False
61
62     def connect(self, request):
63         # This code was shamelessly stolen from
64         # django.db.backends.mysql.base.cursor
65         kwargs = {
66             'charset': 'utf8',
67             'use_unicode': False,
68         }
69         if self.dbuser:
70             kwargs['user'] = self.dbuser
71         if self.dbname:
72             kwargs['db'] = self.dbname
73         if self.dbpass:
74             kwargs['passwd'] = self.dbpass
75         if self.dbhost.startswith('/'):
76             kwargs['unix_socket'] = self.dbhost
77         elif self.dbhost:
78             kwargs['host'] = self.dbhost
79         if self.dbport:
80             kwargs['port'] = int(self.dbport)
81
82         # End stolen code
83
84         try:
85             conn = MySQLdb.connect (**kwargs)
86         except:
87             import sys
88             import traceback
89             info = sys.exc_info()
90             request.log("mysql_login: authentication failed due to exception connecting to DB, traceback follows...")
91             request.log(''.join(traceback.format_exception(*info)))
92             return False
93
94         return conn
95
96     def login(self, request, user_obj, **kw):
97         try:
98             username = kw.get('username')
99             password = kw.get('password')
100
101             if self.verbose: request.log("mysql_login: Trying to log in, username=%r " % (username))
102            
103             # simply continue if something else already logged in
104             # successfully
105             if user_obj and user_obj.valid:
106                 return ContinueLogin(user_obj)
107
108             # Deny empty username or passwords
109             if not username or not password:
110                 return ContinueLogin(user_obj)
111
112             email = self.check_login(request, username, password)
113             
114             # Login incorrect
115             if (not email):
116                 if self.verbose: request.log("mysql_login: authentication failed for %s" % (username))
117                 return ContinueLogin(user_obj)
118
119             if self.verbose: request.log("mysql_login: authenticated %s (email %s)" % (username, email))
120
121             u = user.User(request, auth_username=username, auth_method=self.name, auth_attribs=('password', 'email', ))
122             u.email = email
123             #u.remember_me = 0 # 0 enforces cookie_lifetime config param
124             u.create_or_update(True)
125
126             return ContinueLogin(u)
127         except:
128             import sys
129             import traceback
130             info = sys.exc_info()
131             request.log("mysql_login: authentication failed due to unexpected exception, traceback follows...")
132             request.log(''.join(traceback.format_exception(*info)))
133             return ContinueLogin(user_obj)
134
135     def login_hint(self, request):
136         """ Return a snippet of HTML that is displayed with the login form. """
137         return self.hint
138
139 # vim: set sw=4 expandtab sts=4:vim