Example #1
0
    def init(self):
        self.title = _('Configure')
        self.icon = 'wrench'
        self.category = ''
        self.order = 50

        self.append(self.ui.inflate('configurator:main'))

        self.binder = Binder(ajenti.config.tree, self.find('ajenti-config'))

        self.ccmgr = ClassConfigManager.get()
        self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs'))
        self.classconfig_rows = {}

        def post_classconfig_bind(object, collection, item, ui):
            self.classconfig_rows[item] = ui
            editor = item.classconfig_editor.new(self.ui)
            ui.find('container').append(editor)
            binder = DictAutoBinding(item, 'classconfig', editor.find('bind'))
            binder.populate()

            def save():
                binder.update()
                item.save_classconfig()
                self.context.notify('info', _('Saved'))

            ui.find('save').on('click', save)

        self.find('classconfigs').find('classes').post_item_bind = post_classconfig_bind

        self.find('users').new_item = lambda c: UserData()

        def post_user_bind(object, collection, item, ui):
            box = ui.find('permissions')
            box.empty()
            ui.find('name-edit').visible = item.name != 'root'
            ui.find('name-label').visible = item.name == 'root'
            for prov in PermissionProvider.get_all():
                line = self.ui.create('tab', title=prov.get_name())
                box.append(line)
                for perm in prov.get_permissions():
                    line.append(
                        self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions))
                    )
        self.find('users').post_item_bind = post_user_bind

        def post_user_update(object, collection, item, ui):
            box = ui.find('permissions')
            for prov in PermissionProvider.get_all():
                for perm in prov.get_permissions():
                    has = box.find(perm[0]).value
                    if has and not perm[0] in item.permissions:
                        item.permissions.append(perm[0])
                    if not has and perm[0] in item.permissions:
                        item.permissions.remove(perm[0])
            if ui.find('password').value:
                item.password = ui.find('password').value
        self.find('users').post_item_update = post_user_update

        self.refresh()
Example #2
0
class TestPlugin (SectionPlugin):
    def init(self):
        self.title = 'GeT3'  # those are not class attributes and can be only set in or after init()
        self.icon = 'question'
        self.category = 'Software'

        """
        UI Inflater searches for the named XML layout and inflates it into
        an UIElement object tree
        """
        settings = filter(lambda x: '_settings.py' in x , os.listdir("/home/django/get3/GeT3/settings/"))
        self.instances = [GetIstance(a) for a in settings]

        self.append(self.ui.inflate('ajenti_get:main'))
        self.binder = Binder(self, self.find('bindroot'))

        self.refresh()
        self.binder.populate()

    def refresh(self):
        """
        Changing element properties automatically results
        in an UI updated being issued to client
        """
        #self.find('counter-label').text = 'Counter: %i' % self.counter

    #@on('increment-button', 'click')
    #def on_button(self):
        """
        This method is called every time a child element
        with ID 'increment-button' fires a 'click' event
        """
        #self.counter += 1
        #self.refresh()
Example #3
0
class Supervisor (SectionPlugin):
    def init(self):
        self.title = 'Supervisor'
        self.icon = 'play'
        self.category = _('Software')
        self.append(self.ui.inflate('supervisor:main'))
        self.mgr = SupervisorServiceManager.get()
        self.binder = Binder(None, self.find('main'))
        self.find('programs').new_item = lambda c: ProgramData()
        self.config = SupervisorConfig(path=platform_select(
            default='/etc/supervisor/supervisord.conf',
            centos='/etc/supervisord.conf',
        ))
        self.find('servicebar').name = platform_select(
            centos='supervisord',
            default='supervisor',
        )
        self.find('servicebar').reload()

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.mgr.fill(self.config.tree.programs)
        self.binder.setup(self.config.tree).populate()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
Example #4
0
class Netatalk(SectionPlugin):
    config_path = "/etc/afp.conf"

    def init(self):
        self.title = "Netatalk"
        self.icon = "folder-close"
        self.category = "Software"
        self.append(self.ui.inflate("netatalk:main"))

        if not os.path.exists(self.config_path):
            open(self.config_path, "w").close()

        self.binder = Binder(None, self.find("config"))
        self.find("shares").new_item = lambda c: ShareData()
        self.config = NetatalkConfig(path=self.config_path)

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on("save", "click")
    def on_save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
Example #5
0
    def init(self):
        self.title = _('File Manager')
        self.category = _('Tools')
        self.icon = 'folder-open'

        self.backend = FMBackend().get()

        self.append(self.ui.inflate('fm:main'))
        self.controller = Controller()
        self.controller.new_tab(self.classconfig['root'])

        def post_item_bind(object, collection, item, ui):
            ui.find('name').on('click', self.on_item_click, object, item)
            ui.find('edit').on('click', self.edit, item.fullpath)
        self.find('items').post_item_bind = post_item_bind

        def post_bc_bind(object, collection, item, ui):
            ui.find('name').on('click', self.on_bc_click, object, item)
        self.find('breadcrumbs').post_item_bind = post_bc_bind

        self.binder = Binder(self.controller, self.find('filemanager')).autodiscover().populate()
        self.clipboard = []
        self.binder_c = Binder(self, self.find('bind-clipboard')).autodiscover().populate()
        self.tabs = self.find('tabs')

        self.find('dialog').buttons = [
            {'id': 'save', 'text': _('Save')},
            {'id': 'cancel', 'text': _('Cancel')},
        ]
Example #6
0
class PluginsPlugin (SectionPlugin):
    def init(self):
        self.title = _('Plugins')
        self.icon = 'cogs'
        self.category = ''
        self.order = 60

        # In case you didn't notice it yet, this is the Plugins Plugin Plugin
        self.append(self.ui.inflate('plugins:main'))

        def post_plugin_bind(object, collection, item, ui):
            if not item.crash:
                ui.find('crash').visible = False

        def post_dep_bind(object, collection, item, ui):
            if not item.satisfied():
                installer = ui.find('fix')
                if item.__class__ == ModuleDependency:
                    installer.package = 'python-module-' + item.module_name
                if item.__class__ == BinaryDependency:
                    installer.package = item.binary_name
                installer.recheck()

        self.find('plugins').post_item_bind = post_plugin_bind
        self.find('dependencies').post_item_bind = post_dep_bind

        self.binder = Binder(None, self.find('bind-root'))

    def on_page_load(self):
        self.context.endpoint.send_progress(_('Gathering plugin list'))
        self.plugins = sorted(manager.get_all().values())
        self.binder.setup(self).populate()
Example #7
0
    def init(self):
        self.title = _("Packages")
        self.icon = "gift"
        self.category = _("System")

        self.mgr = PackageManager.get()

        self.append(self.ui.inflate("packages:main"))

        def post_item_bind(object, collection, item, ui):
            ui.find("install").on("click", self.on_install, item)
            ui.find("remove").on("click", self.on_remove, item)
            ui.find("cancel").on("click", self.on_cancel, item)
            ui.find("install").visible = item.action is None
            ui.find("remove").visible = item.action is None and item.state == "i"
            ui.find("cancel").visible = item.action is not None

        self.find("upgradeable").post_item_bind = post_item_bind
        self.find("search").post_item_bind = post_item_bind
        self.find("pending").post_item_bind = post_item_bind

        self.binder = Binder(None, self.find("bind-root"))
        self.binder_p = Binder(self, self.find("bind-pending"))
        self.binder_s = CollectionAutoBinding([], None, self.find("search")).populate()

        self.pending = {}
        self.installation_running = False
        self.action_queue = []
Example #8
0
class PureFTPDExtension (BaseExtension):
    default_config = {
        'created': False,
        'password': None,
    }
    name = 'FTP'

    def init(self):
        self.append(self.ui.inflate('vh-pureftpd:ext'))
        self.binder = Binder(self, self)

        if not 'username' in self.config:
            self.config['username'] = self.website.slug
            
        if not 'system_user' in self.config:
            self.config['system_user'] = ""

        if not 'system_group' in self.config:
            self.config['system_group'] = ""


        if not self.config['created']:
            self.config['password'] = str(uuid.uuid4())
            self.config['path'] = self.website.root
            self.config['created'] = True

        self.refresh()

    def refresh(self):
        self.binder.setup().populate()

    def update(self):
        self.binder.update()
Example #9
0
class VSFTPDExtension (BaseExtension):
    default_config = {
        'created': False,
        'user': None,
        'password': None,
    }
    name = 'FTP'

    def init(self):
        self.append(self.ui.inflate('vh-vsftpd:ext'))
        self.binder = Binder(self, self)

        self.config['username'] = self.website.slug

        if not self.config['created']:
            self.config['password'] = str(uuid.uuid4())
            self.config['created'] = True

        self.refresh()

    def refresh(self):
        self.binder.setup().populate()

    def update(self):
        pass
Example #10
0
    def init(self):
        self.title = _('Packages')
        self.icon = 'gift'
        self.category = _('System')

        self.mgr = PackageManager.get()

        self.append(self.ui.inflate('packages:main'))

        def post_item_bind(object, collection, item, ui):
            ui.find('install').on('click', self.on_install, item)
            ui.find('remove').on('click', self.on_remove, item)
            ui.find('cancel').on('click', self.on_cancel, item)
            ui.find('install').visible = item.action is None
            ui.find('remove').visible = item.action is None and item.state == 'i'
            ui.find('cancel').visible = item.action is not None

        self.find('upgradeable').post_item_bind = post_item_bind
        self.find('search').post_item_bind = post_item_bind
        self.find('pending').post_item_bind = post_item_bind

        self.binder = Binder(None, self.find('bind-root'))
        self.binder_p = Binder(self, self.find('bind-pending'))
        self.binder_s = CollectionAutoBinding([], None, self.find('search')).populate()

        self.pending = {}
        self.installation_running = False
        self.action_queue = []
Example #11
0
class Squid (SectionPlugin):
    def init(self):
        self.title = _('Squid')
        self.icon = 'exchange'
        self.category = _('Software')
        self.append(self.ui.inflate('squid:main'))

        self.binder = Binder(None, self.find('config'))
        self.find('acl').new_item = lambda c: ACLData()
        self.find('http_access').new_item = lambda c: HTTPAccessData()
        self.find('http_port').new_item = lambda c: HTTPPortData()
        self.find('https_port').new_item = lambda c: HTTPSPortData()
        self.config = SquidConfig(path='/etc/squid3/squid.conf')

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
Example #12
0
class DHCPDPlugin (SectionPlugin):
    def init(self):
        self.title = _('DHCP Server')
        self.icon = 'sitemap'
        self.category = _('Software')

        self.append(self.ui.inflate('dhcpd:main'))

        self.config = DHCPDConfig(path='/etc/dhcp/dhcpd.conf')
        self.binder = Binder(None, self)

        for x in self.nearest(lambda x: x.bind == 'ranges'):
            x.new_item = lambda c: RangeData()
        for x in self.nearest(lambda x: x.bind == 'options'):
            x.new_item = lambda c: OptionData()
        self.find('subnets').new_item = lambda c: SubnetData()

    def on_page_load(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
Example #13
0
class Exports (SectionPlugin):
    config_path = '/etc/exports'

    def init(self):
        self.title = _('NFS Exports')
        self.icon = 'hdd'
        self.category = _('Software')
        self.append(self.ui.inflate('exports:main'))

        if not os.path.exists(self.config_path):
            open(self.config_path, 'w').close()

        self.config = ExportsConfig(path=self.config_path)
        self.binder = Binder(None, self)
        self.find('exports').new_item = lambda c: ExportData()
        self.find('clients').new_item = lambda c: ClientData()

    def on_page_load(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
        self.context.notify('info', _('Saved'))
Example #14
0
class PluginsPlugin (SectionPlugin):
    def init(self):
        self.title = 'Plugins'
        self.icon = 'cogs'
        self.category = ''
        self.order = 50

        # In case you didn't notice it yet, this is the Plugins Plugin Plugin
        self.append(self.ui.inflate('plugins:main'))

        def post_plugin_bind(object, collection, item, ui):
            if not item.crash:
                ui.find('crash').visible = False

        def post_dep_bind(object, collection, item, ui):
            if not item.satisfied():
                installer = ui.find('fix')
                if item.__class__ == ModuleDependency:
                    installer.package = 'python-module-' + item.module_name
                if item.__class__ == BinaryDependency:
                    installer.package = item.binary_name
                installer.recheck()

        self.find('plugins').post_item_bind = post_plugin_bind
        self.find('dependencies').post_item_bind = post_dep_bind

        self.binder = Binder(self, self.find('bind-root'))
        self.refresh()

    def refresh(self):
        self.plugins = sorted(manager.get_all().values())
        self.binder.reset().autodiscover().populate()
Example #15
0
File: fm.py Project: nnpro/ajenti
    def init(self):
        self.title = _("File Manager")
        self.category = _("Tools")
        self.icon = "folder-open"

        self.backend = FMBackend().get()

        self.append(self.ui.inflate("fm:main"))
        self.controller = Controller()
        self.controller.new_tab(self.classconfig["root"])

        def post_item_bind(object, collection, item, ui):
            ui.find("name").on("click", self.on_item_click, object, item)
            ui.find("edit").on("click", self.edit, item.fullpath)

        self.find("items").post_item_bind = post_item_bind

        def post_bc_bind(object, collection, item, ui):
            ui.find("name").on("click", self.on_bc_click, object, item)

        self.find("breadcrumbs").post_item_bind = post_bc_bind

        self.binder = Binder(self.controller, self.find("filemanager")).autodiscover().populate()
        self.clipboard = []
        self.binder_c = Binder(self, self.find("filemanager")).autodiscover().populate()
        self.tabs = self.find("tabs")

        self.find("dialog").buttons = [{"id": "save", "text": _("Save")}, {"id": "cancel", "text": _("Cancel")}]
Example #16
0
class Squid (SectionPlugin):
    def init(self):
        self.title = 'Squid'
        self.icon = 'exchange'
        self.category = _('Software')
        self.append(self.ui.inflate('squid:main'))

        self.find('servicebar').name = platform_select(
            debian='squid3',
            centos='squid',
            default='squid',
        )
        self.find('servicebar').reload()

        self.binder = Binder(None, self.find('config'))
        self.find('acl').new_item = lambda c: ACLData(name='new')
        self.find('http_access').new_item = lambda c: HTTPAccessData()
        self.find('http_port').new_item = lambda c: HTTPPortData()
        self.find('https_port').new_item = lambda c: HTTPSPortData()
        for e in self.nearest(lambda x: x.id == 'options'):
            e.new_item = lambda c: ArgumentData()
        self.config = SquidConfig(path='/etc/squid3/squid.conf')

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.binder.setup(self.config.tree).populate()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
Example #17
0
class Netatalk (SectionPlugin):
    config_path = '/etc/afp.conf'

    def init(self):
        self.title = 'Netatalk'
        self.icon = 'folder-close'
        self.category = _('Software')
        self.append(self.ui.inflate('netatalk:main'))

        if not os.path.exists(self.config_path):
            open(self.config_path, 'w').close()

        self.binder = Binder(None, self.find('config'))
        self.find('shares').new_item = lambda c: ShareData()
        self.config = NetatalkConfig(path=self.config_path)

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
Example #18
0
class NetworkPlugin(SectionPlugin):
    platforms = ["debian", "centos"]

    def init(self):
        self.title = _("Network")
        self.icon = "globe"
        self.category = _("System")
        self.net_config = INetworkConfig.get()

        self.append(self.ui.inflate("network:main"))

        def post_interface_bind(o, c, i, u):
            i.add_bits(self.ui)
            for bit in i.bits:
                u.find("bits").append(self.ui.create("tab", children=[bit], title=bit.title))
            u.find("up").on("click", self.on_up, i)
            u.find("down").on("click", self.on_down, i)
            u.find("restart").on("click", self.on_restart, i)

        def post_interface_update(o, c, i, u):
            for bit in i.bits:
                bit.apply()

        self.find("interfaces").post_item_bind = post_interface_bind
        self.find("interfaces").post_item_update = post_interface_update

        self.binder = Binder(self.net_config, self)

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.net_config.rescan()

        sensor = Sensor.find("traffic")
        for i in self.net_config.interface_list:
            i.tx, i.rx = sensor.value(i.name)

        self.binder.reset().autodiscover().populate()
        return

    def on_up(self, iface=None):
        self.net_config.up(iface)
        self.refresh()

    def on_down(self, iface=None):
        self.net_config.down(iface)
        self.refresh()

    def on_restart(self, iface=None):
        self.on_down(iface)
        self.on_up(iface)

    @on("save", "click")
    def on_save(self):
        self.binder.update()
        self.net_config.save()
        self.refresh()
        self.context.notify("info", _("Saved"))
Example #19
0
class TaskManager (SectionPlugin):
    def init(self):
        self.title = _('Processes')
        self.icon = 'th-list'
        self.category = _('System')
        self.append(self.ui.inflate('taskmgr:main'))

        def post_item_bind(object, collection, item, ui):
            ui.find('term').on('click', self.on_term, item)
            ui.find('kill').on('click', self.on_kill, item)

        self.find('processes').post_item_bind = post_item_bind

        self.binder = Binder(None, self)
        self.sorting = '_cpu'
        self.sorting_reverse = True

        for x in ['_cpu', 'pid', '_sort_ram', '_sort_name']:
            self.find('sort-by-' + x).on('click', self.sort, x)

    def on_page_load(self):
        self.refresh()

    def sort(self, by):
        if self.sorting == by:
            self.sorting_reverse = not self.sorting_reverse
        else:
            self.sorting_reverse = by in ['_cpu', '_ram']
        self.sorting = by
        self.refresh()

    def refresh(self):
        self.processes = list(psutil.process_iter())
        for p in self.processes:
            try:
                p._name = p.name
                p._cmd = ' '.join(p.cmdline)
                p._cpu = p.get_cpu_percent(interval=0)
                p._ram = '%i K' % int(p.get_memory_info()[0] / 1024)
                p._ppid = p.ppid
                p._sort_ram = p.get_memory_info()[0]
                p._sort_name = p.name.lower()
                try:
                    p._username = p.username
                except:
                    p._username = '******'
            except psutil.NoSuchProcess:
                self.processes.remove(p)

        self.processes = sorted(self.processes, key=lambda x: getattr(x, self.sorting), reverse=self.sorting_reverse)
        self.binder.setup(self).populate()

    def on_term(self, p):
        os.kill(p.pid, 15)
        self.refresh()

    def on_kill(self, p):
        os.kill(p.pid, 9)
        self.refresh()
Example #20
0
class WebserverPlugin (SectionPlugin):
    service_name = ''
    service_buttons = []
    hosts_available_dir = ''
    hosts_enabled_dir = ''
    template = ''
    supports_host_activation = True

    def init(self):
        self.append(self.ui.inflate('webserver_common:main'))
        self.binder = Binder(None, self)
        self.find_type('servicebar').buttons = self.service_buttons
        self.hosts_dir = AvailabilitySymlinks(
            self.hosts_available_dir, 
            self.hosts_enabled_dir,
            self.supports_host_activation
        )

        def delete_host(host, c):
            c.remove(host)
            self.hosts_dir.delete(host.name)

        def on_host_bind(o, c, host, u):
            host.__old_name = host.name

        def on_host_update(o, c, host, u):
            if host.__old_name != host.name:
                self.hosts_dir.rename(host.__old_name, host.name)
            host.save()

        def new_host(c):
            name = 'untitled'
            while os.path.exists(self.hosts_dir.get_path(name)):
                name += '_'
            self.hosts_dir.open(name, 'w').write(self.template)
            return WebserverHost(self, self.hosts_dir, name)

        self.find('hosts').delete_item = delete_host
        self.find('hosts').new_item = new_host
        self.find('hosts').post_item_bind = on_host_bind
        self.find('hosts').post_item_update = on_host_update
        self.find('header-active-checkbox').visible = \
            self.find('body-active-line').visible = \
                self.supports_host_activation

    def on_page_load(self):
        self.refresh()

    @on('save-button', 'click')
    def save(self):
        self.binder.update()
        self.refresh()
        self.context.notify('info', 'Saved')

    def refresh(self):
        self.hosts = [WebserverHost(self, self.hosts_dir, x) for x in self.hosts_dir.list_available()]
        self.binder.reset(self).autodiscover().populate()
        self.find_type('servicebar').reload()
Example #21
0
class BIND9Plugin (SectionPlugin):
    def init(self):
        self.title = 'BIND9'
        self.icon = 'globe'
        self.category = _('Software')

        self.append(self.ui.inflate('bind9:main'))

        self.config = BIND9Config(path='/etc/bind/named.conf')
        self.binder = Binder(None, self)
        self.find('zones').new_item = lambda c: ZoneData()

        def post_zone_bind(o, c, i, u):
            path = i.file
            if not path.startswith('/'):
                path = '/etc/bind/' + path
            exists = os.path.exists(path)
            u.find('no-file').visible = not exists
            u.find('file').visible = exists
            if exists:
                u.find('editor').value = open(path).read()

            def on_save_zone():
                open(path, 'w').write(u.find('editor').value)
                self.context.notify('info', _('Zone saved'))

            def on_create_zone():
                open(path, 'w').write("""$TTL    604800
@       IN      SOA     ns. root.ns. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@                   IN      NS      ns.
example.com.        IN      A       127.0.0.1
example.com.        IN      AAAA    ::1
""")
                post_zone_bind(o, c, i, u)

            u.find('save-zone').on('click', on_save_zone)
            u.find('create-zone').on('click', on_create_zone)
        self.find('zones').post_item_bind = post_zone_bind

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
Example #22
0
    def init(self):
        self.title = _('Configure')
        self.icon = 'wrench'
        self.category = ''
        self.order = 50

        self.append(self.ui.inflate('configurator:main'))

        self.binder = Binder(ajenti.config.tree, self.find('ajenti-config'))

        self.ccmgr = ClassConfigManager.get()
        self.classconfig_binding = Binder(self.ccmgr, self.find('classconfigs'))

        def post_classconfig_bind(object, collection, item, ui):
            def configure():
                self.configure_plugin(item, notify=False)

            ui.find('configure').on('click', configure)

        self.find('classconfigs').find('classes').post_item_bind = post_classconfig_bind

        self.find('users').new_item = lambda c: UserData()

        def post_user_bind(object, collection, item, ui):
            provider = UserManager.get(manager.context).get_sync_provider()
            editable = item.name != 'root'
            renameable = editable and provider.allows_renaming
            deletable = renameable

            ui.find('name-edit').visible = renameable 
            ui.find('name-label').visible = not renameable 
            ui.find('delete').visible = deletable
            
            box = ui.find('permissions')
            box.empty()

            p = PermissionProvider.get_all()
            for prov in p:
                line = self.ui.create('tab', title=prov.get_name())
                box.append(line)
                for perm in prov.get_permissions():
                    line.append(
                        self.ui.create('checkbox', id=perm[0], text=perm[1], value=(perm[0] in item.permissions))
                    )
        self.find('users').post_item_bind = post_user_bind

        def post_user_update(object, collection, item, ui):
            box = ui.find('permissions')
            for prov in PermissionProvider.get_all():
                for perm in prov.get_permissions():
                    has = box.find(perm[0]).value
                    if has and not perm[0] in item.permissions:
                        item.permissions.append(perm[0])
                    if not has and perm[0] in item.permissions:
                        item.permissions.remove(perm[0])
            if ui.find('password').value:
                item.password = ui.find('password').value
        self.find('users').post_item_update = post_user_update
Example #23
0
class NetworkPlugin (SectionPlugin):
    platforms = ['debian', 'centos']

    def init(self):
        self.title = _('Network')
        self.icon = 'globe'
        self.category = _('System')
        self.net_config = INetworkConfig.get()

        self.append(self.ui.inflate('network:main'))

        def post_interface_bind(o, c, i, u):
            i.add_bits(self.ui)
            for bit in i.bits:
                u.find('bits').append(self.ui.create(
                    'tab',
                    children=[bit],
                    title=bit.title,
                ))
            u.find('up').on('click', self.on_up, i)
            u.find('down').on('click', self.on_down, i)

        def post_interface_update(o, c, i, u):
            for bit in i.bits:
                bit.apply()

        self.find('interfaces').post_item_bind = post_interface_bind
        self.find('interfaces').post_item_update = post_interface_update

        self.binder = Binder(self.net_config, self)

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.net_config.rescan()

        sensor = Sensor.find('traffic')
        for i in self.net_config.interface_list:
            i.tx, i.rx = sensor.value(i.name)

        self.binder.reset().autodiscover().populate()
        return

    def on_up(self, iface=None):
        self.net_config.up(iface)
        self.refresh()

    def on_down(self, iface=None):
        self.net_config.down(iface)
        self.refresh()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.net_config.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
Example #24
0
class MySQLExtension (BaseExtension):
    default_config = {
        'created': False,
        'name': None,
        'user': None,
        'password': None,
    }
    name = 'MySQL'

    def init(self):
        self.append(self.ui.inflate('vh-mysql:ext'))
        self.binder = Binder(self, self)
        self.refresh()
        self.db = MySQLDB.get()

    @staticmethod
    def selftest():
        try:
            MySQLDB.get().query_databases()
        except:
            pass

    def refresh(self):
        self.binder.setup().populate()
        self.find('db-name').value = self.website.slug
        
    def update(self):
        self.binder.update()

    def on_destroy(self):
        if self.config['created']:
            self.on_delete()

    @on('create', 'click')
    def on_create(self):
        try:
            self.db.query_databases()
        except Exception, e:
            self.context.notify('error', str(e))
            self.context.launch('configure-plugin', plugin=self.db)
            return

        dbname = self.find('db-name').value
        for db in self.db.query_databases():
            if db.name == dbname:
                self.context.notify('error', 'This DB name is already used')
                return
        
        self.config['username'] = self.website.slug
        self.config['password'] = str(uuid.uuid4())
        self.config['name'] = dbname
        
        try:
            self.db.query_create(self.config['name'])
        except Exception, e:
            self.context.notify('error', str(e))
            return
Example #25
0
class SNMPDPlugin (SectionPlugin):
    service_name = platform_select(
        default='snmpd',
    )

    def init(self):
        self.title = 'SNMP'
        self.icon = 'exchange'
        self.category = _('Software')

        self.append(self.ui.inflate('snmpd:main'))

        self.find('servicebar').name = self.service_name
        self.find('servicebar').reload()

        self.snmp_config = SNMPConfig(path=platform_select(
            default='/etc/snmp/snmp.conf',
        ))

        self.binder = Binder(None, self)

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.snmp_config.load()
        enabled_mibs = []
        for mib in self.snmp_config.tree.mibs:
            for x in mib.name.strip('-+:').split(':'):
                enabled_mibs.append(x)
        self.mibs = []
        for dirpath, dirname, filenames in os.walk('/usr/share/mibs', followlinks=True):
            for x in filenames:
                if not x.startswith('.'):
                    mib = MIBData()
                    mib.name = x
                    mib.selected = x in enabled_mibs
                    self.mibs.append(mib)
        self.mibs = sorted(self.mibs, key=lambda x: x.name)
        self.binder.setup(self).populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        
        mib = MIBData()
        mib.name = ':'.join([x.name for x in self.mibs if x.selected])
        for x in list(self.snmp_config.tree.mibs):
            self.snmp_config.tree.mibs.remove(x)
        self.snmp_config.tree.mibs.append(mib)

        self.snmp_config.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
        ServiceMultiplexor.get().get_one(self.service_name).restart()
Example #26
0
class Cron(SectionPlugin):
    def init(self):
        self.title = "Cron"
        self.icon = "time"
        self.category = _("System")
        self.append(self.ui.inflate("cron:main"))

        def create_task(cls):
            logging.info("[cron] created a %s" % cls.__name__)
            return cls()

        def remove_task(i, c):
            c.remove(i)
            logging.info("[cron] removed %s" % getattr(i, "command", None))

        self.binder = Binder(None, self.find("config"))
        self.find("normal_tasks").new_item = lambda c: create_task(CrontabNormalTaskData)
        self.find("special_tasks").new_item = lambda c: create_task(CrontabSpecialTaskData)
        self.find("env_settings").new_item = lambda c: create_task(CrontabEnvSettingData)
        self.find("normal_tasks").delete_item = remove_task
        self.find("special_tasks").delete_item = remove_task
        self.find("env_settings").delete_item = remove_task

        self.current_user = "******"

    def on_page_load(self):
        self.refresh()

    @on("user-select", "click")
    def on_user_select(self):
        self.current_user = self.find("users").value
        logging.info("[cron] selected user %s" % self.current_user)
        self.refresh()

    def refresh(self):
        users_select = self.find("users")
        users_select.value = self.current_user
        users = [
            x.name for x in PasswdConfig(path="/etc/passwd").load().tree.users if int(x.uid) >= 500 or x.name == "root"
        ]
        users_select.values = users_select.labels = users

        self.config = CronManager.get().load_tab(self.current_user)
        self.binder.setup(self.config.tree).populate()

    @on("save", "click")
    def on_save(self):
        self.binder.update()
        logging.info("[cron] edited tasks")
        try:
            CronManager.get().save_tab(self.current_user, self.config)
            self.refresh()
        except Exception, e:
            self.context.notify("error", e.message)
Example #27
0
class Filesystems (SectionPlugin):
    def init(self):
        self.title = _('Filesystems')
        self.icon = 'hdd'
        self.category = _('System')
        self.append(self.ui.inflate('fstab:main'))

        self.find('type').labels = ['Auto', 'EXT2', 'EXT3', 'EXT4', 'NTFS', 'FAT', 'ZFS', 'ReiserFS', 'Samba', 'None', 'Loop']
        self.find('type').values = ['auto', 'ext2', 'ext3', 'ext4', 'ntfs', 'vfat', 'zfs', 'reiser',  'smb',   'none', 'loop']

        self.fstab_config = FSTabConfig(path='/etc/fstab')
        self.mounts = MountsBackend.get()

        self.binder = Binder(None, self)
        self.find('fstab').find('filesystems').new_item = lambda c: FilesystemData()

        def post_mount_bind(object, collection, item, ui):
            ui.find('umount').on('click', self.on_umount, item)

        self.find('mounts').find('filesystems').post_item_bind = post_mount_bind

    def on_page_load(self):
        self.refresh()

    def on_umount(self, mount):
        subprocess.call(['umount', mount.mountpoint])
        self.context.notify('info', _('Unmounted'))
        self.refresh()

    @on('mount-all', 'click')
    def on_mount_all(self):
        self.save()
        if subprocess.call(['mount', '-a']):
            self.context.notify('error', _('mount -a failed'))
        self.refresh()

    @on('refresh', 'click')
    def refresh(self):
        self.reload_disks()
        self.fstab_config.load()
        self.fstab = self.fstab_config.tree
        self.mounts.reload()
        self.binder.reset(self).autodiscover().populate()

    def reload_disks(self):
        lst = disks.list_devices(by_uuid=True, by_id=True, by_label=True)
        self.find('device').labels = [x[0] for x in lst]
        self.find('device').values = [x[1] for x in lst]

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.fstab_config.save()
        self.context.notify('info', _('Saved'))
Example #28
0
class Cron (SectionPlugin):
    def init(self):
        self.title = 'Cron'
        self.icon = 'time'
        self.category = _('System')
        self.append(self.ui.inflate('cron:main'))

        def create_task(cls):
            logging.info('[cron] created a %s' % cls.__name__)
            return cls()

        def remove_task(i, c):
            c.remove(i)
            logging.info('[cron] removed %s' % getattr(i, 'command', None))

        self.binder = Binder(None, self.find('config'))
        self.find('normal_tasks').new_item = lambda c: create_task(CrontabNormalTaskData)
        self.find('special_tasks').new_item = lambda c: create_task(CrontabSpecialTaskData)
        self.find('env_settings').new_item = lambda c: create_task(CrontabEnvSettingData)
        self.find('normal_tasks').delete_item = remove_task
        self.find('special_tasks').delete_item = remove_task
        self.find('env_settings').delete_item = remove_task

        self.current_user = '******'

    def on_page_load(self):
        self.refresh()

    @on('user-select', 'click')
    def on_user_select(self):
        self.current_user = self.find('users').value
        logging.info('[cron] selected user %s' % self.current_user)
        self.refresh()

    def refresh(self):
        users_select = self.find('users')
        users_select.value = self.current_user
        users = [x.name for x in PasswdConfig(path='/etc/passwd').load().tree.users]
        users_select.values = users_select.labels = users

        self.config = CronManager.get().load_tab(self.current_user)
        self.binder.setup(self.config.tree).populate()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        logging.info('[cron] edited tasks')
        try:
            CronManager.get().save_tab(self.current_user, self.config)
            self.refresh()
        except Exception as e:
            self.context.notify('error', e.message)
Example #29
0
class LinuxBasicNetworkConfigSet (NetworkConfigBit):
    cls = 'linux-basic'
    title = 'Basic'

    def init(self):
        self.append(self.ui.inflate('network:bit-linux-basic'))
        self.binder = Binder(self.iface, self)

    def refresh(self):
        self.binder.reset(self.iface).autodiscover().populate()

    def apply(self):
        self.binder.update()
Example #30
0
class LinuxDHCPNetworkConfigSet (NetworkConfigBit):
    cls = 'linux-dhcp'
    title = 'DHCP'

    def init(self):
        self.append(self.ui.inflate('network:bit-linux-dhcp'))
        self.binder = Binder(None, self)

    def refresh(self):
        self.binder.setup(self.iface).populate()

    def apply(self):
        self.binder.update()
Example #31
0
class BIND9Plugin (SectionPlugin):
    config_root = platform_select(
        debian='/etc/bind/',
        centos='/etc/named/',
    )
    
    config_path = platform_select(
        debian='/etc/bind/named.conf',
        centos='/etc/named.conf',
    )

    def init(self):
        self.title = 'BIND9'
        self.icon = 'globe'
        self.category = _('Software')

        self.append(self.ui.inflate('bind9:main'))

        self.config = BIND9Config(path=self.config_path)
        self.binder = Binder(None, self)
        self.find('zones').new_item = lambda c: ZoneData()

        def post_zone_bind(o, c, i, u):
            path = i.file
            if not path.startswith('/'):
                path = self.config_root + path
            exists = os.path.exists(path)
            u.find('no-file').visible = not exists
            u.find('file').visible = exists
            if exists:
                u.find('editor').value = open(path).read()

            def on_save_zone():
                open(path, 'w').write(u.find('editor').value)
                self.context.notify('info', _('Zone saved'))

            def on_create_zone():
                open(path, 'w').write("""$TTL    604800
@       IN      SOA     ns. root.ns. (
                              1         ; Serial
                         604800         ; Refresh
                          86400         ; Retry
                        2419200         ; Expire
                         604800 )       ; Negative Cache TTL
;
@                   IN      NS      ns.
example.com.        IN      A       127.0.0.1
example.com.        IN      AAAA    ::1
""")
                post_zone_bind(o, c, i, u)

            u.find('save-zone').on('click', on_save_zone)
            u.find('create-zone').on('click', on_create_zone)
        self.find('zones').post_item_bind = post_zone_bind

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.binder.reset(self.config.tree).autodiscover().populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
Example #32
0
class CSFSection (SectionPlugin):
    def init(self):
        self.title = _('CSF Firewall')
        self.icon = 'fire'
        self.category = _('System')
        self.backend = CSFBackend.get()

        self.append(self.ui.inflate('csf:main'))

        self.config = CSFConfig(path='/etc/csf/csf.conf')
        self.list_allow = []
        self.list_deny = []
        self.list_tempallow = []
        self.list_tempban = []

        def delete_rule(csf_option, i):
            self.save()
            subprocess.call(['csf', csf_option, i.value.split('#')[0]])
            self.refresh()

        self.find('list_allow').on_delete = lambda i, c: delete('-ar', i)
        self.find('list_deny').on_delete = lambda i, c: delete('-dr', i)
        self.find('list_tempallow').on_delete = lambda i, c: delete('-tr', i)
        self.find('list_tempban').on_delete = lambda i, c: delete('-tr', i)

        def add_rule(csf_option, address):
            self.save()
            p = subprocess.Popen(['csf', csf_option, address], stdout=subprocess.PIPE)
            o, e = p.communicate()
            self.context.notify('info', o)
            self.refresh()

        self.find('list_allow-add').on('click', lambda: add_rule('-a', self.find('permanent-lists-add-address').value))
        self.find('list_deny-add').on('click', lambda: add_rule('-d', self.find('permanent-lists-add-address').value))
        self.find('list_tempallow-add').on('click', lambda: add_rule('-ta', self.find('temporary-lists-add-address').value))
        self.find('list_tempban-add').on('click', lambda: add_rule('-td', self.find('temporary-lists-add-address').value))

        self.binder = Binder(None, self)
        self.binder_lists = Binder(self, self.find('lists'))

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.list_allow = self.backend.read_list('allow')
        self.list_deny = self.backend.read_list('deny')
        self.list_tempallow = self.backend.read_list('tempallow')
        self.list_tempban = self.backend.read_list('tempban')
        self.binder.setup(self.config.tree).populate()
        self.binder_lists.populate()

    @on('apply', 'click')
    def on_apply(self):
        self.backend.apply()
        self.context.notify('info', _('Applied'))

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
        self.backend.write_list('allow', self.list_allow)
        self.backend.write_list('deny', self.list_deny)
        self.backend.write_list('tempallow', self.list_tempallow)
        self.backend.write_list('tempban', self.list_tempban)

        self.binder.setup(self.config.tree).populate()
        self.context.notify('info', _('Saved'))
        try:
            self.backend.test_config()
            self.context.notify('info', _('Self-test OK'))
        except Exception, e:
            self.context.notify('error', str(e))
Example #33
0
class Filesystems(SectionPlugin):
    def init(self):
        self.title = _('Filesystems')
        self.icon = 'hdd'
        self.category = _('System')
        self.append(self.ui.inflate('fstab:main'))

        self.find('type').labels = [
            'Auto', 'EXT2', 'EXT3', 'EXT4', 'NTFS', 'FAT', 'ZFS', 'ReiserFS',
            'Samba', 'None', 'Loop'
        ]
        self.find('type').values = [
            'auto', 'ext2', 'ext3', 'ext4', 'ntfs', 'vfat', 'zfs', 'reiser',
            'smb', 'none', 'loop'
        ]

        self.fstab_config = FSTabConfig(path='/etc/fstab')
        self.mounts = MountsBackend.get()

        self.binder = Binder(None, self)
        self.find('fstab').find(
            'filesystems').new_item = lambda c: FilesystemData()

        def post_mount_bind(object, collection, item, ui):
            ui.find('umount').on('click', self.on_umount, item)

        self.find('mounts').find(
            'filesystems').post_item_bind = post_mount_bind

    def on_page_load(self):
        self.refresh()

    def on_umount(self, mount):
        subprocess.call(['umount', mount.mountpoint])
        self.context.notify('info', _('Unmounted'))
        self.refresh()

    @on('mount-all', 'click')
    def on_mount_all(self):
        self.save()
        if subprocess.call(['mount', '-a']):
            self.context.notify('error', _('mount -a failed'))
        self.refresh()

    @on('refresh', 'click')
    def refresh(self):
        self.binder.unpopulate()
        self.reload_disks()
        self.fstab_config.load()
        self.fstab = self.fstab_config.tree
        self.mounts.reload()
        self.binder.setup(self).populate()

    def reload_disks(self):
        lst = disks.list_devices(by_uuid=True, by_id=True, by_label=True)
        self.find('device').labels = [x[0] for x in lst]
        self.find('device').values = [x[1] for x in lst]

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.fstab_config.save()
        self.context.notify('info', _('Saved'))
Example #34
0
class SanickioskScreensaverPrefs(SectionPlugin):
    default_classconfig = {
        'enable_browser': False,
        'home_url': 'http://*****:*****@on('save', 'click')
    def save(self):
        self.binder.update()
        self.save_classconfig()
        self.context.notify(
            'info',
            _('Настройките са запаметени. Моля, рестартирайте киоска.'))
        self.binder.populate()

        #all_vars = '\n'.join([k + '="' + str(v) + '"' for k,v in self.classconfig.iteritems()])
        for k, v in self.classconfig.iteritems():
            if k == 'enable_browser':
                enable_browser = "X-GNOME-Autostart-enabled=%s" % str(
                    v).lower()
            if k == 'home_url':
                home_url = v.lower()

        if enable_browser == "X-GNOME-Autostart-enabled=true":
            ajenti_config = "/etc/ajenti/config.json"

            #Disable Video Mode
            subprocess.call([
                'sed', '-i',
                r's/\\"enable_videos\\": true/\\"enable_videos\\": false/g',
                ajenti_config
            ])
            subprocess.call([
                'sed', '-i',
                r's/X-GNOME-Autostart-enabled=true/X-GNOME-Autostart-enabled=false/g',
                "/home/kiosk/.config/autostart/2-videos.desktop"
            ])

            #Disable Photo Mode
            subprocess.call([
                'sed', '-i',
                r's/\\"photos_enable\\": true/\\"photos_enable\\": false/g',
                ajenti_config
            ])
            subprocess.call([
                'sed', '-i',
                r's/X-GNOME-Autostart-enabled=true/X-GNOME-Autostart-enabled=false/g',
                "/home/kiosk/.config/autostart/2-photos.desktop"
            ])

        cfg = (
            "[Desktop Entry]\n"
            "Type=Application\n"
            "Exec=chromium-browser --kiosk --no-first-run --disable-infobars --disable-session-crashed-bubble %s\n"
            "Hidden=false\n"
            "NoDisplay=false\n"
            "%s\n"
            "Name[en_US]=2-browser\n"
            "Name=2-browser\n"
            "Comment[en_US]=\n"
            "Comment=") % (home_url, enable_browser)

        open('/home/kiosk/.config/autostart/2-browser.desktop',
             'w').write(cfg)  #save
Example #35
0
File: fm.py Project: xuemy/ajenti
 def edit(self, path):
     self.find('dialog').visible = True
     self.item = Item(path)
     self.item.read()
     self.binder_d = Binder(self.item,
                            self.find('dialog')).autodiscover().populate()
Example #36
0
class Firewall(SectionPlugin):
    platforms = ['centos', 'debian']

    def init(self):
        self.title = _('Firewall')
        self.icon = 'fire'
        self.category = _('System')

        self.append(self.ui.inflate('iptables:main'))

        self.fw_mgr = FirewallManager.get()
        self.config = IPTablesConfig(path=self.fw_mgr.config_path_ajenti)
        self.binder = Binder(None, self.find('config'))

        self.find('tables').new_item = lambda c: TableData()
        self.find('chains').new_item = lambda c: ChainData()
        self.find('rules').new_item = lambda c: RuleData()
        self.find('options').new_item = lambda c: OptionData()
        self.find('options').binding = OptionsBinding
        self.find('options').filter = lambda i: not i.name in ['j', 'jump']

        def post_rule_bind(o, c, i, u):
            u.find('add-option').on('change', self.on_add_option, c, i, u)
            action = ''
            j_option = i.get_option('j', 'jump')
            if j_option:
                action = j_option.arguments[0].value
            u.find('action').text = action
            u.find('action').style = 'iptables-action iptables-%s' % action
            u.find('action-select').value = action
            u.find('title').text = i.comment if i.comment else i.summary

        def post_rule_update(o, c, i, u):
            action = u.find('action-select').value
            j_option = i.get_option('j', 'jump')
            if j_option:
                j_option.arguments[0].value = action
            else:
                if action:
                    o = OptionData.create_destination()
                    o.arguments[0].value = action
                    i.options.append(o)

        self.find('rules').post_item_bind = post_rule_bind
        self.find('rules').post_item_update = post_rule_update

        self.find('add-option').values = self.find('add-option').labels = [
            _('Add option')
        ] + sorted(OptionData.templates.keys())

    def on_page_load(self):
        if not os.path.exists(self.fw_mgr.config_path_ajenti):
            if not os.path.exists(self.fw_mgr.config_path):
                open(self.fw_mgr.config_path, 'w').write("""
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

                """)
            open(self.fw_mgr.config_path_ajenti,
                 'w').write(open(self.fw_mgr.config_path).read())
        self.config.load()
        self.refresh()

    @on('load-current', 'click')
    def on_load_current(self):
        subprocess.call('iptables-save > %s' % self.fw_mgr.config_path,
                        shell=True)
        self.config.load()
        self.refresh()

    def refresh(self):
        self.find('autostart').text = (_('Disable')
                                       if self.fw_mgr.get_autostart_state()
                                       else _('Enable')) + _(' autostart')

        actions = ['ACCEPT', 'DROP', 'REJECT', 'LOG', 'MASQUERADE', 'DNAT', 'SNAT'] + \
            list(set(itertools.chain.from_iterable([[c.name for c in t.chains] for t in self.config.tree.tables])))
        self.find('action-select').labels = actions
        self.find('action-select').values = actions
        self.find('chain-action-select').labels = actions
        self.find('chain-action-select').values = actions
        self.binder.setup(self.config.tree).populate()

    @on('autostart', 'click')
    def on_autostart_change(self):
        self.fw_mgr.set_autostart_state(not self.fw_mgr.get_autostart_state())
        self.refresh()

    def on_add_option(self, options, rule, ui):
        o = OptionData.create(ui.find('add-option').value)
        ui.find('add-option').value = ''
        rule.options.append(o)
        self.binder.populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()

        for t in self.config.tree.tables:
            for c in t.chains:
                for r in c.rules:
                    r.verify()

        self.config.save()

        open(self.fw_mgr.config_path, 'w').write(''.join(
            l.split('#')[0] + '\n'
            for l in open(self.fw_mgr.config_path_ajenti).read().splitlines()))
        self.refresh()
        self.context.notify('info', _('Saved'))

    @on('edit', 'click')
    def raw_edit(self):
        self.context.launch('notepad', path=self.fw_mgr.config_path_ajenti)

    @on('apply', 'click')
    def apply(self):
        self.save()
        cmd = 'cat %s | iptables-restore' % self.fw_mgr.config_path
        if subprocess.call(cmd, shell=True) != 0:
            self.context.launch('terminal', command=cmd)
        else:
            self.context.notify('info', _('Applied successfully'))
Example #37
0
class Users(SectionPlugin):
    def init(self):
        self.title = _('Users')
        self.icon = 'group'
        self.category = _('System')
        self.append(self.ui.inflate('users:main'))

        def _filterOnlyUsers(x):
            u = int(x.uid)
            return u >= 500

        def _filterOnlySystemUsers(x):
            u = int(x.uid)
            return u < 500

        def _sorter(x):
            g = int(x.gid)
            if g >= 500:
                return g - 10000
            return g

        self.find('users').filter = _filterOnlyUsers
        self.find('system-users').filter = _filterOnlySystemUsers
        self.find('groups').sorting = _sorter

        self.config = PasswdConfig(path='/etc/passwd')
        self.config_g = GroupConfig(path='/etc/group')
        self.binder = Binder(None, self.find('passwd-config'))
        self.binder_system = Binder(None, self.find('passwd-config-system'))
        self.binder_g = Binder(None, self.find('group-config'))

        self.mgr = UsersBackend.get()

        def post_item_bind(object, collection, item, ui):
            ui.find('change-password').on('click', self.change_password, item,
                                          ui)
            ui.find('remove-password').on('click', self.remove_password, item)
            if not os.path.exists(item.home):
                ui.find('create-home-dir').on('click', self.create_home_dir,
                                              item, ui)
                ui.find('create-home-dir').visible = True

        self.find('users').post_item_bind = post_item_bind
        self.find('system-users').post_item_bind = post_item_bind

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.config_g.load()

        self.binder.setup(self.config.tree).populate()
        self.binder_system.setup(self.config.tree).populate()

        self.binder_g.setup(self.config_g.tree)
        self.find('group-members').labels = self.find(
            'group-members').values = [x.name for x in self.config.tree.users]
        self.binder_g.populate()

    @on('add-user', 'click')
    def on_add_user(self):
        self.find('input-username').visible = True

    @on('input-username', 'submit')
    def on_add_user_done(self, value):
        self.mgr.add_user(value)
        self.refresh()

    @on('add-group', 'click')
    def on_add_group(self):
        self.find('input-groupname').visible = True

    @on('input-groupname', 'submit')
    def on_add_group_done(self, value):
        self.mgr.add_group(value)
        self.refresh()

    @on('save-users', 'click')
    def save_users(self):
        self.binder.update()
        self.config.save()

    @on('save-system-users', 'click')
    def save_system_users(self):
        self.binder_system.update()
        self.config.save()

    @on('save-groups', 'click')
    def save_groups(self):
        self.binder_g.update()
        self.config_g.save()

    def create_home_dir(self, user, ui):
        self.mgr.make_home_dir(user)
        self.context.notify('info',
                            _('Home dir for %s was created') % user.name)
        ui.find('create-home-dir').visible = False

    def change_password(self, user, ui):
        new_password = ui.find('new-password').value

        if new_password:
            try:
                self.mgr.change_password(user, new_password)
                self.context.notify(
                    'info',
                    _('Password for %s was changed') % user.name)
                ui.find('new-password').value = ''
            except Exception, e:
                self.context.notify('error', _('Error: "%s"') % e.message)
        else:
Example #38
0
class MailPlugin (SectionPlugin):
    def init(self):
        self.title = _('Mail')
        self.icon = 'envelope'
        self.category = 'Web'

        self.manager = MailManager.get()

        if not self.manager.is_configured:
            self.append(self.ui.inflate('vh-mail:not-configured'))
        else:
            self.post_init()

    @on('initial-enable', 'click')
    def on_initial_enable(self):
        self.post_init()
        self.manager.save()
        self.refresh()

    def post_init(self):
        self.empty()
        self.append(self.ui.inflate('vh-mail:main'))

        self.binder = Binder(None, self)

        def post_mb_bind(object, collection, item, ui):
            ui.find('size').text = str_fsize(self.manager.get_usage(item))

        def post_mb_update(object, collection, item, ui):
            if ui.find('password').value:
                item.password = ui.find('password').value

        self.find('mailboxes').post_item_bind = post_mb_bind
        self.find('mailboxes').post_item_update = post_mb_update
        self.find('mailboxes').filter = \
            lambda mb: self.context.session.identity in ['root', mb.owner]
        self.find('targets').new_item = lambda c: ForwardingTarget.create()

        self.binder.setup(self.manager.config)

    def _fetch_new_mailbox_name(self, cls):
        mb = cls.create()
        mb.local = self.find('new-mailbox-local').value
        mb.domain = self.find('new-mailbox-domain').value or \
            self.find('new-mailbox-domain-custom').value

        if not mb.local:
            self.context.notify('error', _('Invalid mailbox name'))
            return

        if not mb.domain:
            self.context.notify('error', _('Invalid mailbox domain'))
            return

        if cls == ForwardingMailbox:
            for existing in self.manager.config.forwarding_mailboxes:
                if existing.name == mb.name:
                    self.context.notify(
                        'error',
                        _('This address is already taken')
                    )
                    return
        else:
            for existing in self.manager.config.mailboxes:
                if existing.name == mb.name:
                    self.context.notify(
                        'error',
                        _('This address is already taken')
                    )
                    return

        self.find('new-mailbox-local').value = ''
        return mb

    @on('new-mailbox', 'click')
    def on_new_mailbox(self):
        self.binder.update()
        mb = self._fetch_new_mailbox_name(Mailbox)
        if not mb:
            return
        mb.owner = self.context.session.identity
        mb.password = ''
        self.manager.config.mailboxes.append(mb)
        self.manager.save()
        self.binder.populate()

    @on('new-forwarding-mailbox', 'click')
    def on_new_forwarding_mailbox(self):
        self.binder.update()
        mb = self._fetch_new_mailbox_name(ForwardingMailbox)
        if not mb:
            return
        mb.owner = self.context.session.identity
        self.manager.config.forwarding_mailboxes.append(mb)
        self.manager.save()
        self.binder.populate()

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        if not self.manager.is_configured:
            return

        domains = []
        for ws in VHManager.get().config.websites:
            if self.context.session.identity in ['root', ws.owner]:
                domains += [d.domain for d in ws.domains]
        domains = sorted(list(set(domains)))

        if self.find('new-mailbox-domain'):
            self.find('new-mailbox-domain').labels = \
                domains + [_('Custom domain')]
            self.find('new-mailbox-domain').values = domains + [None]

            if self.manager.is_configured:
                self.binder.unpopulate().populate()

        if os.path.exists(self.manager.config.dkim_private_key):
            pubkey = subprocess.check_output([
                'openssl', 'rsa', '-in', self.manager.config.dkim_private_key,
                '-pubout'
            ])
            pubkey = filter(None, pubkey.split('-'))[1].replace('\n', '')
            dns = '@\t\t\t\t10800 IN TXT "v=spf1 a -all"\n'
            dns += '_domainkey\t\t10800 IN TXT "o=~; r=postmaster@<domain>"\n'
            dns += '%s._domainkey\t10800 IN TXT "v=DKIM1; k=rsa; p=%s"\n' % (
                self.manager.config.dkim_selector,
                pubkey
            )
            dns += '_dmarc\t\t\t10800 IN TXT "v=DMARC1; p=quarantine"\n'

            self.find('dkim-domain-entry').value = dns
        else:
            self.find('dkim-domain-entry').value = _('No valid key exists')

    @on('generate-dkim-key', 'click')
    def on_generate_dkim_key(self):
        self.binder.update()
        self.manager.generate_dkim_key()
        self.binder.populate()
        self.save()

    @on('generate-tls-cert', 'click')
    def on_generate_tls_cert(self):
        self.binder.update()
        self.manager.generate_tls_cert()
        self.binder.populate()
        self.save()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.manager.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
Example #39
0
class Packages (SectionPlugin):
    platforms = ['debian', 'centos', 'freebsd', 'arch']
    def init(self):
        self.title = _('Packages')
        self.icon = 'gift'
        self.category = _('System')

        self.mgr = PackageManager.get()

        self.append(self.ui.inflate('packages:main'))

        def post_item_bind(object, collection, item, ui):
            ui.find('install').on('click', self.on_install, item)
            ui.find('remove').on('click', self.on_remove, item)
            ui.find('cancel').on('click', self.on_cancel, item)
            ui.find('install').visible = item.action is None
            ui.find('remove').visible = item.action is None and item.state == 'i'
            ui.find('cancel').visible = item.action is not None

        self.find('upgradeable').post_item_bind = post_item_bind
        self.find('search').post_item_bind = post_item_bind
        self.find('pending').post_item_bind = post_item_bind

        self.binder = Binder(None, self.find('bind-root'))
        self.binder_p = Binder(self, self.find('bind-pending'))
        self.binder_s = CollectionAutoBinding([], None, self.find('search')).populate()

        self.pending = {}
        self.installation_running = False
        self.action_queue = []

    def refresh(self):
        self.fill(self.mgr.upgradeable)
        self.binder.setup(self.mgr).populate()
        self.binder_s.unpopulate().populate()
        self._pending = self.pending.values()
        self.binder_p.setup(self).populate()

    def run(self, tasks):
        if self.installation_running:
            self.action_queue += tasks
            self.context.notify('info', _('Enqueueing package installation'))
            return

        self.installation_running = True

        def callback():
            self.installation_running = False
            if self.action_queue:
                self.run(self.action_queue)
                self.action_queue = []
                return
            self.context.notify('info', _('Installation complete!'))

        self.mgr.do(tasks, callback=callback)

    @intent('install-package')
    @restrict('packages:modify')
    def intent_install(self, package):
        p = PackageInfo()
        p.name, p.action = package, 'i'
        self.run([p])

    def on_page_load(self):
        self.context.endpoint.send_progress(_('Querying package manager'))
        self.mgr.refresh()
        self.refresh()

    @restrict('packages:modify')
    def on_install(self, package):
        package.action = 'i'
        self.pending[package.name] = package
        self.refresh()

    @restrict('packages:modify')
    def on_cancel(self, package):
        package.action = None
        if package.name in self.pending:
            del self.pending[package.name]
        self.refresh()

    @restrict('packages:modify')
    def on_remove(self, package):
        package.action = 'r'
        self.pending[package.name] = package
        self.refresh()

    @on('get-lists-button', 'click')
    @restrict('packages:refresh')
    def on_get_lists(self):
        self.mgr.get_lists()

    @on('apply-button', 'click')
    @restrict('packages:modify')
    def on_apply(self):
        self.run(self.pending.values())
        self.pending = {}
        self.refresh()

    @on('upgrade-all-button', 'click')
    @restrict('packages:modify')
    def on_upgrade_all(self):
        for p in self.mgr.upgradeable:
            p.action = 'i'
            self.pending[p.name] = p
        self.refresh()

    @on('cancel-all-button', 'click')
    @restrict('packages:modify')
    def on_cancel_all(self):
        self.pending = {}
        self.refresh()

    def fill(self, packages):
        for p in packages:
            if p.name in self.pending:
                p.action = self.pending[p.name].action

    @on('search-button', 'click')
    def on_search(self):
        query = self.find('search-box').value
        results = self.mgr.search(query)
        if self.binder_s:
            self.binder_s.unpopulate()
        if len(results) > 100:
            self.find('search-counter').text = _('%i found, 100 shown') % len(results)
            results = results[:100]
        else:
            self.find('search-counter').text = _('%i found') % len(results)

        self.fill(results)
        self.binder_s = CollectionAutoBinding(results, None, self.find('search')).populate()
Example #40
0
class DBPlugin(SectionPlugin):
    service_name = ''
    service_buttons = []
    has_users = True

    def init(self):
        self.append(self.ui.inflate('db_common:main'))
        self.binder = Binder(None, self)
        self.find_type('servicebar').buttons = self.service_buttons

        def delete_db(db, c):
            self.query_drop(db)
            self.refresh()

        self.find('databases').delete_item = delete_db

        def delete_user(user, c):
            self.query_drop_user(user)
            self.refresh()

        self.find('users').delete_item = delete_user

    def on_page_load(self):
        self.refresh()

    @on('sql-run', 'click')
    def on_sql_run(self):
        try:
            result = self.query_sql(
                self.find('sql-db').value,
                self.find('sql-input').value)
            self.context.notify('info', _('Query finished'))
        except Exception as e:
            self.context.notify('error', str(e))
            return

        tbl = self.find('sql-output')
        tbl.empty()

        if len(result) > 200:
            self.context.notify(
                'info',
                _('Output cut from %i rows to 200') % len(result))
            result = result[:200]

        for row in result:
            erow = self.ui.create('dtr')
            tbl.append(erow)
            for cell in row:
                ecell = self.ui.create('dtd')
                ecell.append(self.ui.create('label', text=str(cell)))
                erow.append(ecell)

    @on('add-db', 'click')
    def on_add_db(self):
        self.find('db-name-dialog').value = ''
        self.find('db-name-dialog').visible = True

    @on('add-user', 'click')
    def on_add_user(self):
        self.find('add-user-dialog').visible = True

    def refresh(self):
        self.databases = []
        self.users = []
        try:
            self.databases = self.query_databases()
            if self.has_users:
                self.users = self.query_users()
        except Exception as e:
            import traceback
            traceback.print_exc()
            self.context.notify('error', str(e))
            if hasattr(self, 'config_class'):
                self.context.launch('configure-plugin',
                                    plugin=self.config_class.get())
            return

        self.binder.unpopulate()
        self.find('sql-db').labels = self.find('sql-db').values = [
            x.name for x in self.databases
        ]
        self.binder.setup(self).populate()
        self.find_type('servicebar').reload()

    @on('db-name-dialog', 'submit')
    def on_db_name_dialog_submit(self, value=None):
        try:
            self.query_create(value)
        except Exception as e:
            self.context.notify('error', str(e))
            return
        self.refresh()

    @on('add-user-dialog', 'button')
    def on_add_user_dialog(self, button=None):
        d = self.find('add-user-dialog')
        d.visible = False
        if button == 'ok':
            u = User()
            u.name = d.find('name').value
            u.host = d.find('host').value
            u.password = d.find('password').value
            try:
                self.query_create_user(u)
            except Exception as e:
                self.context.notify('error', str(e))
                return

        self.refresh()

    def query_sql(self, db, sql):
        raise NotImplementedError()

    def query_databases(self):
        raise NotImplementedError()

    def query_drop(self, db):
        raise NotImplementedError()

    def query_create(self, name):
        raise NotImplementedError()

    def query_users(self):
        raise NotImplementedError()

    def query_create_user(self, user):
        raise NotImplementedError()

    def query_drop_user(self, user):
        raise NotImplementedError()
Example #41
0
class Samba(SectionPlugin):
    def init(self):
        self.title = 'Samba'
        self.icon = 'folder-close'
        self.category = _('Software')
        self.append(self.ui.inflate('samba:main'))

        self.find('servicebar').name = platform_select(
            debian='samba',
            ubuntu='smbd',
            centos='smb',
            default='samba',
        )
        self.find('servicebar').reload()

        self.binder = Binder(None, self.find('config'))
        self.find('shares').new_item = lambda c: ShareData()
        self.config = SambaConfig(path='/etc/samba/smb.conf')

        def post_item_bind(object, collection, item, ui):
            ui.find('disconnect').on('click', self.on_disconnect, item)

        self.find('connections').post_item_bind = post_item_bind

        def post_user_bind(object, collection, item, ui):
            def delete_user():
                self.usermgr.delete(item.username)
                self.refresh()

            ui.find('delete').on('click', delete_user)

            def set_password():
                if self.usermgr.set_password(item.username,
                                             ui.find('password').value):
                    self.context.notify('info', _('Password updated'))
                    ui.find('password').value = ''
                else:
                    self.context.notify('error', _('Password update failed'))

            ui.find('password-set').on('click', set_password)

        self.find('user-list').post_item_bind = post_user_bind

        self.usermgr = SambaUsers()
        self.binder_u = Binder(self.usermgr, self.find('users'))

        self.monitor = SambaMonitor()
        self.binder_m = Binder(self.monitor, self.find('status'))

    def on_page_load(self):
        self.refresh()

    def on_disconnect(self, connection):
        connection.disconnect()
        self.refresh()

    def refresh(self):
        self.config.load()
        self.monitor.refresh()
        self.usermgr.load()
        self.binder.setup(self.config.tree).populate()
        self.binder_m.setup(self.monitor).populate()
        self.binder_u.setup(self.usermgr).populate()

        users_dropdown = self.find('add-user-list')
        users = [
            x.name for x in PasswdConfig(path='/etc/passwd').load().tree.users
        ]
        for u in self.usermgr.users:
            if u.username in users:
                users.remove(u.username)
        users_dropdown.values = users_dropdown.labels = users

    @on('add-user', 'click')
    def on_add_user(self):
        self.usermgr.create(self.find('add-user-list').value)
        self.refresh()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
Example #42
0
class GitPlugin (SectionPlugin):
    def init(self):
        self.title = _('Git')
        self.icon = 'folder-close'
        self.category = 'Software'
        self.append(self.ui.inflate('git:main'))
        self.binder = Binder(None, self)
        self.user = None

        # Find User
        for user in ['gitolite3', 'gitolite2', 'gitolite']:
             try:
                 pwn = getpwnam(user)
                 self.user = pwn
                 break
             except:
                 pass

        if self.user == None:
            exit(-1)

        # Set Conf & Key Directory
        self.confdir = os.path.join(self.user.pw_dir, '.gitolite/conf/')
        self.keydir = os.path.join(self.user.pw_dir, '.gitolite/keydir/')

        # Event for new items
        self.find('usercollection').new_item = lambda c: User('newuser', '')
        self.find('repocollection').new_item = lambda c: Repository('newrepo')

        # Remove old Gitolite.conf and replace our version
        os.remove(self.confdir + 'gitolite.conf')
        with open((self.confdir + 'gitolite.conf'), 'w+') as file:
            file.write('include "*.conf"')

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.refresh_users()
        self.refresh_repositories()
        self.binder.setup(self).populate()

    def reload(self):
        subprocess.call('su -c "gitolite compile" ' + self.user.pw_name, shell=True)
        self.context.notify('info', _('Saved'))

    #
    # Repositories
    #
    def refresh_repositories(self):
        self.repositories = []

        userlist = []
        for user in self.users:
            userlist.append(user.name)
        self.find('rwusers').values = userlist
        self.find('rwusers').labels = userlist
        self.find('rousers').values = userlist
        self.find('rousers').labels = userlist

        for file in os.listdir(self.confdir):
            if os.path.isfile(self.confdir + file) and not 'gitolite.conf' in file:
                with open(self.confdir + file) as content:
                    content = content.read()
                    repo = Repository('')

                    # Repository Name
                    match = re.search(r'repo[\s]+([A-z0-9]+)', content, re.I)
                    repo.name = match.group(1)

                    #Repository Users(read-write)
                    match = re.search(r'RW\+[\s]+\=[\s]+([^\n]+)', content, re.I)
                    repo.rwusers = match is not None and match.group(1) or ''

                    #Repository Users(read-only)
                    match = re.search(r'R[\s]+\=[\s]+([^\n]+)', content, re.I)
                    repo.rousers = match is not None and match.group(1) or ''

                    self.repositories.append(repo)

    @on('save-repositories', 'click')
    def save_repositories(self):
        self.binder.update()

        files = []
        for file in os.listdir(self.confdir):
            if os.path.isfile(self.confdir + file) and not "gitolite.conf" in file:
                files.append(file)

        for repo in self.repositories:
            with open((self.confdir + repo.name + '.conf'), 'w+') as file:
                content = 'repo '
                content += repo.name
                content += '\n'

                rwusers = repo.rwusers.strip()
                if len(rwusers) > 0:
                    content += '\tRW+\t=\t' + rwusers + '\n'

                rousers = repo.rousers.strip()
                if len(rousers) > 0:
                    content += '\tR\t=\t' + rousers + '\n'

                file.write(content)

            if (repo.name + '.conf') in files:
                files.remove(repo.name + '.conf')

        for file in files:
            os.remove(self.confdir + file)

        self.reload()

    #
    # Users
    #
    def refresh_users(self):
        self.users = []

        for file in os.listdir(self.keydir):
            with open(self.keydir + file) as content:
                username = file.replace('.pub', '')
                pubkey = content.read()

                self.users.append(User(username, pubkey))

    @on('save-users', 'click')
    def save_users(self):
        self.binder.update()

        files = []
        for file in os.listdir(self.keydir):
            files.append(file)

        for user in self.users:
            with open((self.keydir + user.name + '.pub'), 'w+') as file:
                file.write(user.pubkey)
            if (user.name + '.pub') in files:
                files.remove(user.name + '.pub')

        for file in files:
            os.remove(self.keydir + file)

        self.reload();
Example #43
0
class FileManager (SectionPlugin):
    default_classconfig = {'root': '/', 'start': '/'}
    classconfig_editor = FileManagerConfigEditor
    classconfig_root = True

    def init(self):
        self.title = _('File Manager')
        self.category = _('Tools')
        self.icon = 'folder-open'

        self.backend = FMBackend().get()

        self.append(self.ui.inflate('fm:main'))
        self.controller = Controller()

        def post_item_bind(object, collection, item, ui):
            ui.find('name').on('click', self.on_item_click, object, item)
            ui.find('edit').on('click', self.edit, item.fullpath)
        self.find('items').post_item_bind = post_item_bind

        def post_bc_bind(object, collection, item, ui):
            ui.find('name').on('click', self.on_bc_click, object, item)
        self.find('breadcrumbs').post_item_bind = post_bc_bind

        self.clipboard = []
        self.tabs = self.find('tabs')

    def on_first_page_load(self):
        self.new_tab()
        self.binder = Binder(self.controller, self.find('filemanager')).populate()
        self.binder_c = Binder(self, self.find('bind-clipboard')).populate()

    def on_page_load(self):
        self.refresh()

    def refresh_clipboard(self):
        self.binder_c.setup().populate()

    @on('tabs', 'switch')
    def on_tab_switch(self):
        if self.tabs.active == (len(self.controller.tabs) - 1):
            self.new_tab()
        self.refresh()

    @intent('fm:browse')
    def new_tab(self, path=None):
        dir = path or self.classconfig.get('start', None) or '/'
        if not dir.startswith(self.classconfig['root']):
            dir = self.classconfig['root']
        self.controller.new_tab(dir)
        if not self.active:
            self.activate()

    @on('close', 'click')
    def on_tab_close(self):
        if len(self.controller.tabs) > 2:
            self.controller.tabs.pop(self.tabs.active)
        self.tabs.active = 0
        self.refresh()

    @on('new-file', 'click')
    def on_new_file(self):
        destination = self.controller.tabs[self.tabs.active].path
        logging.info('[fm] new file in %s' % destination)
        path = os.path.join(destination, 'new file')
        try:
            open(path, 'w').close()
            self._chown_new(path)
        except OSError as e:
            self.context.notify('error', str(e))
        self.refresh()

    @on('new-dir', 'click')
    def on_new_directory(self):
        destination = self.controller.tabs[self.tabs.active].path
        logging.info('[fm] new directory in %s' % destination)
        path = os.path.join(destination, 'new directory')
        if not os.path.exists(path):
            try:
                os.mkdir(path)
                os.chmod(path, 0755)
                self._chown_new(path)
            except OSError as e:
                self.context.notify('error', str(e))
        self.refresh()

    def _chown_new(self, path):
        uid = self.classconfig.get('new_owner', 'root') or 'root'
        gid = self.classconfig.get('new_group', 'root') or 'root'
        try:
            uid = int(uid)
        except:
            uid = pwd.getpwnam(uid)[2]
        try:
            gid = int(gid)
        except:
            gid = grp.getgrnam(gid)[2]
        os.chown(path, uid, gid)

    def upload(self, name, file):
        destination = self.controller.tabs[self.tabs.active].path
        logging.info('[fm] uploading %s to %s' % (name, destination))
        try:
            output = open(os.path.join(destination, name), 'w')
            while True:
                data = file.read(1024 * 1024)
                if not data:
                    break
                gevent.sleep(0)
                output.write(data)
            output.close()
        except OSError as e:
            self.context.notify('error', str(e))
        self.refresh()

    @on('mass-cut', 'click')
    def on_cut(self):
        l = self._get_checked()
        for i in l:
            i.action = 'cut'
        self.clipboard += l
        self.refresh_clipboard()

    @on('mass-copy', 'click')
    def on_copy(self):
        l = self._get_checked()
        for i in l:
            i.action = 'copy'
        self.clipboard += l
        self.refresh_clipboard()

    @on('mass-delete', 'click')
    def on_delete(self):
        def callback(task):
            self.context.notify('info', _('Files deleted'))
            self.refresh()
        self.backend.remove(self._get_checked(), cb=callback)

    @on('paste', 'click')
    def on_paste(self):
        tab = self.controller.tabs[self.tabs.active]
        for_move = []
        for_copy = []
        for i in self.clipboard:
            if i.action == 'cut':
                for_move.append(i)
            else:
                for_copy.append(i)

        try:
            if for_move:
                def callback(task):
                    self.context.notify('info', _('Files moved'))
                    self.refresh()
                self.backend.move(for_move, tab.path, callback)
            if for_copy:
                def callback(task):
                    self.context.notify('info', _('Files copied'))
                    self.refresh()
                self.backend.copy(for_copy, tab.path, callback)
            self.clipboard = []
        except Exception as e:
            self.context.notify('error', str(e))
        self.refresh_clipboard()

    @on('select-all', 'click')
    def on_select_all(self):
        self.binder.update()
        tab = self.controller.tabs[self.tabs.active]
        for item in tab.items:
            item.checked = not item.checked
        self.binder.populate()
        self.context.notify('info', _('Selected %i items') % len(tab.items)) 

    def _get_checked(self):
        self.binder.update()
        tab = self.controller.tabs[self.tabs.active]
        r = []
        for item in tab.items:
            if item.checked:
                r.append(item)
                item.checked = False
        self.refresh()
        return r

    @on('clear-clipboard', 'click')
    def on_clear_clipboard(self):
        self.clipboard = []
        self.refresh_clipboard()

    def on_item_click(self, tab, item):
        path = os.path.join(tab.path, item.name)
        if not os.path.isdir(path):
            self.edit(path)
        if not path.startswith(self.classconfig['root']):
            return
        tab.navigate(path)
        self.refresh()

    def edit(self, path):
        self.find('dialog').visible = True
        self.item = Item(path)
        self.item.read()
        self.binder_d = Binder(self.item, self.find('dialog')).populate()

        # Unpack
        u = Unpacker.find(self.item.fullpath.lower())
        unpack_btn = self.find('dialog').find('unpack')
        unpack_btn.visible = u is not None

        def cb():
            self.context.notify('info', _('Unpacked'))
            self.refresh()

        def unpack():
            u.unpack(self.item.fullpath, cb=cb)
            logging.info('[fm] unpacking %s' % self.item.fullpath)

        unpack_btn.on('click', lambda: unpack())

        # Edit
        edit_btn = self.find('dialog').find('edit')
        if self.item.size > 1024 * 1024 * 5:
            edit_btn.visible = False

        def edit():
            self.context.launch('notepad', path=self.item.fullpath)

        edit_btn.on('click', lambda: edit())

    @on('dialog', 'button')
    def on_close_dialog(self, button):
        self.find('dialog').visible = False
        if button == 'save':
            self.binder_d.update()
            try:
                self.item.write()
            except Exception as e:
                self.context.notify('error', str(e))
            self.refresh()

            if self.find('chmod-recursive').value:
                cmd = 'chown -Rv "%s:%s" "%s"; chmod -Rv %o "%s"' % (
                    self.item.owner, self.item.group,
                    self.item.fullpath,
                    self.item.mode,
                    self.item.fullpath,
                )
                self.context.launch('terminal', command=cmd)

            logging.info('[fm] modifying %s: %o %s:%s' % (self.item.fullpath, self.item.mode, self.item.owner, self.item.group))

    def on_bc_click(self, tab, item):
        if not item.path.startswith(self.classconfig['root']):
            return
        tab.navigate(item.path)
        self.refresh()

    def refresh(self, _=None):
        for tab in self.controller.tabs:
            tab.refresh()
        self.binder.populate()
Example #44
0
class MailPlugin(SectionPlugin):
    def init(self):
        self.title = _('Mail')
        self.icon = 'envelope'
        self.category = 'Web'

        self.manager = MailManager.get()

        if not self.manager.is_configured:
            self.append(self.ui.inflate('vh-mail:not-configured'))
        else:
            self.post_init()

    @on('initial-enable', 'click')
    def on_initial_enable(self):
        self.post_init()
        self.manager.save()
        self.refresh()

    def post_init(self):
        self.empty()
        self.append(self.ui.inflate('vh-mail:main'))

        self.binder = Binder(None, self)

        def post_mb_bind(object, collection, item, ui):
            ui.find('size').text = str_fsize(self.manager.get_usage(item))

        def post_mb_update(object, collection, item, ui):
            if ui.find('password').value:
                item.password = ui.find('password').value

        self.find('mailboxes').post_item_bind = post_mb_bind
        self.find('mailboxes').post_item_update = post_mb_update

        self.binder.setup(self.manager.config)

    @on('new-mailbox', 'click')
    def on_new_mailbox(self):
        self.binder.update()
        mb = Mailbox.create()
        mb.local = self.find('new-mailbox-local').value
        mb.domain = self.find('new-mailbox-domain').value or self.find(
            'new-mailbox-domain-custom').value
        mb.password = ''
        self.find('new-mailbox-local').value = ''
        if not mb.local:
            self.context.error(_('Invalid mailbox name'))
        if not mb.domain:
            self.context.error(_('Invalid mailbox domain'))

        self.manager.config.mailboxes.append(mb)
        self.manager.save()
        self.binder.populate()

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        domains = []
        for ws in VHManager.get().config.websites:
            domains += [d.domain for d in ws.domains]
        domains = sorted(list(set(domains)))

        self.find('new-mailbox-domain').labels = domains + [_('Custom domain')]
        self.find('new-mailbox-domain').values = domains + [None]

        if self.manager.is_configured:
            self.binder.unpopulate().populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.manager.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
Example #45
0
File: fm.py Project: xuemy/ajenti
class FileManager(SectionPlugin):
    default_classconfig = {'root': '/'}
    classconfig_editor = FileManagerConfigEditor
    classconfig_root = True

    def init(self):
        self.title = _('File Manager')
        self.category = _('Tools')
        self.icon = 'folder-open'

        self.backend = FMBackend().get()

        self.append(self.ui.inflate('fm:main'))
        self.controller = Controller()

        def post_item_bind(object, collection, item, ui):
            ui.find('name').on('click', self.on_item_click, object, item)
            ui.find('edit').on('click', self.edit, item.fullpath)

        self.find('items').post_item_bind = post_item_bind

        def post_bc_bind(object, collection, item, ui):
            ui.find('name').on('click', self.on_bc_click, object, item)

        self.find('breadcrumbs').post_item_bind = post_bc_bind

        self.clipboard = []
        self.tabs = self.find('tabs')

    def on_first_page_load(self):
        self.controller.new_tab(self.classconfig['root'])
        self.binder = Binder(
            self.controller,
            self.find('filemanager')).autodiscover().populate()
        self.binder_c = Binder(
            self, self.find('bind-clipboard')).autodiscover().populate()

    def refresh_clipboard(self):
        self.binder_c.reset().autodiscover().populate()

    @on('tabs', 'switch')
    def on_tab_switch(self):
        if self.tabs.active == (len(self.controller.tabs) - 1):
            self.controller.new_tab(self.classconfig['root'])
        self.refresh()

    @on('close', 'click')
    def on_tab_close(self):
        if len(self.controller.tabs) > 2:
            self.controller.tabs.pop(self.tabs.active)
        self.tabs.active = 0
        self.refresh()

    @on('new-file', 'click')
    def on_new_file(self):
        open(
            os.path.join(self.controller.tabs[self.tabs.active].path,
                         'new file'), 'w').close()
        self.refresh()

    def upload(self, name, file):
        open(os.path.join(self.controller.tabs[self.tabs.active].path, name),
             'w').write(file.read())
        self.refresh()

    @on('new-dir', 'click')
    def on_new_directory(self):
        path = os.path.join(self.controller.tabs[self.tabs.active].path,
                            'new directory')
        if not os.path.exists(path):
            os.mkdir(path)
        self.refresh()

    @on('mass-cut', 'click')
    def on_cut(self):
        l = self._get_checked()
        for i in l:
            i.action = 'cut'
        self.clipboard += l
        self.refresh_clipboard()

    @on('mass-copy', 'click')
    def on_copy(self):
        l = self._get_checked()
        for i in l:
            i.action = 'copy'
        self.clipboard += l
        self.refresh_clipboard()

    @on('mass-delete', 'click')
    def on_delete(self):
        self.backend.remove(self._get_checked())
        self.refresh()

    @on('paste', 'click')
    def on_paste(self):
        tab = self.controller.tabs[self.tabs.active]
        for_move = []
        for_copy = []
        for i in self.clipboard:
            if i.action == 'cut':
                for_move.append(i)
            else:
                for_copy.append(i)

        try:
            if for_move:
                self.backend.move(for_move, tab.path)
            if for_copy:
                self.backend.copy(for_copy, tab.path)
            self.clipboard = []
        except Exception as e:
            self.context.notify('error', str(e))
        self.refresh_clipboard()
        self.refresh()

    @on('select-all', 'click')
    def on_select_all(self):
        self.binder.update()
        tab = self.controller.tabs[self.tabs.active]
        for item in tab.items:
            item.checked = True
        self.binder.populate()
        self.context.notify('info', _('Selected %i items') % len(tab.items))

    def _get_checked(self):
        self.binder.update()
        tab = self.controller.tabs[self.tabs.active]
        r = []
        for item in tab.items:
            if item.checked:
                r.append(item)
                item.checked = False
        self.refresh()
        return r

    @on('clear-clipboard', 'click')
    def on_clear_clipboard(self):
        self.clipboard = []
        self.refresh_clipboard()

    def on_item_click(self, tab, item):
        path = os.path.join(tab.path, item.name)
        if not os.path.isdir(path):
            self.edit(path)
        if not path.startswith(self.classconfig['root']):
            return
        tab.navigate(path)
        self.refresh()

    def edit(self, path):
        self.find('dialog').visible = True
        self.item = Item(path)
        self.item.read()
        self.binder_d = Binder(self.item,
                               self.find('dialog')).autodiscover().populate()

    @on('dialog', 'button')
    def on_close_dialog(self, button):
        self.find('dialog').visible = False
        if button == 'save':
            self.binder_d.update()
            self.item.write()
            self.refresh()

            if self.find('chmod-recursive').value:
                cmd = 'chown -Rv "%s:%s" "%s"; chmod -Rv %o "%s"' % (
                    self.item.owner,
                    self.item.group,
                    self.item.fullpath,
                    self.item.mode,
                    self.item.fullpath,
                )
                self.context.launch('terminal', command=cmd)

    def on_bc_click(self, tab, item):
        if not item.path.startswith(self.classconfig['root']):
            return
        tab.navigate(item.path)
        self.refresh()

    def refresh(self):
        for tab in self.controller.tabs:
            tab.refresh()
        self.binder.populate()
Example #46
0
    def init(self):
        self.title = _('Configure')
        self.icon = 'wrench'
        self.category = ''
        self.order = 50

        self.append(self.ui.inflate('configurator:main'))

        self.binder = Binder(ajenti.config.tree, self.find('ajenti-config'))

        self.ccmgr = ClassConfigManager.get()
        if Licensing.licensing_active:
            self.find('licensing').append(LicensingUI.new(self.ui))
        else:
            self.find('licensing').delete()
        self.classconfig_binding = Binder(self.ccmgr,
                                          self.find('classconfigs'))

        def post_classconfig_bind(object, collection, item, ui):
            def configure():
                self.configure_plugin(item, notify=False)

            ui.find('configure').on('click', configure)

        self.find('classconfigs').find('classes') \
            .post_item_bind = post_classconfig_bind

        self.find('users').new_item = lambda c: UserData()

        def post_user_bind(object, collection, item, ui):
            provider = UserManager.get().get_sync_provider()
            editable = item.name != 'root'
            renameable = editable and provider.allows_renaming
            deletable = renameable

            ui.find('name-edit').visible = renameable
            ui.find('name-label').visible = not renameable
            ui.find('delete').visible = deletable

            box = ui.find('permissions')
            box.empty()

            p = PermissionProvider.get_all()
            for prov in p:
                line = self.ui.create('tab', title=prov.get_name())
                box.append(line)
                for perm in prov.get_permissions():
                    line.append(
                        self.ui.create('checkbox',
                                       id=perm[0],
                                       text=perm[1],
                                       value=(perm[0] in item.permissions)))

            def copy():
                self.save()
                newuser = deepcopy(item)
                newuser.name += '_'
                collection[newuser.name] = newuser
                self.refresh()

            ui.find('copy').on('click', copy)

        self.find('users').post_item_bind = post_user_bind

        def post_user_update(object, collection, item, ui):
            box = ui.find('permissions')
            for prov in PermissionProvider.get_all():
                for perm in prov.get_permissions():
                    has = box.find(perm[0]).value
                    if has and not perm[0] in item.permissions:
                        item.permissions.append(perm[0])
                    if not has and perm[0] in item.permissions:
                        item.permissions.remove(perm[0])
            if ui.find('password').value:
                item.password = ui.find('password').value

        self.find('users').post_item_update = post_user_update
Example #47
0
class LetsEncryptPlugin(SectionPlugin):

    pwd = os.path.join(os.path.dirname(os.path.realpath(__file__)), '')

    nginx_config_dir = platform_select(
        debian='/etc/nginx.custom.d',
        centos='/etc/nginx.custom.d',
        mageia='/etc/nginx.custom.d',
        freebsd='/usr/local/etc/nginx.custom.d',
        arch='/etc/nginx/sites-available',
        osx='/opt/local/etc/nginx',
    )

    crontab_dir = platform_select(
        debian='/etc/cron.d',
        centos='/etc/cron.d',
        mageia='/etc/cron.d',
        freebsd='/usr/local/etc/cron.d',
        arch='/etc/cron.d',
        osx='/opt/local/etc/cron.d',
    )

    has_domains = False

    def init(self):
        self.title = 'LetsEncrypt'  # those are not class attributes and can be only set in or after init()
        self.icon = 'lock'
        self.category = 'Security'
        """
        UI Inflater searches for the named XML layout and inflates it into
        an UIElement object tree
        """
        self.append(self.ui.inflate('letsencrypt:main'))

        self.settings = Settings()

        self.binder = Binder(self.settings, self)
        self.binder.populate()

    def on_page_load(self):
        filepath = self.settings.basedir + self.settings.domainfile
        domains = ''
        if os.path.isfile(filepath):
            domains = os.linesep.join(self.read_domain_file())
        cron = self.check_cron()
        self.find('domains').value = str(domains)
        self.find('cronjob').value = cron

    def write_domain_file(self):
        filepath = self.settings.basedir + self.settings.domainfile
        if not self.find('domains').value:
            self.context.notify('info', 'No domains specified')
            self.has_domains = False
            return

        file = open(filepath, 'w')
        if file.write(self.find('domains').value) is None:
            self.has_domains = True
        else:
            self.context.notify('error', 'Domain file write error')
        file.close()

    def read_domain_file(self):
        filepath = self.settings.basedir + self.settings.domainfile
        if not open(filepath):
            self.context.notify('error', 'Domain file could not be read')

        file = open(filepath)
        with file as f:
            lines = f.readlines()
        return lines

    def create_folders(self):
        uid = pwd.getpwnam("www-data").pw_uid
        gid = grp.getgrnam("www-data").gr_gid

        if not os.path.exists(self.settings.basedir):
            os.makedirs(self.settings.basedir)
            os.chown(self.settings.basedir, uid, gid)
        if not os.path.exists(self.settings.wellknown):
            os.makedirs(self.settings.wellknown)
            os.chown(self.settings.wellknown, uid, gid)

    def create_custom_config(self):
        template = """
        BASEDIR=$basedir
        WELLKNOWN=$wellknown
        """
        dict = {
            'basedir': self.settings.basedir,
            'wellknown': self.settings.wellknown
        }

        filename = 'config'
        filepath = self.settings.basedir + filename
        file = open(filepath, 'w')
        src = Template(template)
        if file.write(src.safe_substitute(dict)) is not None:
            self.context.notify('info', 'Letsencrypt error')
        file.close()

    def create_wellknown(self):
        if not self.check_nginx_custom_dir():
            return False

        template = """
server {
    server_name $domains;
    listen *:80;
    location $location {
        alias $alias;
    }
}
        """
        dict = {
            'location': '/.well-known/acme-challenge',
            'alias': self.settings.wellknown,
            'domains': " ".join(self.read_domain_file())
        }
        filepath = self.nginx_config_dir + '/' + self.settings.nginx_config
        file = open(filepath, 'w')
        src = Template(template)
        if file.write(src.safe_substitute(dict)) is not None:
            self.context.notify('info', 'WELLKNOWN config write error')
        file.close()

    def create_cron(self):
        file = open(self.crontab_dir + '/' + self.settings.cronfile, 'w')
        template = "0 0 1 * * " + self.pwd + 'libs/letsencrypt.sh/letsencrypt.sh -c'
        if not file.write(template):
            self.context.notify('info', 'Cron job error')
        file.close()

    def remove_cron(self):
        if os.path.isfile(self.crontab_dir + '/' + self.settings.cronfile):
            if os.remove(self.crontab_dir + '/' + self.settings.cronfile):
                return True
            else:
                self.context.notify('info', 'Cron remove error')
                return False

    def check_cron(self):
        if os.path.isfile(self.crontab_dir + '/' + self.settings.cronfile):
            return True
        return False

    def check_nginx_custom_dir(self):
        if not os.path.isdir(self.nginx_config_dir):
            if os.makedirs(self.nginx_config_dir):
                return True
            else:
                self.context.notify('error', 'NGINX custom dir write error')
                return False

    def request_certificates(self):
        params = [self.pwd + 'libs/letsencrypt.sh/letsencrypt.sh', '-c']
        if self.find('renewal').value:
            params.append('--force')

        p = subprocess.Popen(params,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE)
        out, err = p.communicate()

        if out:
            self.context.notify('info', 'OUT: ' + out)
        if err:
            self.context.notify('info', 'ERR: ' + err)

    def save(self):
        self.binder.update()
        self.binder.populate()
        self.create_folders()
        self.write_domain_file()

        if not self.has_domains:
            return

        self.create_custom_config()
        self.create_wellknown()

        if self.settings.cronjob:
            self.create_cron()
        else:
            self.remove_cron()

    @on('save', 'click')
    def save_button(self):
        self.save()

    @on('request', 'click')
    def request_button(self):
        self.save()
        self.request_certificates()
Example #48
0
class Configurator(SectionPlugin):
    def init(self):
        self.title = _('Configure')
        self.icon = 'wrench'
        self.category = ''
        self.order = 50

        self.append(self.ui.inflate('configurator:main'))

        self.binder = Binder(ajenti.config.tree, self.find('ajenti-config'))

        self.ccmgr = ClassConfigManager.get()
        if Licensing.licensing_active:
            self.find('licensing').append(LicensingUI.new(self.ui))
        else:
            self.find('licensing').delete()
        self.classconfig_binding = Binder(self.ccmgr,
                                          self.find('classconfigs'))

        def post_classconfig_bind(object, collection, item, ui):
            def configure():
                self.configure_plugin(item, notify=False)

            ui.find('configure').on('click', configure)

        self.find('classconfigs').find('classes') \
            .post_item_bind = post_classconfig_bind

        self.find('users').new_item = lambda c: UserData()

        def post_user_bind(object, collection, item, ui):
            provider = UserManager.get().get_sync_provider()
            editable = item.name != 'root'
            renameable = editable and provider.allows_renaming
            deletable = renameable

            ui.find('name-edit').visible = renameable
            ui.find('name-label').visible = not renameable
            ui.find('delete').visible = deletable

            box = ui.find('permissions')
            box.empty()

            p = PermissionProvider.get_all()
            for prov in p:
                line = self.ui.create('tab', title=prov.get_name())
                box.append(line)
                for perm in prov.get_permissions():
                    line.append(
                        self.ui.create('checkbox',
                                       id=perm[0],
                                       text=perm[1],
                                       value=(perm[0] in item.permissions)))

            def copy():
                self.save()
                newuser = deepcopy(item)
                newuser.name += '_'
                collection[newuser.name] = newuser
                self.refresh()

            ui.find('copy').on('click', copy)

        self.find('users').post_item_bind = post_user_bind

        def post_user_update(object, collection, item, ui):
            box = ui.find('permissions')
            for prov in PermissionProvider.get_all():
                for perm in prov.get_permissions():
                    has = box.find(perm[0]).value
                    if has and not perm[0] in item.permissions:
                        item.permissions.append(perm[0])
                    if not has and perm[0] in item.permissions:
                        item.permissions.remove(perm[0])
            if ui.find('password').value:
                item.password = ui.find('password').value

        self.find('users').post_item_update = post_user_update

    def on_page_load(self):
        self.refresh()

    @on('sync-users-button', 'click')
    def on_sync_users(self):
        self.save()
        prov = UserManager.get().get_sync_provider()
        try:
            prov.test()
            prov.sync()
        except Exception as e:
            self.context.notify('error', str(e))
        self.refresh()

    @on('configure-sync-button', 'click')
    def on_configure_sync(self):
        self.save()
        if UserManager.get().get_sync_provider(
        ).classconfig_editor is not None:
            self.configure_plugin(UserManager.get().get_sync_provider(),
                                  notify=False)
        self.refresh()

    def refresh(self):
        self.binder.unpopulate()

        self.find('sync-providers').labels = [
            x.title for x in UserSyncProvider.get_classes()
        ]
        self.find('sync-providers').values = [
            x.id for x in UserSyncProvider.get_classes()
        ]

        provider = UserManager.get().get_sync_provider()
        self.find('sync-providers').value = provider.id
        self.find('users-dt').addrow = _('Add') if provider.id == '' else None
        self.find('sync-users-button').visible = provider.id != ''
        self.find('password').visible = provider.id == ''
        self.find('configure-sync-button').visible = \
            provider.classconfig_editor is not None

        try:
            provider.test()
            sync_ok = True
        except Exception as e:
            self.context.notify('error', str(e))
            sync_ok = False

        self.find('sync-status-ok').visible = sync_ok
        self.find('sync-status-fail').visible = not sync_ok

        languages = sorted(ajenti.locales.list_locales())
        self.find('language').labels = [_('Auto'), 'en_US'] + languages
        self.find('language').values = ['', 'en_US'] + languages

        self.binder.setup().populate()
        self.ccmgr.reload()
        self.classconfig_binding.setup().populate()

    @on('save-button', 'click')
    @restrict('configurator:configure')
    def save(self):
        self.binder.update()

        UserManager.get().set_sync_provider(self.find('sync-providers').value)

        UserManager.get().hash_passwords()

        self.refresh()
        ajenti.config.save()
        self.context.notify(
            'info',
            _('Saved. Please restart Ajenti for changes to take effect.'))

    @on('fake-ssl', 'click')
    def on_gen_ssl(self):
        host = self.find('fake-ssl-host').value
        if host == '':
            self.context.notify('error', _('Please supply hostname'))
        else:
            self.gen_ssl(host)

    @on('restart-button', 'click')
    def on_restart(self):
        ajenti.restart()

    @intent('configure-plugin')
    def configure_plugin(self, plugin=None, notify=True):
        self.find('tabs').active = 1
        self.refresh()

        if plugin and notify:
            self.context.notify(
                'info',
                _('Please configure %s plugin!') %
                plugin.classconfig_editor.title)

        self.activate()

        dialog = self.find('classconfigs').find('dialog')
        dialog.find('container').empty()
        dialog.visible = True

        editor = plugin.classconfig_editor.new(self.ui)
        dialog.find('container').append(editor)

        if editor.find('bind'):
            logging.warn('%s uses old dictbinding classconfig editor layout')
            binder = DictAutoBinding(plugin, 'classconfig',
                                     editor.find('bind'))
        else:
            binder = Binder(plugin, editor)
        binder.populate()

        def save(button=None):
            dialog.visible = False
            binder.update()
            plugin.save_classconfig()
            self.save()

        dialog.on('button', save)

    @intent('setup-fake-ssl')
    def gen_ssl(self, host):
        self.save()
        subprocess.call(['ajenti-ssl-gen', host, '-f'])
        ajenti.config.load()
        self.refresh()
Example #49
0
 def init(self):
     self.append(self.ui.inflate('vh-mysql:ext'))
     self.binder = Binder(self, self)
     self.refresh()
     self.db = MySQLDB.get()
Example #50
0
class WebserverPlugin (SectionPlugin):
    service_name = ''
    service_buttons = []
    hosts_available_dir = ''
    hosts_enabled_dir = ''
    template = ''
    supports_host_activation = True

    def log(self, msg):
        logging.info('[%s] %s' % (self.service_name, msg))

    def init(self):
        self.append(self.ui.inflate('webserver_common:main'))
        self.binder = Binder(None, self)
        self.find_type('servicebar').buttons = self.service_buttons
        self.hosts_dir = AvailabilitySymlinks(
            self.hosts_available_dir, 
            self.hosts_enabled_dir,
            self.supports_host_activation
        )

        def delete_host(host, c):
            self.log('removed host %s' % host.name)
            c.remove(host)
            self.hosts_dir.delete(host.name)

        def on_host_bind(o, c, host, u):
            host.__old_name = host.name

        def on_host_update(o, c, host, u):
            if host.__old_name != host.name:
                self.log('renamed host %s to %s' % (host.__old_name, host.name))
                self.hosts_dir.rename(host.__old_name, host.name)
            host.save()

        def new_host(c):
            name = 'untitled'
            while os.path.exists(self.hosts_dir.get_path(name)):
                name += '_'
            self.log('created host %s' % name)
            self.hosts_dir.open(name, 'w').write(self.template)
            return WebserverHost(self, self.hosts_dir, name)

        self.find('hosts').delete_item = delete_host
        self.find('hosts').new_item = new_host
        self.find('hosts').post_item_bind = on_host_bind
        self.find('hosts').post_item_update = on_host_update
        self.find('header-active-checkbox').visible = \
            self.find('body-active-line').visible = \
                self.supports_host_activation

    def on_page_load(self):
        self.refresh()

    @on('save-button', 'click')
    def save(self):
        self.log('saving hosts')
        self.binder.update()
        self.refresh()
        self.context.notify('info', 'Saved')

    def refresh(self):
        self.hosts = [WebserverHost(self, self.hosts_dir, x) for x in self.hosts_dir.list_available()]
        self.binder.setup(self).populate()
        self.find_type('servicebar').reload()
Example #51
0
class MySQLExtension(BaseExtension):
    default_config = {
        'databases': [],
        'users': [],
    }
    name = 'MySQL'

    def init(self):
        self.append(self.ui.inflate('vh-mysql:ext'))
        self.binder = Binder(self, self)
        self.refresh()
        self.db = MySQLDB.get()

    @staticmethod
    def selftest():
        try:
            MySQLDB.get().query_databases()
        except:
            pass

    def refresh(self):
        if not 'databases' in self.config:
            if self.config['created']:
                self.config['databases'] = [{
                    'name': self.config['name'],
                }]
                self.config['users'] = [{
                    'name': self.config['user'],
                    'password': self.config['password'],
                }]
            else:
                self.config['databases'] = []
                self.config['users'] = []

            del self.config['created']
            del self.config['name']
            del self.config['user']
            del self.config['password']

        def post_db_bind(object, collection, item, ui):
            ui.find('detach').on('click', self.on_detach_db, item)

        self.find('databases').post_item_bind = post_db_bind

        def post_user_bind(object, collection, item, ui):
            ui.find('detach').on('click', self.on_detach_user, item)

        self.find('users').post_item_bind = post_user_bind

        self.binder.setup().populate()
        self.find('db-name').value = self.website.slug
        self.find('db-username').value = self.website.slug

        self.find('db-password').value = str(uuid.uuid4())

        self.find('databases').delete_item = lambda i, c: self.on_delete_db(i)
        self.find('users').delete_item = lambda i, c: self.on_delete_user(i)

    def update(self):
        self.binder.update()

    def on_destroy(self):
        pass

    @on('create-db', 'click')
    def on_create_db(self):
        try:
            self.db.query_databases()
        except Exception, e:
            self.context.notify('error', str(e))
            self.context.launch('configure-plugin', plugin=self.db)
            return

        dbname = self.find('db-name').value

        for db in self.db.query_databases():
            if db.name == dbname:
                self.context.notify('error',
                                    _('This database name is already used'))
                return

        db_cfg = {'name': dbname}

        try:
            self.db.query_create(db_cfg['name'])
        except Exception, e:
            self.context.notify('error', str(e))
            return
Example #52
0
 def init(self):
     self.append(self.ui.inflate('network:bit-linux-ifupdown'))
     self.binder = Binder(None, self)
Example #53
0
class NetworkPlugin(SectionPlugin):
    platforms = ['debian', 'centos']

    def init(self):
        self.title = _('Network')
        self.icon = 'globe'
        self.category = _('System')
        self.net_config = INetworkConfig.get()

        self.append(self.ui.inflate('network:main'))

        def post_interface_bind(o, c, i, u):
            i.add_bits(self.ui)
            for bit in i.bits:
                u.find('bits').append(
                    self.ui.create(
                        'tab',
                        children=[bit],
                        title=bit.title,
                    ))
            u.find('up').on('click', self.on_up, i)
            u.find('down').on('click', self.on_down, i)
            u.find('restart').on('click', self.on_restart, i)

        def post_interface_update(o, c, i, u):
            for bit in i.bits:
                bit.apply()

        self.find('interfaces').post_item_bind = post_interface_bind
        self.find('interfaces').post_item_update = post_interface_update

        self.binder = Binder(self.net_config, self)

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.net_config.rescan()

        sensor = Sensor.find('traffic')
        for i in self.net_config.interface_list:
            i.tx, i.rx = sensor.value(i.name)

        self.binder.reset().autodiscover().populate()
        return

    def on_up(self, iface=None):
        self.save()
        self.net_config.up(iface)
        self.refresh()

    def on_down(self, iface=None):
        self.save()
        self.net_config.down(iface)
        self.refresh()

    def on_restart(self, iface=None):
        self.save()
        self.on_down(iface)
        self.on_up(iface)

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.net_config.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
Example #54
0
class NTPDPlugin(SectionPlugin):
    def get_tz_debian(self):
        return open('/etc/timezone').read().strip()

    def get_tz_nondebian(self):
        return os.path.realpath(
            '/etc/localtime')[len('/usr/share/zoneinfo/'):] if os.path.islink(
                '/etc/localtime') else ''

    def set_tz_debian(self, timezone):
        open('/etc/timezone', 'w').write(timezone + '\n')

    def set_tz_nondebian(self, timezone):
        tz = os.path.join('/usr/share/zoneinfo/', timezone)
        if os.path.exists('/etc/localtime'):
            os.unlink('/etc/localtime')
        os.symlink(tz, '/etc/localtime')

    openntpd = isopenntpd()

    service_name = platform_select(
        default='openntpd' if openntpd else 'ntp',
        centos='openntpd' if openntpd else 'ntpd',
        mageia='ntpd',
    )

    get_tz = platform_select(
        debian=get_tz_debian,
        default=get_tz_nondebian,
    )

    set_tz = platform_select(
        debian=set_tz_debian,
        default=set_tz_nondebian,
    )

    def init(self):
        self.title = _('Date & Time')
        self.icon = 'time'
        self.category = _('System')

        self.append(self.ui.inflate('ntpd:main'))

        self.find('servicebar').name = self.service_name
        self.find('servicebar').reload()

        self.config = NTPDConfig(path=platform_select(
            default=open_ntpd_conf if self.openntpd else ntpd_conf,
            centos='/usr/local/etc/ntpd.conf' if self.openntpd else ntpd_conf,
            freebsd='/usr/local/etc/ntpd.conf' if self.openntpd else ntpd_conf,
        ))

        self.binder = Binder(None, self)

        self.available_zones = []
        for d, dirs, files in os.walk('/usr/share/zoneinfo',
                                      followlinks=False):
            for f in files:
                if f != 'zone.tab':
                    self.available_zones.append(os.path.join(d, f))
        self.available_zones = [
            x[len('/usr/share/zoneinfo/'):] for x in self.available_zones
        ]
        self.available_zones.sort()

        self.find('servers').new_item = lambda c: ServerData()

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.config.load()
        self.now = int(time.time())
        self.timezone = self.get_tz()
        self.binder.setup(self).populate()

    @on('set', 'click')
    def on_set(self):
        self.binder.update()
        d = datetime.fromtimestamp(self.now)
        s = d.strftime('%m%d%H%M%Y')
        self.set_tz(self.timezone)
        subprocess.call(['date', s])
        self.refresh()

    @on('sync', 'click')
    def on_sync(self):
        self.binder.update()
        if len(self.config.tree.servers) == 0:
            self.context.notify('error', _('No servers defined'))
            return
        server = self.config.tree.servers[0].address
        output = subprocess.check_output(['ntpdate', '-u', server])
        self.context.notify('info', _('Done'))
        self.context.notify('info', output)
        self.refresh()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
        self.refresh()
        self.context.notify('info', _('Saved'))
        ServiceMultiplexor.get().get_one(self.service_name).restart()
Example #55
0
class fail2ban(SectionPlugin):
    def init(self):
        self.title = 'fail2ban'
        self.icon = 'shield'
        self.category = _('Software')
        self.f2b_v = subprocess.check_output(['fail2ban-client', '--version']).splitlines()[0]
        self.append(self.ui.inflate('fail2ban:main'))
        self.binder = Binder(self, self)
        self.update_status = True

        def on_config_update(o, c, config, u):
            if config.__old_name != config.name:
                if os.path.exists(os.path.join(c.path, config.name)):
                    self.context.notify('error', _(
                        'File with name {0} already exists in {1}.').format(config.name, c.path))
                    self.update_status = False
                    config.name = config.__old_name
                    return
                logging.debug('renamed config file %s to %s' % (config.__old_name, config.name))
                os.unlink(config.configfile)
            config.save()
            self.update_status = True

        def on_config_bind(o, c, config, u):
            config.__old_name = config.name

        def new_config(c):
            new_fn = 'untitled{0}.conf'
            s_fn = new_fn.format('')
            filename = os.path.join(c.path, s_fn)
            i = 1
            while os.path.exists(filename):
                s_fn = new_fn.format('_' + str(i))
                filename = os.path.join(c.path, s_fn)
                i += 1
            try:
                logging.debug('add config %s' % filename)
                conf = f2b_Config(s_fn, c.path)
                conf.config = config_templates[c.type]
                return conf.save()
            except IOError as e:
                print('Error writing file {0} in {1}'.format(filename, c.path))

        def delete_config(config, c):
            filename = config.configfile
            logging.debug('removed config %s' % config.configfile)
            c.remove(config)
            os.unlink(filename)

        self.find('configlist').post_item_update = on_config_update
        self.find('configlist').post_item_bind = on_config_bind
        self.find('configlist').new_item = new_config
        self.find('configlist').delete_item = delete_config

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.configurations = [
            f2b_Configs(k, d).update()
            for k, d in config_dirs.iteritems()
            if os.path.isdir(d)
        ]
        self.binder.setup(self).populate()

    @on('save-button', 'click')
    def save(self):
        self.binder.update()
        if self.update_status:
            self.context.notify('info', _('Saved'))
        self.update_status = True
        self.binder.setup(self).populate()

    @on('check-regex', 'click')
    def check_regex(self):
        self.find('check-status').text = ''
        log_fname = self.find('log-filename').value
        filter_fname = self.find('filter-filename').value
        log_as_text = self.find('log-file').value
        filter_as_text = self.find('filter-file').value
        if not (log_fname or log_as_text) or not (filter_fname or filter_as_text):
            logging.debug('Filter checker. Some parameters are empty.')
            self.context.notify('error', _('Some parameters are empty.'))
            return

        with open(filter_fname + '.tmp', 'w') as rt:
            rt.write(self.find('filter-file').value)
            rt_name = rt.name
            rt.close()

        p = subprocess.Popen(['fail2ban-regex', '--full-traceback', log_fname, rt_name], stdout=subprocess.PIPE,
                             stderr=subprocess.STDOUT)
        out, err = p.communicate()
        self.find('check-status').text = out

        os.unlink(rt_name)

    @on('open-filter-button', 'click')
    def open_filter(self):
        self.find('openfilterdialog').show()

    @on('openfilterdialog', 'button')
    def on_open_filter_dialog(self, button):
        self.find('openfilterdialog').visible = False

    @on('openfilterdialog', 'select')
    def on_filter_file_select(self, path=None):
        if not path:
            return
        self.find('openfilterdialog').visible = False
        self.find('filter-filename').value = path
        self.find('filter-file').value = ''.join(open(path).readlines())

    @on('open-log-button', 'click')
    def open_log(self):
        self.find('openlogdialog').show()

    @on('openlogdialog', 'button')
    def on_open_log_dialog(self, button):
        self.find('openlogdialog').visible = False

    @on('openlogdialog', 'select')
    def on_log_file_select(self, path=None):
        if not path:
            return
        self.find('openlogdialog').visible = False
        self.find('log-filename').value = path
        self.find('log-file').value = ''.join(open(path).readlines())

    @on('save-filter-button', 'click')
    def save_filter(self):
        try:
            open(self.find('filter-filename').value, 'w').write(self.find('filter-file').value)
        except IOError as e:
            self.context.notify('error', _('Could not save config file. %s') % str(e))
            logging.error(e.message)
Example #56
0
class Firewall (SectionPlugin):

    def init(self):
        self.title = 'Firewall'
        self.icon = 'fire'
        self.category = 'System'

        self.append(self.ui.inflate('iptables:main'))

        self.fw_mgr = FirewallManager.get()
        self.config = IPTablesConfig(path=self.fw_mgr.config_path)
        self.binder = Binder(None, self.find('config'))

        self.find('tables').new_item = lambda c: TableData()
        self.find('chains').new_item = lambda c: ChainData()
        self.find('rules').new_item = lambda c: RuleData()
        self.find('options').new_item = lambda c: OptionData()
        self.find('options').binding = OptionsBinding
        self.find('options').filter = lambda i: not i.name in ['j', 'jump']

        def post_rule_bind(o, c, i, u):
            u.find('add-option').on('change', self.on_add_option, c, i, u)
            actions = ['ACCEPT', 'DROP', 'REJECT', 'LOG', 'MASQUERADE', 'DNAT', 'SNAT'] + \
                list(set(itertools.chain.from_iterable([[c.name for c in t.chains] for t in self.config.tree.tables])))
            u.find('action-select').labels = actions
            u.find('action-select').values = actions
            action = ''
            j_option = i.get_option('j', 'jump')
            if j_option:
                action = j_option.arguments[0].value
            u.find('action').text = action
            u.find('action').style = 'iptables-action iptables-%s' % action
            u.find('action-select').value = action

        def post_rule_update(o, c, i, u):
            action = u.find('action-select').value
            j_option = i.get_option('j', 'jump')
            if j_option:
                j_option.arguments[0].value = action
            else:
                o = OptionData.create_destination()
                o.arguments[0].value = action
                i.options.append(o)

        self.find('rules').post_item_bind = post_rule_bind
        self.find('rules').post_item_update = post_rule_update

        self.find('add-option').values = self.find('add-option').labels = ['Add option'] + sorted(OptionData.templates.keys())

    def on_page_load(self):
        if not os.path.exists(self.fw_mgr.config_path):
            subprocess.call('iptables-save > %s' % self.fw_mgr.config_path, shell=True)
        self.config.load()
        self.refresh()

    def refresh(self):
        self.binder.reset(self.config.tree).autodiscover().populate()
        self.find('autostart').text = ('Disable' if self.fw_mgr.get_autostart_state() else 'Enable') + ' autostart'

    @on('autostart', 'click')
    def on_autostart_change(self):
        self.fw_mgr.set_autostart_state(not self.fw_mgr.get_autostart_state())
        self.refresh()

    def on_add_option(self, options, rule, ui):
        o = OptionData.create(ui.find('add-option').value)
        ui.find('add-option').value = ''
        rule.options.append(o)
        self.binder.populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.config.save()
        self.refresh()

    @on('edit', 'click')
    def raw_edit(self):
        self.context.launch('notepad', path='/etc/iptables.up.rules')

    @on('apply', 'click')
    def apply(self):
        self.save()
        cmd = 'cat /etc/iptables.up.rules | iptables-restore'
        if subprocess.call(cmd, shell=True) != 0:
            self.context.launch('terminal', command=cmd)
        else:
            self.context.notify('info', 'Saved')
Example #57
0
class CTDB(SectionPlugin):
    nodes_file = '/etc/ctdb/nodes'
    addresses_file = '/etc/ctdb/public_addresses'

    def init(self):
        self.title = _('Samba Cluster')
        self.icon = 'folder-close'
        self.category = _('Software')

        self.append(self.ui.inflate('ctdb:main'))

        self.config_path = {
            'debian': '/etc/default/ctdb',
            'centos': '/etc/sysconfig/ctdb',
            'mageia': '/etc/sysconfig/ctdb'
        }[ajenti.platform]

        self.config = CTDBConfig(path=self.config_path)
        self.config.load()

        self.binder = Binder(None, self.find('main-config'))
        self.n_binder = Binder(None, self.find('nodes-config'))
        self.a_binder = Binder(None, self.find('addresses-config'))
        self.find('nodes').new_item = lambda c: NodeData()
        self.find('addresses').new_item = lambda c: self.new_address()

    def new_address(self):
        a = PublicAddressData()
        a.address = '192.168.0.1/24'
        return a

    def on_page_load(self):
        n_path = self.config.tree.nodes_file
        self.nodes_config = CTDBNodesConfig(path=n_path)
        if not os.path.exists(n_path):
            open(n_path, 'w').close()
        self.nodes_config.load()

        a_path = self.config.tree.public_addresses_file
        self.addresses_config = CTDBPublicAddressesConfig(path=a_path)
        if not os.path.exists(a_path):
            open(a_path, 'w').close()
        self.addresses_config.load()

        self.config.load()
        self.binder.setup(self.config.tree).populate()
        self.n_binder.setup(self.nodes_config.tree).populate()
        self.a_binder.setup(self.addresses_config.tree).populate()
        self.refresh()

    @on('refresh', 'click')
    def refresh(self):
        try:
            self.find('status').value = subprocess.check_output(
                ['ctdb', 'status'])
            self.find('status-ip').value = subprocess.check_output(
                ['ctdb', 'ip'])
        except:
            self.find('status').value = _('Failed to obtain CTDB status')

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.n_binder.update()
        self.a_binder.update()
        self.config.save()
        self.nodes_config.save()
        self.addresses_config.save()
        self.context.notify('info', _('Saved'))
Example #58
0
class Configurator(SectionPlugin):
    def init(self):
        self.title = _('Configure')
        self.icon = 'wrench'
        self.category = ''
        self.order = 50

        self.append(self.ui.inflate('configurator:main'))

        self.binder = Binder(ajenti.config.tree, self.find('ajenti-config'))

        self.ccmgr = ClassConfigManager.get()
        self.classconfig_binding = Binder(self.ccmgr,
                                          self.find('classconfigs'))
        self.classconfig_rows = {}

        def post_classconfig_bind(object, collection, item, ui):
            self.classconfig_rows[item] = ui
            editor = item.classconfig_editor.new(self.ui)
            ui.find('container').append(editor)
            binder = DictAutoBinding(item, 'classconfig', editor.find('bind'))
            binder.populate()

            def save():
                binder.update()
                item.save_classconfig()
                self.context.notify('info', _('Saved'))

            ui.find('save').on('click', save)

        self.find('classconfigs').find(
            'classes').post_item_bind = post_classconfig_bind

        self.find('users').new_item = lambda c: UserData()

        def post_user_bind(object, collection, item, ui):
            box = ui.find('permissions')
            box.empty()
            ui.find('name-edit').visible = item.name != 'root'
            ui.find('name-label').visible = item.name == 'root'
            for prov in PermissionProvider.get_all():
                line = self.ui.create('tab', title=prov.get_name())
                box.append(line)
                for perm in prov.get_permissions():
                    line.append(
                        self.ui.create('checkbox',
                                       id=perm[0],
                                       text=perm[1],
                                       value=(perm[0] in item.permissions)))

        self.find('users').post_item_bind = post_user_bind

        def post_user_update(object, collection, item, ui):
            box = ui.find('permissions')
            for prov in PermissionProvider.get_all():
                for perm in prov.get_permissions():
                    has = box.find(perm[0]).value
                    if has and not perm[0] in item.permissions:
                        item.permissions.append(perm[0])
                    if not has and perm[0] in item.permissions:
                        item.permissions.remove(perm[0])
            if ui.find('password').value:
                item.password = ui.find('password').value

        self.find('users').post_item_update = post_user_update

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        self.binder.reset().autodiscover().populate()
        self.ccmgr.reload()
        self.classconfig_binding.reset().autodiscover().populate()

    @on('save-button', 'click')
    @restrict('configurator:configure')
    def save(self):
        self.binder.update()
        for user in ajenti.config.tree.users.values():
            if not '|' in user.password:
                user.password = UserManager.get().hash_password(user.password)
        self.binder.populate()
        ajenti.config.save()
        self.context.notify(
            'info',
            _('Saved. Please restart Ajenti for changes to take effect.'))

    @on('fake-ssl', 'click')
    def on_gen_ssl(self):
        host = self.find('fake-ssl-host').value
        if host == '':
            self.context.notify('error', _('Please supply hostname'))
        else:
            self.gen_ssl(host)

    @on('restart-button', 'click')
    def on_restart(self):
        ajenti.restart()

    @intent('configure-plugin')
    def configure_plugin(self, plugin=None):
        self.find('tabs').active = 1
        self.refresh()
        #if plugin in self.classconfig_rows:
        #    self.classconfig_rows[plugin].children[0].expanded = True
        #    print self.classconfig_rows[plugin].children[0]
        if plugin:
            self.context.notify(
                'info',
                _('Please configure %s plugin!') %
                plugin.classconfig_editor.title)
        self.activate()

    @intent('setup-fake-ssl')
    def gen_ssl(self, host):
        self.save()
        subprocess.call(['ajenti-ssl-gen', host, '-f'])
        ajenti.config.load()
        self.refresh()
Example #59
0
File: main.py Project: xuemy/ajenti
class Tasks(SectionPlugin):
    def init(self):
        self.title = _('Tasks')
        self.icon = 'cog'
        self.category = _('Tools')

        self.append(self.ui.inflate('tasks:main'))

        self.manager = TaskManager.get(manager.context)
        self.binder = Binder(None, self)

        def post_td_bind(object, collection, item, ui):
            if item.get_class():
                params_ui = self.ui.inflate(item.get_class().ui)
                item.binder = DictAutoBinding(item, 'params',
                                              params_ui.find('bind'))
                item.binder.populate()
                ui.find('slot').empty()
                ui.find('slot').append(params_ui)

        def post_td_update(object, collection, item, ui):
            if hasattr(item, 'binder'):
                item.binder.update()

        def post_rt_bind(object, collection, item, ui):
            def abort():
                item.abort()
                self.refresh()

            ui.find('abort').on('click', abort)

        self.find('task_definitions').post_item_bind = post_td_bind
        self.find('task_definitions').post_item_update = post_td_update
        self.find('running_tasks').post_item_bind = post_rt_bind

        self.find('job_definitions').new_item = lambda c: JobDefinition()

    def on_page_load(self):
        self.refresh()

    @on('refresh', 'click')
    def refresh(self):
        self.binder.reset(self.manager)
        self.manager.refresh()

        dd = self.find('task-classes')
        dd.labels = []
        dd.values = []
        for task in Task.get_classes():
            if not task.hidden:
                dd.labels.append(task.name)
                dd.values.append(task.classname)

        dd = self.find('task-selector')
        dd.labels = [_.name for _ in self.manager.task_definitions]
        dd.values = [_.id for _ in self.manager.task_definitions]
        self.find('run-task-selector').labels = dd.labels
        self.find('run-task-selector').values = dd.values

        self.binder.autodiscover().populate()

    @on('run-task', 'click')
    def on_run_task(self):
        self.manager.run(task_id=self.find('run-task-selector').value,
                         context=self.context)
        self.refresh()

    @on('create-task', 'click')
    def on_create_task(self):
        cls = self.find('task-classes').value
        td = TaskDefinition(task_class=cls)
        td.name = td.get_class().name
        self.manager.task_definitions.append(td)
        self.refresh()

    @on('save', 'click')
    def on_save(self):
        self.binder.update()
        self.manager.save()
        self.refresh()
Example #60
0
 def on_first_page_load(self):
     self.new_tab()
     self.binder = Binder(self.controller, self.find('filemanager')).populate()
     self.binder_c = Binder(self, self.find('bind-clipboard')).populate()