# -*- coding: utf-8 -*- # # Copyright (C) 2005 Matthew Good # # "THE BEER-WARE LICENSE" (Revision 42): # wrote this file. As long as you retain this notice you # can do whatever you want with this stuff. If we meet some day, and you think # this stuff is worth it, you can buy me a beer in return. Matthew Good # # Author: Matthew Good import inspect from trac.core import * from trac.config import Option from trac.perm import PermissionSystem from trac.util import sorted from trac.util.datefmt import format_datetime from trac.web.chrome import ITemplateProvider from webadmin.web_ui import IAdminPageProvider from acct_mgr.api import AccountManager from acct_mgr.web_ui import _create_user def _getoptions(cls): if isinstance(cls, Component): cls = cls.__class__ return [(name, value) for name, value in inspect.getmembers(cls) if isinstance(value, Option)] 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', 'Comptes', 'config', 'Configuration') yield ('accounts', 'Comptes', 'users', 'Utilisateurs') 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'] = u'L\'espace de stockage des ' \ u'mots de passe ne supporte ' \ u'pas la création des utilisateurs' 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'] = u'L\'espace de stockage des ' \ u'mots de passe ne supporte ' \ u'pas la suppression des utilisateurs' 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 # ITemplateProvider def get_htdocs_dirs(self): """Return the absolute path of a directory containing additional static resources (such as images, style sheets, etc). """ return [] def get_templates_dirs(self): """Return the absolute path of the directory containing the provided ClearSilver templates. """ from pkg_resources import resource_filename return [resource_filename(__name__, 'templates')]