def _do_account(self, req): assert (req.authname and req.authname != 'anonymous') action = req.args.get('action') delete_enabled = self.acctmgr.supports('delete_user') and \ self.acctmgr.allow_delete_account data = { 'delete_enabled': delete_enabled, 'delete_msg_confirm': _("Are you sure you want to delete your account?"), } force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': if self._do_change_password(req) and force_change_password: del req.session['force_change_passwd'] req.session.save() add_notice(req, _("Thank you for taking the time to " "update your password.")) force_change_password = False elif action == 'delete' and delete_enabled: self._do_delete(req) if force_change_password: add_warning(req, tag_( "You are required to change password because of a recent " "password change request. %(invitation)s", invitation=tag.b(_("Please change your password now.")))) return data
def process_request(self, req): if not req.session.authenticated: chrome.add_warning(req, 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 htpasswd(password, hash): if hash.startswith('$apr1$'): return md5crypt(password, hash[6:].split('$')[0], '$apr1$') elif hash.startswith('{SHA}'): return '{SHA}' + sha1(password).digest().encode('base64')[:-1] elif passlib_ctxt is not None and hash.startswith('$5$') and \ 'sha256_crypt' in passlib_ctxt.policy.schemes(): return passlib_ctxt.encrypt(password, scheme="sha256_crypt", rounds=5000, salt=hash[3:].split('$')[0]) elif passlib_ctxt is not None and hash.startswith('$6$') and \ 'sha512_crypt' in passlib_ctxt.policy.schemes(): return passlib_ctxt.encrypt(password, scheme="sha512_crypt", rounds=5000, salt=hash[3:].split('$')[0]) elif crypt is None: # crypt passwords are only supported on Unix-like systems raise NotImplementedError( _("""The \"crypt\" module is unavailable on this platform.""")) else: if hash.startswith('$5$') or hash.startswith('$6$'): # Import of passlib failed, now check, if crypt is capable. if not crypt(password, hash).startswith(hash): # No, so bail out. raise NotImplementedError( _("""Neither are \"sha2\" hash algorithms supported by the \"crypt\" module on this platform nor is \"passlib\" available.""")) return crypt(password, hash)
def _do_account(self, req): assert (req.authname and req.authname != 'anonymous') action = req.args.get('action') delete_enabled = self.acctmgr.supports('delete_user') and \ self.acctmgr.allow_delete_account data = { 'delete_enabled': delete_enabled, 'delete_msg_confirm': _("Are you sure you want to delete your account?"), } force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': if self._do_change_password(req) and force_change_password: del req.session['force_change_passwd'] req.session.save() add_notice( req, _("Thank you for taking the time to " "update your password.")) force_change_password = False elif action == 'delete' and delete_enabled: self._do_delete(req) if force_change_password: add_warning( req, Markup( _( "You are required to change password because of a recent " "password change request. %(invitation)s", invitation=tag.b( _("Please change your password now."))))) return data
def _prepare_attrs(self, req, attr): page = int(req.args.get('page', '1')) # Paginator can't deal with dict, so convert to list. attr_lst = [(k,v) for k,v in attr.iteritems()] max_per_page = as_int(req.args.get('max_per_page'), None) if max_per_page is None: max_per_page = self.ACCTS_PER_PAGE attr = Paginator(attr_lst, page - 1, max_per_page) pagedata = [] shown_pages = attr.get_shown_pages(21) for shown_page in shown_pages: page_href = req.href.admin('accounts', 'users', page=shown_page, max_per_page=max_per_page) pagedata.append([page_href, None, str(shown_page), _("page %(num)s", num=str(shown_page))]) fields = ['href', 'class', 'string', 'title'] attr.shown_pages = [dict(zip(fields, p)) for p in pagedata] attr.current_page = {'href': None, 'class': 'current', 'string': str(attr.page + 1), 'title':None} if attr.has_next_page: next_href = req.href.admin('accounts', 'users', page=page + 1, max_per_page=max_per_page) add_link(req, 'next', next_href, _('Next Page')) if attr.has_previous_page: prev_href = req.href.admin('accounts', 'users', page=page - 1, max_per_page=max_per_page) add_link(req, 'prev', prev_href, _('Previous Page')) page_href = req.href.admin('accounts', 'cleanup') return {'attr': attr, 'page_href': page_href}
def post_process_request(self, req, template, data, content_type): if template is None or 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 \ 'ACCTMGR_ADMIN' not in req.perm: 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, tag_( "An email has been sent to <%(email)s> with a token to " "%(link)s.", email=tag(email), link=link))
def render_registration_fields(self, req, data): """Add an email address text input field to the registration form.""" # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('email', '').strip() insert = tag.label(_("Email:"), tag.input(type='text', name='email', size=20, class_='textwidget', value=old_value)) # Deferred import required to aviod circular import dependencies. from acct_mgr.web_ui import AccountModule reset_password = AccountModule(self.env).reset_password_enabled verify_account = self.env.is_enabled(EmailVerificationModule) and \ EmailVerificationModule(self.env).verify_email if verify_account: # TRANSLATOR: Registration form hints for a mandatory input field. hint = tag.p(_(""" The email address is required for Trac to send you a verification token. """), class_='hint') if reset_password: hint = tag(hint, tag.p(_(""" Entering your email address will also enable you to reset your password if you ever forget it. """), class_='hint')) return tag(insert, hint), data elif reset_password: # TRANSLATOR: Registration form hint, if email input is optional. hint = tag.p(_("""Entering your email address will enable you to reset your password if you ever forget it."""), class_='hint') return dict(optional=tag(insert, hint)), data else: # Always return the email text input itself as optional field. return dict(optional=insert), data
def _do_account(self, req): assert(req.authname and req.authname != 'anonymous') action = req.args.get('action') delete_enabled = self.acctmgr.supports('delete_user') and \ self.acctmgr.allow_delete_account data = {'delete_enabled': delete_enabled, 'delete_msg_confirm': _( "Are you sure you want to delete your account?"), } force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': data.update(self._do_change_password(req)) if force_change_password: del(req.session['force_change_passwd']) req.session.save() chrome.add_notice(req, Markup(tag.span(tag_( "Thank you for taking the time to update your password." )))) force_change_password = False elif action == 'delete' and delete_enabled: data.update(self._do_delete(req)) else: data.update({'error': 'Invalid action'}) if force_change_password: chrome.add_warning(req, Markup(tag.span(_( "You are required to change password because of a recent " "password change request. "), tag.b(_("Please change your password now."))))) return data
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') # TRANSLATOR: Hint for visible bot trap registration input field. hint = tag.p(Markup(_( """Apologies for the inconvenience, but please use the Sugarlabs Wiki, find the page referring to find the gold in the pot, and insert here the four words on the second line, or send mail to systems mailing list.""", token=tag.b(self.reg_basic_token))), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint ) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field.")) ) return insert, data
def render_registration_fields(self, req, data): """Add a hidden text input field to the registration form, and a visible one with mandatory input as well, if token is configured. """ if self.reg_basic_token: # Preserve last input for editing on failure instead of typing # everything again. old_value = req.args.get('basic_token', '') if self.reg_basic_question: # TRANSLATOR: Question-style hint for visible bot trap # registration input field. hint = tag.p(_("Please answer above: %(question)s", question=self.reg_basic_question), class_='hint') else: # TRANSLATOR: Verbatim token hint for visible bot trap # registration input field. hint = tag.p(tag_( "Please type [%(token)s] as verification token, " "exactly replicating everything within the braces.", token=tag.b(self.reg_basic_token)), class_='hint') insert = tag( tag.label(_("Parole:"), tag.input(type='text', name='basic_token', size=20, class_='textwidget', value=old_value)), hint) else: insert = None # TRANSLATOR: Registration form hint for hidden bot trap input field. insert = tag(insert, tag.input(type='hidden', name='sentinel', title=_("Better do not fill this field."))) return insert, data
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: AccountManager(self.env)._notify( 'email_verification_requested', req.authname, req.session['email_verification_token'] ) chrome.add_notice(req, _("A notification email has been resent to <%s>."), req.session.get('email') ) elif 'verify' in req.args: # allow via POST or GET (the latter for email links) if req.args['token'] == req.session['email_verification_token']: del req.session['email_verification_token'] chrome.add_notice( req, _("Thank you for verifying your email address.") ) req.redirect(req.href.prefs()) else: chrome.add_warning(req, _("Invalid verification token")) data = {'_dgettext': dgettext} if 'token' in req.args: data['token'] = req.args['token'] if 'email_verification_token' not in req.session: data['button_state'] = { 'disabled': 'disabled' } return 'verify_email.html', data, None
def htpasswd(password, hash): if hash.startswith('$apr1$'): return md5crypt(password, hash[6:].split('$')[0], '$apr1$') elif hash.startswith('{SHA}'): return '{SHA}' + sha1(password).digest().encode('base64')[:-1] elif passlib_ctxt is not None and hash.startswith('$5$') and \ 'sha256_crypt' in passlib_ctxt.policy.schemes(): return passlib_ctxt.encrypt(password, scheme="sha256_crypt", rounds=5000, salt=hash[3:].split('$')[0]) elif passlib_ctxt is not None and hash.startswith('$6$') and \ 'sha512_crypt' in passlib_ctxt.policy.schemes(): return passlib_ctxt.encrypt(password, scheme="sha512_crypt", rounds=5000, salt=hash[3:].split('$')[0]) elif crypt is None: # crypt passwords are only supported on Unix-like systems raise NotImplementedError(_("""The \"crypt\" module is unavailable on this platform.""")) else: if hash.startswith('$5$') or hash.startswith('$6$'): # Import of passlib failed, now check, if crypt is capable. if not crypt(password, hash).startswith(hash): # No, so bail out. raise NotImplementedError(_( """Neither are \"sha2\" hash algorithms supported by the \"crypt\" module on this platform nor is \"passlib\" available.""")) return crypt(password, hash)
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 AccountManager(self.env)._notify( 'email_verification_requested', req.authname, req.session['email_verification_token'] ) # 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=email, link=link)))) ) return template, data, content_type
def post_process_request(self, req, template, data, content_type): if not req.session.authenticated: # Don't start the email verification precedure on anonymous users. return template, data, content_type email = req.session.get('email') # Only send verification if the user entered an email address. acctmgr = AccountManager(self.env) if acctmgr.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 acctmgr._notify('email_verification_requested', req.authname, req.session['email_verification_token']) # 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=email, link=link))))) return template, data, content_type
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: AccountManager(self.env)._notify( 'email_verification_requested', req.authname, req.session['email_verification_token']) chrome.add_notice( req, _("A notification email has been resent to <%s>."), req.session.get('email')) elif 'verify' in req.args: # allow via POST or GET (the latter for email links) if req.args['token'] == req.session['email_verification_token']: del req.session['email_verification_token'] chrome.add_notice( req, _("Thank you for verifying your email address.")) req.redirect(req.href.prefs()) else: chrome.add_warning(req, _("Invalid verification token")) data = {'_dgettext': dgettext} if 'token' in req.args: data['token'] = req.args['token'] if 'email_verification_token' not in req.session: data['button_state'] = {'disabled': 'disabled'} return 'verify_email.html', data, None
def process_request(self, req): if req.path_info.startswith('/login') and req.authname == 'anonymous': try: referer = self._referer(req) except AttributeError: # Fallback for Trac 0.11 compatibility. referer = req.get_header('Referer') # Steer clear of requests going nowhere or loop to self. if referer is None or \ referer.startswith(str(req.abs_href()) + '/login'): referer = req.abs_href() data = { '_dgettext': dgettext, 'login_opt_list': self.login_opt_list, 'persistent_sessions': AccountManager(self.env).persistent_sessions, 'referer': referer, 'registration_enabled': RegistrationModule(self.env).enabled, 'reset_password_enabled': AccountModule(self.env).reset_password_enabled } if req.method == 'POST': self.log.debug( "LoginModule.process_request: 'user_locked' = %s" % req.args.get('user_locked')) if not req.args.get('user_locked'): # TRANSLATOR: Intentionally obfuscated login error data['login_error'] = _("Invalid username or password") else: f_user = req.args.get('username') release_time = AccountGuard(self.env).pretty_release_time( req, f_user) if not release_time is None: data['login_error'] = _( """Account locked, please try again after %(release_time)s """, release_time=release_time) else: data['login_error'] = _("Account locked") return 'login.html', data, None else: n_plural = req.args.get('failed_logins') if n_plural > 0: add_warning( req, Markup( tag.span( tag( ngettext( "Login after %(attempts)s failed attempt", "Login after %(attempts)s failed attempts", n_plural, attempts=n_plural))))) return auth.LoginModule.process_request(self, req)
def validate_registration(self, req): """Check registration form input. Returns a RegistrationError with error message, or None on success. """ # Nicer than a plain NotImplementedError. raise NotImplementedError, _( "No check method 'validate_registration' defined in %(module)s", module=self.__class__.__name__)
class EmailVerificationModule(CommonTemplateProvider): """Performs email verification on every new or changed address. A working email sender for Trac (!TracNotification or !TracAnnouncer) is strictly required to enable this module's functionality. Anonymous users should register and perms should be tweaked, so that anonymous users can't edit wiki pages and change or create tickets. So this email verification code won't be used on them. """ implements(IRequestFilter, IRequestHandler) def __init__(self, *args, **kwargs): self.email_enabled = True if self.config.getbool('announcer', 'email_enabled') != True and \ self.config.getbool('notification', 'smtp_enabled') != True: self.email_enabled = False if is_enabled(self.env, self.__class__) == True: self.env.log.warn(' '.join([ self.__class__.__name__, "can't work because of missing email setup." ])) # IRequestFilter methods def pre_process_request(self, req, handler): if not req.session.authenticated: # Permissions for anonymous users remain unchanged. return handler elif req.path_info == '/prefs' and req.method == 'POST' and \ not 'restore' in req.args: try: EmailCheck(self.env).validate_registration(req) # Check passed without error: New email address seems good. except RegistrationError, e: # Attempt to change email to an empty or invalid # address detected, resetting to previously stored value. chrome.add_warning(req, Markup(gettext(e.message))) req.redirect(req.href.prefs(None)) if AccountManager(self.env).verify_email and handler is not self and \ 'email_verification_token' in req.session and \ not req.perm.has_permission('ACCTMGR_ADMIN'): # TRANSLATOR: Your permissions have been limited until you ... link = tag.a(_("verify your email address"), href=req.href.verify_email()) # TRANSLATOR: ... verify your email address chrome.add_warning( req, Markup( tag.span( Markup( _("Your permissions have been limited until you %(link)s.", link=link))))) req.perm = perm.PermissionCache(self.env, 'anonymous') return handler
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 _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 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: # Check request and prime account on success. acctmgr.validate_account(req, 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. acctmgr._notify('registration_approval_required', username) 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())
def _pretty_dateinfo(date, format=None, dateonly=False): absolute = format_datetime(date, tzinfo=req.tz) relative = pretty_timedelta(date) if format == 'absolute': label = absolute # TRANSLATOR: Sync with same msgid in Trac 0.13, please. title = _("%(relativetime)s ago", relativetime=relative) else: if dateonly: label = relative else: label = _("%(relativetime)s ago", relativetime=relative) title = absolute return tag.span(label, title=title)
def _do_reset_password(self, req): email = req.args.get('email') username = req.args.get('username') if not username: add_warning(req, _("Username is required.")) elif not email: add_warning(req, _("Email is required.")) else: for username_, name, email_ in self.env.get_known_users(): if username_ == username and email_ == email: self._reset_password(req, username, email) return add_warning(req, _("Email and username must match a known account."))
def _do_reset_password(self, req): email = req.args.get('email') username = req.args.get('username') if not username: add_warning(req, _("Username is required.")) elif not email: add_warning(req, _("Email is required.")) else: for username_, name, email_ in self.env.get_known_users(): if username_ == username and email_ == email: self._reset_password(req, username, email) return add_warning(req, _( "Email and username must match a known account."))
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 \ acctmgr.verify_email data['verify_account_enabled'] = verify_enabled if req.method == 'POST' and action == 'create': try: # Check request and prime account on success. acctmgr.validate_registration(req) 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 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())
def process_request(self, req): if req.path_info.startswith('/login') and req.authname == 'anonymous': try: referer = self._referer(req) except AttributeError: # Fallback for Trac 0.11 compatibility. referer = req.get_header('Referer') # Steer clear of requests going nowhere or loop to self. if referer is None or \ referer.startswith(str(req.abs_href()) + '/login'): referer = req.abs_href() data = { '_dgettext': dgettext, 'login_opt_list': self.login_opt_list, 'persistent_sessions': AccountManager(self.env ).persistent_sessions, 'referer': referer, 'registration_enabled': RegistrationModule(self.env).enabled, 'reset_password_enabled': AccountModule(self.env ).reset_password_enabled } if req.method == 'POST': self.log.debug( "LoginModule.process_request: 'user_locked' = %s" % req.args.get('user_locked')) if not req.args.get('user_locked'): # TRANSLATOR: Intentionally obfuscated login error data['login_error'] = _("Invalid username or password") else: f_user = req.args.get('user') release_time = AccountGuard(self.env ).pretty_release_time(req, f_user) if not release_time is None: data['login_error'] = _( """Account locked, please try again after %(release_time)s """, release_time=release_time) else: data['login_error'] = _("Account locked") return 'login.html', data, None else: n_plural=req.args.get('failed_logins') if n_plural > 0: chrome.add_warning(req, Markup(tag.span(tag(ngettext( "Login after %(attempts)s failed attempt", "Login after %(attempts)s failed attempts", n_plural, attempts=n_plural ))))) return auth.LoginModule.process_request(self, req)
def _do_delete(self, req): user = req.authname password = req.args.get('password') if not password: return {'delete_error': _("Password cannot be empty.")} if not self.acctmgr.check_password(user, password): return {'delete_error': _("Password is incorrect.")} self.acctmgr.delete_user(user) # 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())
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: self.acctmgr.delete_user(username) # 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())
def replace(self, old_uid, new_uid, db): if not self.enabled: plugin = 'TracAnnouncer' result = _("Unsupported db schema version, please update " "%(plugin)s to a recent version.", plugin=plugin) return dict(error={('subscriptions', 'sid', None): result}) results=dict() self.column = 'sid' self.table = 'subscription' result = super(TracAnnouncerUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) self.table = 'subscription_attribute' result = super(TracAnnouncerUserIdChanger, self).replace(old_uid, new_uid, db) if 'error' in result: return result results.update(result) return results
def replace(self, old_uid, new_uid): if not self.enabled: plugin = 'TracForms' result = _( "Unsupported db schema version, please update " "%(plugin)s to a recent version.", plugin=plugin) return dict(error={('forms', 'author', None): result}) results = dict() self.table = 'forms' result = super(TracFormsUserIdChanger, self).replace(old_uid, new_uid) if 'error' in result: return result results.update(result) self.table = 'forms_fields' result = super(TracFormsUserIdChanger, self).replace(old_uid, new_uid) if 'error' in result: return result results.update(result) self.table = 'forms_history' result = super(TracFormsUserIdChanger, self).replace(old_uid, new_uid) if 'error' in result: return result results.update(result) return results
def replace(self, old_uid, new_uid): if not self.enabled: plugin = 'TracForms' result = _("Unsupported db schema version, please update " "%(plugin)s to a recent version.", plugin=plugin) return dict(error={('forms', 'author', None): result}) results = dict() self.table = 'forms' result = super(TracFormsUserIdChanger, self).replace(old_uid, new_uid) if 'error' in result: return result results.update(result) self.table = 'forms_fields' result = super(TracFormsUserIdChanger, self).replace(old_uid, new_uid) if 'error' in result: return result results.update(result) self.table = 'forms_history' result = super(TracFormsUserIdChanger, self).replace(old_uid, new_uid) if 'error' in result: return result results.update(result) return results
def replace(self, old_uid, new_uid): if not self.enabled: plugin = 'TracAnnouncer' result = _( "Unsupported db schema version, please update " "%(plugin)s to a recent version.", plugin=plugin) return dict(error={('subscriptions', 'sid', None): result}) results = {} self.column = 'sid' self.table = 'subscription' result = super(TracAnnouncerUserIdChanger, self).\ replace(old_uid, new_uid) if 'error' in result: return result results.update(result) self.table = 'subscription_attribute' result = super(TracAnnouncerUserIdChanger, self).\ replace(old_uid, new_uid) if 'error' in result: return result results.update(result) return results
def process_request(self, req): if req.authname != 'anonymous': req.redirect(req.href.prefs('account')) action = req.args.get('action') data = { 'acctmgr': { 'username': None, 'name': None, 'email': None, }, '_dgettext': dgettext, } data['verify_account_enabled'] = is_enabled( self.env, EmailVerificationModule) and self.acctmgr.verify_email if req.method == 'POST' and action == 'create': try: _create_user(req, self.env) except TracError, e: data['registration_error'] = e.message data['acctmgr'] = getattr(e, 'acctmgr', '') else: chrome.add_notice( req, Markup( tag.span( Markup( _("""Registration has been finished successfully. You may login as user %(user)s now.""", user=tag.b(req.args.get('username'))))))) req.redirect(req.href.login())
def get_navigation_items(self, req): loginmod = LoginModule(self.env) if not self.enabled: return if req.authname == 'anonymous': yield 'metanav', 'register', tag.a(_("Register"), href=req.href.register())
def pre_process_request(self, req, handler): if not req.session.authenticated: # Permissions for anonymous users remain unchanged. return handler if AccountManager(self.env).verify_email and handler is not self and \ 'email_verification_token' in req.session and \ not req.perm.has_permission('ACCTMGR_ADMIN'): # TRANSLATOR: Your permissions have been limited until you ... link = tag.a(_("verify your email address"), href=req.href.verify_email()) # TRANSLATOR: ... verify your email address chrome.add_warning(req, Markup(tag.span(Markup(_( "Your permissions have been limited until you %(link)s.", link=link))))) req.perm = perm.PermissionCache(self.env, 'anonymous') return handler
def get_navigation_items(self, req): if self.reset_password_enabled and \ LoginModule(self.env).enabled and \ req.authname == 'anonymous': yield 'metanav', 'reset_password', \ tag.a(_("Forgot your password?"), href=req.href.reset_password())
def get_preference_panels(self, req): writable = self._write_check() if not writable: return if req.authname and req.authname != 'anonymous': user_store = self.acctmgr.find_user_store(req.authname) if user_store in writable: yield 'account', _("Account")
def _do_reset_password(self, req): if req.authname and req.authname != 'anonymous': return {'logged_in': True} if req.method != 'POST': return {} username = req.args.get('username') email = req.args.get('email') if not username: return {'error': _("Username is required")} if not email: return {'error': _("Email is required")} for username_, name, email_ in self.env.get_known_users(): if username_ == username and email_ == email: error = self._reset_password(username, email) return error and error or {'sent_to_email': email} return {'error': _( "The email and username must match a known account.")}
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 _reset_password(self, req, username, email): acctmgr = self.acctmgr new_password = self._random_password try: self.store.set_password(username, new_password) acctmgr._notify('password_reset', username, email, new_password) # 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)) except Exception, e: add_warning( req, _("Cannot reset password: %(error)s", error=', '.join(map(to_unicode, e.args)))) return
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 pre_process_request(self, req, handler): if not req.session.authenticated: # Permissions for anonymous users remain unchanged. return handler if AccountManager(self.env).verify_email and handler is not self and \ 'email_verification_token' in req.session and \ not req.perm.has_permission('ACCTMGR_ADMIN'): # TRANSLATOR: Your permissions have been limited until you ... link = tag.a(_("verify your email address"), href=req.href.verify_email()) # TRANSLATOR: ... verify your email address chrome.add_warning( req, Markup( tag.span( Markup( _("Your permissions have been limited until you %(link)s.", link=link))))) req.perm = perm.PermissionCache(self.env, 'anonymous') return handler
def htpasswd(password, hash): if hash.startswith('$apr1$'): return md5crypt(password, hash[6:].split('$')[0], '$apr1$') elif hash.startswith('{SHA}'): return '{SHA}' + sha1(password).digest().encode('base64')[:-1] elif crypt is None: # crypt passwords are only supported on Unix-like systems raise NotImplementedError(_("""The \"crypt\" module is unavailable on this platform.""")) else: return crypt(password, hash)
def _do_account(self, req): if not req.authname or req.authname == 'anonymous': # DEVEL: Shouldn't this be a more generic URL? req.redirect(req.href.wiki()) action = req.args.get('action') delete_enabled = self.acctmgr.supports('delete_user') and \ self.acctmgr.allow_delete_account data = { 'delete_enabled': delete_enabled, 'delete_msg_confirm': _("Are you sure you want to delete your account?"), } force_change_password = req.session.get('force_change_passwd', False) if req.method == 'POST': if action == 'save': data.update(self._do_change_password(req)) if force_change_password: del (req.session['force_change_passwd']) req.session.save() chrome.add_notice( req, Markup( tag.span( tag_( "Thank you for taking the time to update your password." )))) force_change_password = False elif action == 'delete' and delete_enabled: data.update(self._do_delete(req)) else: data.update({'error': 'Invalid action'}) if force_change_password: chrome.add_warning( req, Markup( tag.span( _("You are required to change password because of a recent " "password change request. "), tag.b(_("Please change your password now."))))) return data
def process_request(self, req): data = dict(_dgettext=dgettext) if req.authname and req.authname != 'anonymous': add_notice(req, Markup(tag_( "You're already logged in. If you need to change your " "password please use the %(prefs_href)s page.", prefs_href=tag.a(_("Account Preferences"), href=req.href.prefs('account'))))) data['authenticated'] = True if req.method == 'POST': self._do_reset_password(req) return 'reset_password.html', data, None
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())
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())
def _do_change_password(self, req): username = req.authname old_password = req.args.get('old_password') if not self.acctmgr.check_password(username, old_password): if old_password: add_warning(req, _("Old password is incorrect.")) else: add_warning(req, _("Old password cannot be empty.")) return password = req.args.get('password') if not password: add_warning(req, _("Password cannot be empty.")) elif password != req.args.get('password_confirm'): add_warning(req, _("The passwords must match.")) elif password == old_password: add_warning(req, _("Password must not match old password.")) else: _set_password(self.env, req, username, password, old_password) if req.session.get('password') is not None: # Fetch all session_attributes in case new user password is in # SessionStore, preventing overwrite by session.save(). req.session.get_session(req.authname, authenticated=True) add_notice(req, _("Password updated successfully.")) return True