def replace(self, old_uid, new_uid, db): cursor = db.cursor() try: cursor.execute("DELETE FROM %s WHERE %s=%%s" % (self.table, self.column), (new_uid,)) except (_get_db_exc(self.env)), e: result = exception_to_unicode(e) self.log.debug(self.msg(old_uid, new_uid, self.table, self.column, result='failed: %s' % exception_to_unicode(e, traceback=True))) return dict(error={(self.table, self.column, None): result})
def process_request(self, req): if not req.session.authenticated: chrome.add_warning(req, Markup(tag.span(tag_( "Please log in to finish email verification procedure."))) ) req.redirect(req.href.login()) if 'email_verification_token' not in req.session: chrome.add_notice(req, _("Your email is already verified.")) elif req.method == 'POST' and 'resend' in req.args: try: AccountManager(self.env)._notify( 'email_verification_requested', req.authname, req.session['email_verification_token'] ) except NotificationError, e: chrome.add_warning(req, _("Error raised while sending a " "change notification.") + _("You should " "report that issue to a Trac admin.")) self.log.error('Unable to send verification notification: %s', exception_to_unicode(e, traceback=True)) else: chrome.add_notice(req, _("A notification email has been resent to <%s>."), req.session.get('email') )
def post_process_request(self, req, template, data, content_type): if not req.session.authenticated: # Don't start the email verification procedure on anonymous users. return template, data, content_type email = req.session.get('email') # Only send verification if the user entered an email address. if self.verify_email and self.email_enabled is True and email and \ email != req.session.get('email_verification_sent_to') and \ not req.perm.has_permission('ACCTMGR_ADMIN'): req.session['email_verification_token'] = self._gen_token() req.session['email_verification_sent_to'] = email try: AccountManager(self.env)._notify( 'email_verification_requested', req.authname, req.session['email_verification_token'] ) except NotificationError, e: chrome.add_warning(req, _( "Error raised while sending a change notification." ) + _("You should report that issue to a Trac admin.")) self.log.error('Unable to send registration notification: %s', exception_to_unicode(e, traceback=True)) else: # TRANSLATOR: An email has been sent to <%(email)s> # with a token to ... (the link label for following message) link = tag.a(_("verify your new email address"), href=req.href.verify_email()) # TRANSLATOR: ... verify your new email address chrome.add_notice(req, Markup(tag.span(Markup(_( "An email has been sent to <%(email)s> with a token to " "%(link)s.", email=tag(email), link=link)))) )
def _set_password(env, req, username, password, old_password=None): try: AccountManager(env).set_password(username, password, old_password=old_password) except NotificationError, e: add_warning(req, _("Error raised while sending a change " "notification.") + _("You should report " "that issue to a Trac admin.")) env.log.error('Unable to send password change notification: %s', exception_to_unicode(e, traceback=True))
def replace(self, old_uid, new_uid, db): result = 0 cursor = db.cursor() try: cursor.execute("SELECT COUNT(*) FROM %s WHERE %s=%%s" % (self.table, self.column), (old_uid,)) exists = cursor.fetchone() if exists[0]: cursor.execute("UPDATE %s SET %s=%%s WHERE %s=%%s" % (self.table, self.column, self.column), (new_uid, old_uid)) result = int(exists[0]) self.log.debug(self.msg(old_uid, new_uid, self.table, self.column, result='%s time(s)' % result)) except (_get_db_exc(self.env)), e: result = exception_to_unicode(e) self.log.debug(self.msg(old_uid, new_uid, self.table, self.column, result='failed: %s' % exception_to_unicode(e, traceback=True))) return dict(error={(self.table, self.column, None): result})
def _notify(self, mod, *args): mod = '_'.join(['user', mod]) for listener in self.change_listeners: # Support divergent account change listener implementations too. try: self.log.debug('CHANGE_LISTENER: %s(%s)' % (repr(listener), mod)) getattr(listener, mod)(*args) except AttributeError, e: self.log.warn( 'IAccountChangeListener %s does not support method %s: %s' % (listener.__class__.__name__, mod, exception_to_unicode(e)))
def _notify(self, mod, *args): mod = '_'.join(['user', mod]) for listener in self.change_listeners: # Support divergent account change listener implementations too. try: self.log.debug( 'CHANGE_LISTENER: %s(%s)' % (repr(listener), mod)) getattr(listener, mod)(*args) except AttributeError, e: self.log.warn( 'IAccountChangeListener %s does not support method %s: %s' % (listener.__class__.__name__, mod, exception_to_unicode(e)))
def replace(self, old_uid, new_uid, db): results=dict() self.column = 'owner' result = super(TicketUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) self.column = 'reporter' result = super(TicketUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) # Replace user ID in Cc ticket column. cursor = db.cursor() cursor.execute("SELECT id,cc FROM ticket WHERE cc %s" % db.like(), ('%' + db.like_escape(old_uid) + '%',)) result = 0 for row in cursor.fetchall(): cc = _get_cc_list(row[1]) for i in [i for i,r in enumerate(cc) if r == old_uid]: cc[i] = new_uid try: cursor.execute("UPDATE ticket SET cc=%s WHERE id=%s", (', '.join(cc), int(row[0]))) result += 1 except (_get_db_exc(self.env)), e: result = exception_to_unicode(e) self.log.debug(self.msg(old_uid, new_uid, self.table, 'cc', result='failed: %s' % exception_to_unicode(e, traceback=True))) return dict(error={(self.table, 'cc', None): result})
def _distribute_auth(self, req, trac_auth, name=None): # Single Sign On authentication distribution between multiple # Trac environments managed by AccountManager. local_environ = req.environ.get('SCRIPT_NAME', '').lstrip('/') for environ, path in get_environments(req.environ).iteritems(): if environ != local_environ: try: # Cache environment for subsequent invocations. env = open_environment(path, use_cache=True) auth_cookie_path = env.config.get('trac', 'auth_cookie_path') # Consider only Trac environments with equal, non-default # 'auth_cookie_path', which enables cookies to be shared. if auth_cookie_path == self.auth_cookie_path: db = env.get_db_cnx() cursor = db.cursor() # Authentication cookie values must be unique. Ensure, # there is no other session (or worst: session ID) # associated to it. cursor.execute( """ DELETE FROM auth_cookie WHERE cookie=%s """, (trac_auth, )) if not name: db.commit() env.log.debug('Auth data revoked from: %s' % local_environ) continue cursor.execute( """ INSERT INTO auth_cookie (cookie,name,ipnr,time) VALUES (%s,%s,%s,%s) """, (trac_auth, name, req.remote_addr, int( time.time()))) db.commit() env.log.debug('Auth data received from: %s' % local_environ) self.log.debug('Auth distribution success: %s' % environ) except Exception, e: self.log.debug( 'Auth distribution skipped for env %s: %s' % (environ, exception_to_unicode(e, traceback=True)))
def _distribute_auth(self, req, trac_auth, name=None): # Single Sign On authentication distribution between multiple # Trac environments managed by AccountManager. local_environ = req.environ.get('SCRIPT_NAME', '').lstrip('/') for environ, path in get_environments(req.environ).iteritems(): if environ != local_environ: try: # Cache environment for subsequent invocations. env = open_environment(path, use_cache=True) auth_cookie_path = env.config.get('trac', 'auth_cookie_path') # Consider only Trac environments with equal, non-default # 'auth_cookie_path', which enables cookies to be shared. if auth_cookie_path == self.auth_cookie_path: with env.db_transaction as db: cursor = db.cursor() # Authentication cookie values must be unique. Ensure, # there is no other session (or worst: session ID) # associated to it. cursor.execute(""" DELETE FROM auth_cookie WHERE cookie=%s """, (trac_auth,)) if not name: env.log.debug('Auth data revoked from: %s' % local_environ) continue cursor.execute(""" INSERT INTO auth_cookie (cookie,name,ipnr,time) VALUES (%s,%s,%s,%s) """, (trac_auth, name, req.remote_addr, int(time.time()))) env.log.debug('Auth data received from: %s' % local_environ) self.log.debug('Auth distribution success: %s' % environ) except Exception, e: self.log.debug('Auth distribution skipped for env %s: %s' % (environ, exception_to_unicode(e, traceback=True)) )
def _reset_password(self, req, username, email): """Store a new, temporary password on admin or user request. This method is used by acct_mgr.admin.AccountManagerAdminPanel too. """ acctmgr = self.acctmgr new_password = self._random_password try: self.store.set_password(username, new_password) acctmgr._notify('password_reset', username, email, new_password) except NotificationError, e: msg = _("Error raised while sending a change notification.") if req.path_info.startswith('/admin'): msg += _("You'll get details with TracLogging enabled.") else: msg += _("You should report that issue to a Trac admin.") add_warning(req, msg) self.log.error('Unable to send password reset notification: %s', exception_to_unicode(e, traceback=True))
def _do_delete(self, req): username = req.authname password = req.args.get('password') if not password: add_warning(req, _("Password cannot be empty.")) elif not self.acctmgr.check_password(username, password): add_warning(req, _("Password is incorrect.")) else: try: self.acctmgr.delete_user(username) except NotificationError, e: # User wont care for notification, only care for logging here. self.log.error( 'Unable to send account deletion notification: %s', exception_to_unicode(e, traceback=True)) # Delete the whole session, since records in session_attribute # would get restored on logout otherwise. req.session.clear() req.session.save() req.redirect(req.href.logout())
result = 0 for row in cursor.fetchall(): cc = _get_cc_list(row[2]) for i in [i for i,r in enumerate(cc) if r == old_uid]: cc[i] = new_uid try: cursor.execute(""" UPDATE %s SET %s=%%s WHERE ticket=%%s AND time=%%s """ % (table, column), (', '.join(cc), int(row[0]), int(row[1]))) result += 1 except (_get_db_exc(self.env)), e: result = exception_to_unicode(e) self.log.debug( self.msg(old_uid, new_uid, table, column, constraint, result='failed: %s' % exception_to_unicode(e, traceback=True) )) return dict(error={(self.table, column, constraint): result}) self.log.debug(self.msg(old_uid, new_uid, table, column, constraint, result='%s time(s)' % result)) results.update({(table, column, constraint): result}) return results class WikiUserIdChanger(PrimitiveUserIdChanger): """Change user IDs in wiki pages."""
class TicketUserIdChanger(PrimitiveUserIdChanger): """Change all user IDs in tickets.""" table = 'ticket' # IUserIdChanger method def replace(self, old_uid, new_uid, db): results=dict() self.column = 'owner' result = super(TicketUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) self.column = 'reporter' result = super(TicketUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) # Replace user ID in Cc ticket column. cursor = db.cursor() cursor.execute("SELECT id,cc FROM ticket WHERE cc %s" % db.like(), ('%' + db.like_escape(old_uid) + '%',)) result = 0 for row in cursor.fetchall(): cc = _get_cc_list(row[1]) for i in [i for i,r in enumerate(cc) if r == old_uid]: cc[i] = new_uid try: cursor.execute("UPDATE ticket SET cc=%s WHERE id=%s", (', '.join(cc), int(row[0]))) result += 1 except (_get_db_exc(self.env)), e: result = exception_to_unicode(e) self.log.debug(self.msg(old_uid, new_uid, self.table, 'cc', result='failed: %s' % exception_to_unicode(e, traceback=True))) return dict(error={(self.table, 'cc', None): result}) self.log.debug(self.msg(old_uid, new_uid, self.table, 'cc', result='%s time(s)' % result)) results.update({(self.table, 'cc', None): result}) table = 'ticket_change' self.column = 'author' self.table = table result = super(TicketUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) constraint = "field='owner'|'reporter'" cursor = db.cursor() for column in ('oldvalue', 'newvalue'): cursor.execute(""" SELECT COUNT(*) FROM %s WHERE %s=%%s AND (field='owner' OR field='reporter') """ % (table, column), (old_uid,)) exists = cursor.fetchone() result = int(exists[0]) if exists[0]: try: cursor.execute(""" UPDATE %s SET %s=%%s WHERE %s=%%s AND (field='owner' OR field='reporter') """ % (table, column, column), (new_uid, old_uid)) except (_get_db_exc(self.env)), e: result = exception_to_unicode(e) self.log.debug( self.msg(old_uid, new_uid, table, column, constraint, result='failed: %s' % exception_to_unicode(e, traceback=True))) return dict(error={(self.table, column, constraint): result}) self.log.debug(self.msg(old_uid, new_uid, table, column, constraint, result='%s time(s)' % result)) results.update({(table, column, constraint): result})
new_password = self._random_password try: self.store.set_password(username, new_password) acctmgr._notify('password_reset', username, email, new_password) except NotificationError, e: msg = _("Error raised while sending a change notification.") if req.path_info.startswith('/admin'): msg += _("You'll get details with TracLogging enabled.") else: msg += _("You should report that issue to a Trac admin.") add_warning(req, msg) self.log.error('Unable to send password reset notification: %s', exception_to_unicode(e, traceback=True)) except Exception, e: add_warning(req, _("Cannot reset password: %(error)s", error=exception_to_unicode(e))) self.log.error('Unable to reset password: %s', exception_to_unicode(e, traceback=True)) return else: # No message, if method has been called from user admin panel. if not req.path_info.startswith('/admin'): add_notice(req, _("A new password has been sent to you at " "<%(email)s>.", email=email)) if acctmgr.force_passwd_change: set_user_attribute(self.env, username, 'force_change_passwd', 1) class LoginModule(auth.LoginModule, CommonTemplateProvider): """Custom login form and processing.
def process_request(self, req): acctmgr = self.acctmgr if req.authname != 'anonymous': req.redirect(req.href.prefs('account')) action = req.args.get('action') name = req.args.get('name', '').strip() username = acctmgr.handle_username_casing(req.args.get('username', '').strip()) data = { '_dgettext': dgettext, 'acctmgr': dict(name=name, username=username), 'ignore_auth_case': self.config.getbool('trac', 'ignore_auth_case') } verify_enabled = is_enabled(self.env, EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email data['verify_account_enabled'] = verify_enabled if req.method == 'POST' and action == 'create': try: try: # Check request and prime account on success. acctmgr.validate_account(req, True) except NotificationError, e: chrome.add_warning(req, _( "Error raised while sending a change notification." ) + _("You should report that issue to a Trac admin.")) self.log.error( 'Unable to send registration notification: %s', exception_to_unicode(e, traceback=True)) except RegistrationError, e: # Attempt deferred translation. message = gettext(e.message) # Check for (matching number of) message arguments before # attempting string substitution. if e.msg_args and \ len(e.msg_args) == len(re.findall('%s', message)): message = message % e.msg_args chrome.add_warning(req, Markup(message)) else: if self.require_approval: set_user_attribute(self.env, username, 'approval', N_('pending')) # Notify admin user about registration pending for review. try: acctmgr._notify('registration_approval_required', username) except NotificationError, e: chrome.add_warning(req, _( "Error raised while sending a change " "notification.") + _("You should report that " "issue to a Trac admin.")) self.log.error('Unable to send admin notification: %s', exception_to_unicode(e, traceback=True)) else: chrome.add_notice(req, Markup(tag.span(Markup(_( "Your username has been registered successfully, " "but your account requires administrative " "approval. Please proceed according to local " "policy.")))) ) if verify_enabled: chrome.add_notice(req, Markup(tag.span(Markup(_( """Your username has been successfully registered but your account still requires activation. Please login as user %(user)s, and follow the instructions.""", user=tag.b(username))))) ) req.redirect(req.href.login()) chrome.add_notice(req, Markup(tag.span(Markup(_( """Registration has been finished successfully. You may log in as user %(user)s now.""", user=tag.b(username))))) ) req.redirect(req.href.login())