root/accountmanagerplugin/trunk/acct_mgr/api.py

Revision 3731, 5.5 kB (checked in by pacopablo, 5 months ago)

Added forcing password change after reset. Patch by s0undt3ch. Minor change such that the message indicating password reset needed isn't shown after a successful password reset. Fixes #1427

Line 
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2005 Matthew Good <trac@matt-good.net>
4 #
5 # "THE BEER-WARE LICENSE" (Revision 42):
6 # <trac@matt-good.net> wrote this file.  As long as you retain this notice you
7 # can do whatever you want with this stuff. If we meet some day, and you think
8 # this stuff is worth it, you can buy me a beer in return.   Matthew Good
9 #
10 # Author: Matthew Good <trac@matt-good.net>
11
12 from trac.core import *
13 from trac.config import Option, BoolOption, ExtensionOption
14
15 class IPasswordStore(Interface):
16     """An interface for Components that provide a storage method for users and
17     passwords.
18     """
19
20     def config_key(self):
21         """
22         '''Deprecated''': new implementations of this interface are not required
23         to implement this method, since the prefered way to configure the
24         `IPasswordStore` implemenation is by using its class name in
25         the `password_store` option.
26
27         Returns a string used to identify this implementation in the config.
28         This password storage implementation will be used if the value of
29         the config property "account-manager.password_format" matches.
30         """
31
32     def get_users(self):
33         """Returns an iterable of the known usernames
34         """
35
36     def has_user(self, user):
37         """Returns whether the user account exists.
38         """
39
40     def set_password(self, user, password):
41         """Sets the password for the user.  This should create the user account
42         if it doesn't already exist.
43         Returns True if a new account was created, False if an existing account
44         was updated.
45         """
46
47     def check_password(self, user, password):
48         """Checks if the password is valid for the user.
49         """
50
51     def delete_user(self, user):
52         """Deletes the user account.
53         Returns True if the account existed and was deleted, False otherwise.
54         """
55
56 class IAccountChangeListener(Interface):
57     """An interface for receiving account change events.
58     """
59
60     def user_created(self, user, password):
61         """New user
62         """
63
64     def user_password_changed(self, user, password):
65         """Password changed
66         """
67
68     def user_deleted(self, user):
69         """User deleted
70         """
71
72 class AccountManager(Component):
73     """The AccountManager component handles all user account management methods
74     provided by the IPasswordStore interface.
75
76     The methods will be handled by the underlying password storage
77     implementation set in trac.ini with the "account-manager.password_format"
78     setting.
79     """
80
81     implements(IAccountChangeListener)
82
83     _password_store = ExtensionOption('account-manager', 'password_store',
84                                       IPasswordStore)
85     _password_format = Option('account-manager', 'password_format')
86     stores = ExtensionPoint(IPasswordStore)
87     change_listeners = ExtensionPoint(IAccountChangeListener)
88     force_passwd_change = BoolOption('account-manager', 'force_passwd_change',
89                                      True, doc="Forge the user to change "
90                                      "password when it's reset.")
91
92     # Public API
93
94     def get_users(self):
95         return self.password_store.get_users()
96
97     def has_user(self, user):
98         return self.password_store.has_user(user)
99
100     def set_password(self, user, password):
101         if self.password_store.set_password(user, password):
102             self._notify('created', user, password)
103         else:
104             self._notify('password_changed', user, password)
105
106     def check_password(self, user, password):
107         return self.password_store.check_password(user, password)
108
109     def delete_user(self, user):
110         db = self.env.get_db_cnx()
111         cursor = db.cursor()
112         # Delete session attributes
113         cursor.execute("DELETE FROM session_attribute where sid=%s", (user,))
114         # Delete session
115         cursor.execute("DELETE FROM session where sid=%s", (user,))
116         # Delete any custom permissions set for the user
117         cursor.execute("DELETE FROM permission where username=%s", (user,))
118         db.commit()
119         db.close()
120         # Delete from password store
121         self.log.debug('deleted user')
122         if self.password_store.delete_user(user):
123             self._notify('deleted', user)
124
125     def supports(self, operation):
126         try:
127             store = self.password_store
128         except AttributeError:
129             return False
130         else:
131             return hasattr(store, operation)
132
133     def password_store(self):
134         try:
135             return self._password_store
136         except AttributeError:
137             # fall back on old "password_format" option
138             fmt = self._password_format
139             for store in self.stores:
140                 config_key = getattr(store, 'config_key', None)
141                 if config_key is None:
142                     continue
143                 if config_key() == fmt:
144                     return store
145             # if the "password_format" is not set re-raise the AttributeError
146             raise
147     password_store = property(password_store)
148
149     def _notify(self, func, *args):
150         func = 'user_' + func
151         for l in self.change_listeners:
152             getattr(l, func)(*args)
153
154     # IAccountChangeListener methods
155
156     def user_created(self, user, password):
157         self.log.info('Created new user: %s' % user)
158
159     def user_password_changed(self, user, password):
160         self.log.info('Updated password for user: %s' % user)
161
162     def user_deleted(self, user):
163         self.log.info('Deleted user: %s' % user)
Note: See TracBrowser for help on using the browser.