Ejemplo n.º 1
0
 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'))
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
    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
Ejemplo n.º 8
0
 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
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
    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
Ejemplo n.º 11
0
 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
Ejemplo n.º 12
0
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)
Ejemplo n.º 13
0
    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
Ejemplo n.º 14
0
    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
Ejemplo n.º 15
0
    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}
Ejemplo n.º 16
0
 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
Ejemplo n.º 17
0
 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)
Ejemplo n.º 18
0
    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__)
Ejemplo n.º 19
0
    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__)
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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))
Ejemplo n.º 22
0
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))
Ejemplo n.º 23
0
 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())
Ejemplo n.º 24
0
 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)
Ejemplo n.º 25
0
 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."))
Ejemplo n.º 26
0
 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."))
Ejemplo n.º 27
0
 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)
Ejemplo n.º 28
0
 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())
Ejemplo n.º 29
0
 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)
Ejemplo n.º 30
0
    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())
Ejemplo n.º 31
0
    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())
Ejemplo n.º 32
0
    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())
Ejemplo n.º 33
0
    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
Ejemplo n.º 34
0
    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
Ejemplo n.º 35
0
    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
Ejemplo n.º 36
0
    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
Ejemplo n.º 37
0
 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())
Ejemplo n.º 38
0
 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())
Ejemplo n.º 39
0
 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())
Ejemplo n.º 40
0
 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
Ejemplo n.º 41
0
 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())
Ejemplo n.º 42
0
 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")
Ejemplo n.º 43
0
 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.")}
Ejemplo n.º 44
0
 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")
Ejemplo n.º 45
0
    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))
Ejemplo n.º 46
0
 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
Ejemplo n.º 47
0
    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))
Ejemplo n.º 48
0
 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
Ejemplo n.º 49
0
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)
Ejemplo n.º 50
0
 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
Ejemplo n.º 51
0
 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
Ejemplo n.º 52
0
    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())
Ejemplo n.º 53
0
    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())
Ejemplo n.º 54
0
    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