Ejemplo n.º 1
0
class AccountManagerAdminPage(Component):

    implements(IAdminPanelProvider, ITemplateProvider)

    def __init__(self):
        self.account_manager = AccountManager(self.env)

    # IAdminPageProvider
    def get_admin_panels(self, req):
        if req.perm.has_permission('TRAC_ADMIN'):
            yield ('accounts', 'Accounts', 'config', 'Configuration')
            yield ('accounts', 'Accounts', 'users', 'Users')

    def render_admin_panel(self, req, cat, page, path_info):
        if page == 'config':
            return self._do_config(req)
        elif page == 'users':
            return self._do_users(req)

    def _do_config(self, req):
        stores = StoreOrder(stores=self.account_manager.stores,
                            list=self.account_manager.password_store)
        if req.method == 'POST':
            _setorder(req, stores)
            self.config.set('account-manager', 'password_store',
                            ','.join(stores.get_enabled_store_names()))
            for store in stores.get_all_stores():
                for attr, option in _getoptions(store):
                    newvalue = req.args.get('%s.%s' % (store.__class__.__name__, attr))
                    self.log.debug("%s.%s: %s" % (store.__class__.__name__, attr, newvalue))
                    if newvalue is not None:
                        self.config.set(option.section, option.name, newvalue)
                        self.config.save()
            self.config.set('account-manager', 'force_passwd_change',
                            req.args.get('force_passwd_change'))
            self.config.save()
        sections = []
        for store in self.account_manager.stores:
            options = []
            for attr, option in _getoptions(store):
                opt_val = option.__get__(store, store)
                opt_val = isinstance(opt_val, Component) and \
                          opt_val.__class__.__name__ or opt_val
                options.append(
                            {'label': attr,
                            'name': '%s.%s' % (store.__class__.__name__, attr),
                            'value': opt_val,
                            })
                continue
            sections.append(
                        {'name': store.__class__.__name__,
                        'classname': store.__class__.__name__,
                        'order': stores[store],
                        'options' : options,
                        })
            continue
        sections = sorted(sections, key=lambda i: i['name'])
        numstores = range(0, stores.numstores() + 1)
        data = {'sections': sections,
                'numstores': numstores,
                'force_passwd_change': self.account_manager.force_passwd_change}
        return 'admin_accountsconfig.html', data

    def _do_users(self, req):
        perm = PermissionSystem(self.env)
        listing_enabled = self.account_manager.supports('get_users')
        create_enabled = self.account_manager.supports('set_password')
        password_change_enabled = self.account_manager.supports('set_password')
        delete_enabled = self.account_manager.supports('delete_user')

        data = {
            'listing_enabled': listing_enabled,
            'create_enabled': create_enabled,
            'delete_enabled': delete_enabled,
            'password_change_enabled': password_change_enabled,
            'acctmgr' : { 'username' : None,
                          'name' : None,
                          'email' : None,
                        }
        }

        if req.method == 'POST':
            if req.args.get('add'):
                if create_enabled:
                    try:
                        _create_user(req, self.env, check_permissions=False)
                    except TracError, e:
                        data['registration_error'] = e.message
                        data['acctmgr'] = e.acctmgr
                else:
                    data['registration_error'] = 'The password store does ' \
                                                 'not support creating users'
            elif req.args.get('remove'):
                if delete_enabled:
                    sel = req.args.get('sel')
                    sel = isinstance(sel, list) and sel or [sel]
                    for account in sel:
                        self.account_manager.delete_user(account)
                else:
                    data['deletion_error'] = 'The password store does not ' \
                                             'support deleting users'
            elif req.args.get('change'):
                if password_change_enabled:
                    try:
                        user = req.args.get('change_user')
                        acctmgr = { 'change_username' : user,
                        }
                        error = TracError('')
                        error.acctmgr = acctmgr
                        if not user:
                            error.message = 'Username cannot be empty.'
                            raise error

                        password = req.args.get('change_password')
                        if not password:
                            error.message = 'Password cannot be empty.'
                            raise error

                        if password != req.args.get('change_password_confirm'):
                            error.message = 'The passwords must match.'
                            raise error

                        self.account_manager.set_password(user, password)
                    except TracError, e:
                        data['password_change_error'] = e.message
                        data['acctmgr'] = getattr(e, 'acctmgr', '')
                else:
                    data['password_change_error'] = 'The password store does not ' \
                                                    'support changing passwords'
class AccountManagerAdminPage(Component):

    implements(IAdminPanelProvider, ITemplateProvider)

    def __init__(self):
        self.account_manager = AccountManager(self.env)

    # IAdminPageProvider
    def get_admin_panels(self, req):
        if req.perm.has_permission("TRAC_ADMIN"):
            yield ("accounts", "Accounts", "config", "Configuration")
            yield ("accounts", "Accounts", "users", "Users")

    def render_admin_panel(self, req, cat, page, path_info):
        if page == "config":
            return self._do_config(req)
        elif page == "users":
            return self._do_users(req)

    def _do_config(self, req):
        stores = StoreOrder(stores=self.account_manager.stores, list=self.account_manager.password_store)
        if req.method == "POST":
            _setorder(req, stores)
            self.config.set("account-manager", "password_store", ",".join(stores.get_enabled_store_names()))
            for store in stores.get_all_stores():
                for attr, option in _getoptions(store):
                    newvalue = req.args.get("%s.%s" % (store.__class__.__name__, attr))
                    self.log.debug("%s.%s: %s" % (store.__class__.__name__, attr, newvalue))
                    if newvalue is not None:
                        self.config.set(option.section, option.name, newvalue)
                        self.config.save()
            self.config.set("account-manager", "force_passwd_change", req.args.get("force_passwd_change"))
            self.config.set("account-manager", "persistent_sessions", req.args.get("persistent_sessions"))
            self.config.save()
        sections = []
        for store in self.account_manager.stores:
            options = []
            for attr, option in _getoptions(store):
                opt_val = option.__get__(store, store)
                opt_val = isinstance(opt_val, Component) and opt_val.__class__.__name__ or opt_val
                options.append({"label": attr, "name": "%s.%s" % (store.__class__.__name__, attr), "value": opt_val})
                continue
            sections.append(
                {
                    "name": store.__class__.__name__,
                    "classname": store.__class__.__name__,
                    "order": stores[store],
                    "options": options,
                }
            )
            continue
        sections = sorted(sections, key=lambda i: i["name"])
        numstores = range(0, stores.numstores() + 1)
        data = {
            "sections": sections,
            "numstores": numstores,
            "force_passwd_change": self.account_manager.force_passwd_change,
            "persistent_sessions": self.account_manager.persistent_sessions,
        }
        return "admin_accountsconfig.html", data

    def _do_users(self, req):
        perm = PermissionSystem(self.env)
        listing_enabled = self.account_manager.supports("get_users")
        create_enabled = self.account_manager.supports("set_password")
        password_change_enabled = self.account_manager.supports("set_password")
        delete_enabled = self.account_manager.supports("delete_user")

        data = {
            "listing_enabled": listing_enabled,
            "create_enabled": create_enabled,
            "delete_enabled": delete_enabled,
            "password_change_enabled": password_change_enabled,
            "acctmgr": {"username": None, "name": None, "email": None},
        }

        if req.method == "POST":
            if req.args.get("add"):
                if create_enabled:
                    try:
                        _create_user(req, self.env, check_permissions=False)
                    except TracError, e:
                        data["registration_error"] = e.message
                        data["acctmgr"] = e.acctmgr
                else:
                    data["registration_error"] = "The password store does " "not support creating users"
            elif req.args.get("remove"):
                if delete_enabled:
                    sel = req.args.get("sel")
                    sel = isinstance(sel, list) and sel or [sel]
                    for account in sel:
                        self.account_manager.delete_user(account)
                else:
                    data["deletion_error"] = "The password store does not " "support deleting users"
            elif req.args.get("change"):
                if password_change_enabled:
                    try:
                        user = req.args.get("change_user")
                        acctmgr = {"change_username": user}
                        error = TracError("")
                        error.acctmgr = acctmgr
                        if not user:
                            error.message = "Username cannot be empty."
                            raise error

                        password = req.args.get("change_password")
                        if not password:
                            error.message = "Password cannot be empty."
                            raise error

                        if password != req.args.get("change_password_confirm"):
                            error.message = "The passwords must match."
                            raise error

                        self.account_manager.set_password(user, password)
                    except TracError, e:
                        data["password_change_error"] = e.message
                        data["acctmgr"] = getattr(e, "acctmgr", "")
                else:
                    data["password_change_error"] = "The password store does not " "support changing passwords"
Ejemplo n.º 3
0
class AccountModule(CommonTemplateProvider):
    """Exposes methods for users to do account management on their own.

    Allows users to change their password, reset their password, if they've
    forgotten it, even delete their account.  The settings for the
    AccountManager module must be set in trac.ini in order to use this.
    Password reset procedure depends on both, ResetPwStore and an
    IPasswordHashMethod implementation being enabled as well.
    """

    implements(IPreferencePanelProvider, IRequestHandler,
               INavigationContributor, IRequestFilter)

    _password_chars = string.ascii_letters + string.digits
    password_length = IntOption(
        'account-manager', 'generated_password_length', 8,
        """Length of the randomly-generated passwords created when resetting
        the password for an account.""")
    reset_password = BoolOption(
        'account-manager', 'reset_password', True,
        'Set to False, if there is no email system setup.')

    def __init__(self):
        self.acctmgr = AccountManager(self.env)
        self.store = ResetPwStore(self.env)
        self._write_check(log=True)

    def _write_check(self, log=False):
        """Returns all configured write-enabled password stores."""
        writable = self.acctmgr.get_all_supporting_stores('set_password')
        if writable:
            try:
                writable = writable.remove(self.store)
            except ValueError:
                # ResetPwStore is not enabled.
                if log:
                    self.log.warn("ResetPwStore is disabled, therefor "
                                  "password reset won't work.")
        # Require at least one more write-enabled password store.
        if not writable and log:
            self.log.warn("AccountModule is disabled because no configured "
                          "password store supports writing.")
        return writable

    # INavigationContributor methods

    def get_active_navigation_item(self, req):
        return 'reset_password'

    def get_navigation_items(self, req):
        if not self.reset_password_enabled or LoginModule(self.env).enabled:
            return
        if req.authname == 'anonymous':
            yield 'metanav', 'reset_password', tag.a(
                _("Forgot your password?"), href=req.href.reset_password())

    def _reset_password_enabled(self, log=False):
        try:
            self.store.hash_method
        except AttributeError:
            return False
        return is_enabled(self.env, self.__class__) and \
               self.reset_password and (self._write_check(log) != []) and \
               is_enabled(self.env, self.store.__class__) and \
               self.store.hash_method and True or False

    reset_password_enabled = property(_reset_password_enabled)

    # IPreferencePanelProvider methods

    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 render_preference_panel(self, req, panel):
        data = dict(_dgettext=dgettext)
        data.update(self._do_account(req))
        return 'prefs_account.html', data

    # IRequestFilter methods

    def pre_process_request(self, req, handler):
        if req.path_info == '/prefs/account' and \
                not (req.authname and req.authname != 'anonymous'):
            # An anonymous session has no account associated with it, and
            # no account properies too, but general session preferences should
            # always be available.
            req.redirect(req.href.prefs())
        return handler

    def post_process_request(self, req, template, data, content_type):
        if req.authname and req.authname != 'anonymous':
            if req.session.get('force_change_passwd', False):
                # Prevent authenticated usage before another password change.
                redirect_url = req.href.prefs('account')
                if req.href(req.path_info) != redirect_url:
                    req.redirect(redirect_url)
        return (template, data, content_type)

    # IRequestHandler methods

    def match_request(self, req):
        return req.path_info == '/reset_password' and \
               self._reset_password_enabled(log=True)

    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_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 _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:
            self.acctmgr.set_password(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

    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 _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."))

    @property
    def _random_password(self):
        return ''.join([
            random.choice(self._password_chars)
            for _ in xrange(self.password_length)
        ])

    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
        if acctmgr.force_passwd_change:
            set_user_attribute(self.env, username, 'force_change_passwd', 1)
Ejemplo n.º 4
0
class AccountManagerAdminPage(Component):

    implements(IAdminPageProvider)

    def __init__(self):
        self.account_manager = AccountManager(self.env)

    # IAdminPageProvider
    def get_admin_pages(self, req):
        if req.perm.has_permission('TRAC_ADMIN'):
            yield ('accounts', 'Accounts', 'config', 'Configuration')
            yield ('accounts', 'Accounts', 'users', 'Users')

    def process_admin_request(self, req, cat, page, path_info):
        if page == 'config':
            return self._do_config(req)
        elif page == 'users':
            return self._do_users(req)

    def _do_config(self, req):
        if req.method == 'POST':
            selected_class = req.args.get('selected')
            self.config.set('account-manager', 'password_store',
                            selected_class)
            selected = self.account_manager.password_store
            for attr, option in _getoptions(selected):
                newvalue = req.args.get('%s.%s' % (selected_class, attr))
                if newvalue is not None:
                    self.config.set(option.section, option.name, newvalue)
                    self.config.save()
        try:
            selected = self.account_manager.password_store
        except AttributeError:
            selected = None
        sections = [{
            'name':
            store.__class__.__name__,
            'classname':
            store.__class__.__name__,
            'selected':
            store is selected,
            'options': [{
                'label': attr,
                'name': '%s.%s' % (store.__class__.__name__, attr),
                'value': option.__get__(store, store),
            } for attr, option in _getoptions(store)],
        } for store in self.account_manager.stores]
        sections = sorted(sections, key=lambda i: i['name'])
        req.hdf['sections'] = sections
        return 'admin_accountsconfig.cs', None

    def _do_users(self, req):
        perm = PermissionSystem(self.env)
        listing_enabled = self.account_manager.supports('get_users')
        create_enabled = self.account_manager.supports('set_password')
        delete_enabled = self.account_manager.supports('delete_user')

        req.hdf['listing_enabled'] = listing_enabled
        req.hdf['create_enabled'] = create_enabled
        req.hdf['delete_enabled'] = delete_enabled

        if req.method == 'POST':
            if req.args.get('add'):
                if create_enabled:
                    try:
                        _create_user(req, self.env, check_permissions=False)
                    except TracError, e:
                        req.hdf['registration.error'] = e.message
                else:
                    req.hdf['registration_error'] = 'The password store does ' \
                                                    'not support creating users'
            elif req.args.get('remove'):
                if delete_enabled:
                    sel = req.args.get('sel')
                    sel = isinstance(sel, list) and sel or [sel]
                    for account in sel:
                        self.account_manager.delete_user(account)
                else:
                    req.hdf['deletion_error'] = 'The password store does not ' \
                                                'support deleting users'
        if listing_enabled:
            accounts = {}
            for username in self.account_manager.get_users():
                accounts[username] = {'username': username}

            for username, name, email in self.env.get_known_users():
                account = accounts.get(username)
                if account:
                    account['name'] = name
                    account['email'] = email

            db = self.env.get_db_cnx()
            cursor = db.cursor()
            cursor.execute(
                "SELECT sid,last_visit FROM session WHERE authenticated=1")
            for username, last_visit in cursor:
                account = accounts.get(username)
                if account and last_visit:
                    account['last_visit'] = format_datetime(last_visit)

            req.hdf['accounts'] = sorted(accounts.itervalues(),
                                         key=lambda acct: acct['username'])

        return 'admin_users.cs', None
Ejemplo n.º 5
0
class AccountModule(CommonTemplateProvider):
    """Exposes methods for users to do account management on their own.

    Allows users to change their password, reset their password, if they've
    forgotten it, even delete their account.  The settings for the
    AccountManager module must be set in trac.ini in order to use this.
    Password reset procedure depends on both, ResetPwStore and an
    IPasswordHashMethod implementation being enabled as well.
    """

    implements(IPreferencePanelProvider, IRequestHandler,
               INavigationContributor, IRequestFilter)

    _password_chars = string.ascii_letters + string.digits
    password_length = IntOption(
        'account-manager', 'generated_password_length', 8,
        """Length of the randomly-generated passwords created when resetting
        the password for an account.""")
    reset_password = BoolOption(
        'account-manager', 'reset_password', True,
        'Set to False, if there is no email system setup.')

    def __init__(self):
        self.acctmgr = AccountManager(self.env)
        self.store = ResetPwStore(self.env)
        self._write_check(log=True)

    def _write_check(self, log=False):
        """Returns all configured write-enabled password stores."""
        writable = self.acctmgr.get_all_supporting_stores('set_password')
        if writable:
            try:
                writable = writable.remove(self.store)
            except ValueError:
                # ResetPwStore is not enabled.
                if log:
                    self.log.warn("ResetPwStore is disabled, therefor "
                                  "password reset won't work.")
        # Require at least one more write-enabled password store.
        if not writable and log:
            self.log.warn("AccountModule is disabled because no configured "
                          "password store supports writing.")
        return writable

    # INavigationContributor methods

    def get_active_navigation_item(self, req):
        return 'reset_password'

    def get_navigation_items(self, req):
        if not self.reset_password_enabled or LoginModule(self.env).enabled:
            return
        if req.authname == 'anonymous':
            yield 'metanav', 'reset_password', tag.a(
                _("Forgot your password?"), href=req.href.reset_password())

    def _reset_password_enabled(self, log=False):
        try:
            self.store.hash_method
        except (AttributeError, ConfigurationError):
            return False
        return is_enabled(self.env, self.__class__) and \
               self.reset_password and (self._write_check(log) != []) and \
               is_enabled(self.env, self.store.__class__) and \
               self.store.hash_method and True or False

    reset_password_enabled = property(_reset_password_enabled)

    # IPreferencePanelProvider methods

    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 render_preference_panel(self, req, panel):
        data = dict(_dgettext=dgettext)
        data.update(self._do_account(req))
        return 'prefs_account.html', data

    # IRequestFilter methods

    def pre_process_request(self, req, handler):
        if req.path_info == '/prefs/account' and \
                not (req.authname and req.authname != 'anonymous'):
            # An anonymous session has no account associated with it, and
            # no account properies too, but general session preferences should
            # always be available.
            req.redirect(req.href.prefs())
        return handler

    def post_process_request(self, req, template, data, content_type):
        if req.authname and req.authname != 'anonymous':
            if req.session.get('force_change_passwd', False):
                # Prevent authenticated usage before another password change.
                redirect_url = req.href.prefs('account')
                if req.href(req.path_info) != redirect_url:
                    req.redirect(redirect_url)
        return (template, data, content_type)

    # IRequestHandler methods

    def match_request(self, req):
        return req.path_info == '/reset_password' and \
               self._reset_password_enabled(log=True)

    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_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 _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

    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.º 6
0
class AccountManagerAdminPage(Component):

    implements(IAdminPageProvider)

    def __init__(self):
        self.account_manager = AccountManager(self.env)

    # IAdminPageProvider
    def get_admin_pages(self, req):
        if req.perm.has_permission('TRAC_ADMIN'):
            yield ('accounts', 'Accounts', 'config', 'Configuration') 
            yield ('accounts', 'Accounts', 'users', 'Users')

    def process_admin_request(self, req, cat, page, path_info):
        if page == 'config': 
            return self._do_config(req)
        elif page == 'users': 
            return self._do_users(req) 
            
    def _do_config(self, req):
        if req.method == 'POST':
            selected_class = req.args.get('selected')
            self.config.set('account-manager', 'password_store', selected_class)
            selected = self.account_manager.password_store
            for attr, option in _getoptions(selected):
                newvalue = req.args.get('%s.%s' % (selected_class, attr))
                if newvalue is not None:
                    self.config.set(option.section, option.name, newvalue)
                    self.config.save()
        try:
            selected = self.account_manager.password_store
        except AttributeError:
            selected = None
        sections = [
            {'name': store.__class__.__name__,
             'classname': store.__class__.__name__,
             'selected': store is selected,
             'options': [
                {'label': attr,
                 'name': '%s.%s' % (store.__class__.__name__, attr),
                 'value': option.__get__(store, store),
                }
                for attr, option in _getoptions(store)
             ],
            } for store in self.account_manager.stores
        ]
        sections = sorted(sections, key=lambda i: i['name'])
        req.hdf['sections'] = sections
        return 'admin_accountsconfig.cs', None
            
    def _do_users(self, req):
        perm = PermissionSystem(self.env)
        listing_enabled = self.account_manager.supports('get_users')
        create_enabled = self.account_manager.supports('set_password') 
        delete_enabled = self.account_manager.supports('delete_user')
        
        req.hdf['listing_enabled'] = listing_enabled
        req.hdf['create_enabled'] = create_enabled
        req.hdf['delete_enabled'] = delete_enabled
        
        if req.method == 'POST':
            if req.args.get('add'):
                if create_enabled:
                    try:
                        _create_user(req, self.env, check_permissions=False)
                    except TracError, e:
                        req.hdf['registration.error'] = e.message
                else:
                    req.hdf['registration_error'] = 'The password store does ' \
                                                    'not support creating users'
            elif req.args.get('remove'):
                if delete_enabled:
                    sel = req.args.get('sel')
                    sel = isinstance(sel, list) and sel or [sel]
                    for account in sel:
                        self.account_manager.delete_user(account)
                else:
                    req.hdf['deletion_error'] = 'The password store does not ' \
                                                'support deleting users'
        if listing_enabled:
            accounts = {}
            for username in self.account_manager.get_users():
                accounts[username] = {'username': username}

            for username, name, email in self.env.get_known_users():
                account = accounts.get(username)
                if account:
                    account['name'] = name
                    account['email'] = email

            db = self.env.get_db_cnx()
            cursor = db.cursor()
            cursor.execute("SELECT sid,last_visit FROM session WHERE authenticated=1")
            for username, last_visit in cursor:
                account = accounts.get(username)
                if account and last_visit:
                    account['last_visit'] = format_datetime(last_visit)

            req.hdf['accounts'] = sorted(accounts.itervalues(),
                                         key=lambda acct: acct['username'])

        return 'admin_users.cs', None