Пример #1
0
class SanickioskScreensaverPrefs(SectionPlugin):
    default_classconfig = {
        'xscreensaver_enable': True,
        'xscreensaver_idle': '0:01:30',
        'glslideshow_duration': '',
        'glslideshow_pan': '',
        'glslideshow_fade': '3',
        'glslideshow_zoom': '100',
        'glslideshow_clip': True,
    }
    classconfig_root = True

    def init(self):
        self.title = 'Screensaver'
        self.icon = 'picture'
        self.category = 'Sanickiosk'

        self.append(self.ui.inflate('sanickiosk_screensaver:main'))
        self.binder = Binder(self, self)
        self.binder.populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.save_classconfig()
        self.context.notify(
            'info',
            _('Saved. Please restart Sanickiosk for changes to take effect.'))
        self.binder.populate()

        all_vars = '\n'.join(
            [k + '="' + str(v) + '"' for k, v in self.classconfig.iteritems()])
        open('/home/kiosk/.sanickiosk/screensaver.cfg',
             'w').write(all_vars)  #save
Пример #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()
Пример #3
0
class SimpleDemo(SectionPlugin):
    def init(self):
        self.title = "Binder"
        self.icon = "question"
        self.category = "Demo"

        self.append(self.ui.inflate("test:binder-main"))

        self.data = [Person("Alice", "123"), Person("Bob", "234")]

        self.dict = {"a": 1, "b": 2}

        self.find("data").text = repr(self.data)

        self.binder = Binder(self, self.find("bindroot"))

    @on("populate", "click")
    def on_populate(self):
        self.binder.populate()

    @on("unpopulate", "click")
    def on_unpopulate(self):
        self.binder.unpopulate()

    @on("update", "click")
    def on_update(self):
        self.binder.update()
        self.find("data").text = repr(self.data)
Пример #4
0
class SimpleDemo (SectionPlugin):
    def init(self):
        self.title = 'Binder'
        self.icon = 'question'
        self.category = 'Demo'

        self.append(self.ui.inflate('test:binder-main'))

        self.data = [
            Person('Alice', '123'),
            Person('Bob', '234'),
        ]
        self.find('data').text = repr(self.data)

        self.binder = Binder(self, self.find('bindroot'))

    @on('populate', 'click')
    def on_populate(self):
        self.binder.populate()

    @on('unpopulate', 'click')
    def on_unpopulate(self):
        self.binder.unpopulate()

    @on('update', 'click')
    def on_update(self):
        self.binder.update()
        self.find('data').text = repr(self.data)
Пример #5
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):
        """
Пример #6
0
class SanickioskScreensaverPrefs (SectionPlugin):
	default_classconfig = {
		'xscreensaver_enable': True,
		'xscreensaver_idle': '0:01:30',
		'glslideshow_duration': '',
		'glslideshow_pan': '',
		'glslideshow_fade': '3',
		'glslideshow_zoom': '100',
		'glslideshow_clip': True,
	}
	classconfig_root = True

	def init(self):
		self.title = 'Screensaver'
		self.icon = 'picture'
		self.category = 'Sanickiosk'

		self.append(self.ui.inflate('sanickiosk_screensaver:main'))
		self.binder = Binder(self, self)
		self.binder.populate()

	@on('save', 'click')
	def save(self):
		self.binder.update()
		self.save_classconfig()
		self.context.notify('info', _('Saved. Please restart Sanickiosk for changes to take effect.'))
		self.binder.populate()

		all_vars = '\n'.join([k + '="' + str(v) + '"' for k,v in self.classconfig.iteritems()])
		open('/home/kiosk/.sanickiosk/screensaver.cfg', 'w').write(all_vars) #save
Пример #7
0
class Teamspeak(SectionPlugin):
    def init(self):
        self.title = 'Teamspeak'
        self.icon = 'comments'
        self.category = _('Software')
        self.append(self.ui.inflate('teamspeak3:main'))
        self.backend = TeamspeakBackend.get()
        self.users = []
        self.servers = []
        self.banlist = []
        self.binder = Binder(self, self)

        def post_item_bind_users(object, collection, item, ui):
            ui.find('poke').on('click', self.on_poke, item)
            ui.find('kick').on('click', self.on_kick, item)
            ui.find('ban').on('click', self.on_ban, item)

        def post_item_bind_banlist(object, collection, item, ui):
            ui.find('unban').on('click', self.on_unban, item)

        self.find('users').post_item_bind = post_item_bind_users
        self.find('banlist').post_item_bind = post_item_bind_banlist

    def on_poke(self, item):
        self.backend.clientpoke(item.uid)
        self.context.notify('info', 'Client has been poked!')

    def on_kick(self, item):
        self.backend.clientkick(item.uid)
        self.refresh()
        self.context.notify('info', 'Client has been kicked from the server!')

    def on_ban(self, item):
        self.backend.clientban(item.username)  # @todo Change this to IP Address!
        self.refresh()
        self.context.notify('info', 'Client has been banned from the server!')

    def on_unban(self, item):
        self.backend.clientunban(item.banid)
        self.refresh()
        self.context.notify('info', 'Client has been unbanned from the server!')

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        try:
            self.backend.initialize()
        except Exception as err:
            self.context.notify('error', err.message)
            self.context.launch('configure-plugin', plugin=self.backend)
            return

        self.binder.update()
        self.users = self.backend.clientlist()
        self.servers = self.backend.serverinfo()
        self.banlist = self.backend.banlist()
        self.binder.populate()
Пример #8
0
class SanickioskScreensaverPrefs (SectionPlugin):
	default_classconfig = {
		    'enable_videos': False,
    		'video_volume': 50
	}
	classconfig_root = True

	def init(self):
		self.title = 'Режим Видео'
		self.icon = 'facetime-video'
		self.category = 'Kiosk'

		self.append(self.ui.inflate('kiosk_videos:main'))
		self.binder = Binder(self, self)
		self.binder.populate()

	@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_videos':
			enable_videos = "X-GNOME-Autostart-enabled=%s" % str(v).lower()
		    if k == 'video_volume':
			video_volume = v.lower()
		
		if enable_videos == "X-GNOME-Autostart-enabled=true":
		    ajenti_config = "/etc/ajenti/config.json"
		    
		    #Disable Browser Mode
		    subprocess.call(['sed', '-i', r's/\\"enable_browser\\": true/\\"enable_browser\\": 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-browser.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=/home/kiosk/.kiosk/videos.sh %s\n"
		    "Hidden=false\n"
		    "NoDisplay=false\n"
		    "%s\n"
		    "Name[en_US]=2-videos\n"
		    "Name=2-videos\n"
		    "Comment[en_US]=\n"
		    "Comment=") % (video_volume, enable_videos)
		    		    
		open('/home/kiosk/.config/autostart/2-videos.desktop', 'w').write(cfg) #save
Пример #9
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
Пример #10
0
class SanickioskScreensaverPrefs (SectionPlugin):
	default_classconfig = {
		'photos_enable': False,
	}
	classconfig_root = True

	def init(self):
		self.title = 'Режим Снимки'
		self.icon = 'picture'
		self.category = 'Kiosk'

		self.append(self.ui.inflate('kiosk_photos:main'))
		self.binder = Binder(self, self)
		self.binder.populate()

	@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 == 'photos_enable':
				photos_enable = "X-GNOME-Autostart-enabled=%s" % str(v).lower()
        
        	if photos_enable == "X-GNOME-Autostart-enabled=true":
			ajenti_config = "/etc/ajenti/config.json"
		
		#Disable Browser Mode
            	subprocess.call(['sed', '-i', r's/\\"enable_browser\\": true/\\"enable_browser\\": 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-browser.desktop"])
            
            	#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"])
            
        	cfg = ("[Desktop Entry]\n"
		"Type=Application\n"
            	"Exec=feh --recursive --quiet --randomize --full-screen --borderless --reload 300 --slideshow-delay 10 --no-menus --auto-zoom --hide-pointer /home/kiosk/Photos/\n"
            	"Hidden=false\n"
            	"NoDisplay=false\n"
            	"%s\n"
            	"Name[en_US]=2-photos\n"
            	"Name=2-photos\n"
            	"Comment[en_US]=\n"
            	"Comment=") % (photos_enable)
            
        	open('/home/kiosk/.config/autostart/2-photos.desktop', 'w').write(cfg) #save
Пример #11
0
class Dnsmasq(SectionPlugin):
    def init(self):
        self.icon = 'globe'
        self.title = 'Dnsmasq'
        self.category = _('Software')

        self.append(self.ui.inflate('dnsmasq:main'))
        self.leases = DnsmasqLeases()
        self.binder = Binder(self.leases, self.find('main'))
        self.binder.populate()


    @on('refresh', 'click')
    def refresh(self):
        self.leases.update()
        self.binder.populate()
Пример #12
0
class MailPlugin(SectionPlugin):

    def init(self):
        # meta-data
        self.title = _('Mail')
        self.icon = 'envelope'
        self.category = _("Software")

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

    def on_first_page_load(self):
        username = pwd.getpwuid(os.getuid()).pw_name
        self.mbox = mailbox.mbox('/var/mail/%s' % username, factory=message_factory(mailbox.mboxMessage))
        self.binder = Binder(self, self.find('main'))
        self.binder.populate()

    @on('refresh', 'click')
    def refresh(self):
        self.binder.populate()
Пример #13
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()
Пример #14
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.binder.setup(self).populate()
        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.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()
Пример #15
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))
Пример #16
0
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')
        self.find('dialog').buttons = [
            {'id': 'save', 'text': _('Save')},
            {'id': 'cancel', 'text': _('Cancel')},
        ]

    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):
        os.mkdir(os.path.join(self.controller.tabs[self.tabs.active].path, 'new directory'))
        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()

    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()
Пример #17
0
class SanickioskScreensaverPrefs(SectionPlugin):
    default_classconfig = {
        'home_url': 'http://sanickiosk.org',
        'kioskspeeddial': False,
        'kioskmode': True,
        'fullscreen': True,
        'browser_reset': True,
        'browser_idle': '2',
        'nokeys': False,
        'nocontextmenu': True,
        'nomenu': True,
        'nodownload': True,
        'noprint': True,
        'nomaillinks': True,
        'disable_config_url': True,
        'empty_on_exit': True,
        'accept_cookies_session_only': True,
        'hide_toolbar': False,
        'hide_home': False,
        'hide_back': False,
        'hide_forward': False,
        'hide_reload': False,
        'hide_addressbar': False,
        'hide_find': False,
        'hide_zoom': False,
        'hide_ppreview': True,
        'hide_print': True,
        'hide_reset': False,
        'custom_user_agent': '',
    }
    classconfig_root = True

    def init(self):
        self.title = 'Browser'
        self.icon = 'globe'
        self.category = 'Sanickiosk'

        self.append(self.ui.inflate('sanickiosk_browser:main'))
        self.binder = Binder(self, self)
        self.binder.populate()

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.save_classconfig()
        self.context.notify(
            'info',
            _('Saved. Please restart Sanickiosk for changes to take effect.'))
        self.binder.populate()

        all_vars = '\n'.join(
            [k + '="' + str(v) + '"' for k, v in self.classconfig.iteritems()])
        open('/home/kiosk/.sanickiosk/browser.cfg', 'w').write(all_vars)  #save

    @on('speeddial_edit', 'click')
    def speeddial_edit(self):
        self.context.launch('notepad', path='/home/kiosk/.opera/speeddial.sav')

    @on('filters_edit', 'click')
    def filters_edit(self):
        self.context.launch('notepad', path='/home/kiosk/.opera/urlfilter.ini')
Пример #18
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()
            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])

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

        self.refresh()

    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
        path = self.find('fake-ssl-path').value
        if host == '':
            self.context.notify('error', 'Please supply hostname')
        elif not os.path.exists(path):
            self.context.notify('error', 'Please supply valid path')
        else:
            self.gen_ssl(host, path.rstrip('/'))

    @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, path):
        self.save()
        ajenti.config.tree.ssl.enable = True
        ajenti.config.tree.ssl.certificate_path = '%s/ajenti.pem' % path
        ajenti.config.save()
        self.refresh()

        script = """
            echo '\n-> Generating key\n';
            openssl genrsa -des3 -out /tmp/ajenti.key -passout pass:1234 2048;
            echo '\n-> Generating certificate request\n';
            openssl req -new -key /tmp/ajenti.key -out /tmp/ajenti.csr -passin pass:1234 -subj /C=US/ST=NA/L=Nowhere/O=Acme\\ Inc/OU=IT/CN={0}/;
            echo '\n-> Removing passphrase\n';
            cp /tmp/ajenti.key /tmp/ajenti.key.org;
            openssl rsa -in /tmp/ajenti.key.org -out /tmp/ajenti.key -passin pass:1234;
            echo '\n-> Generating certificate\n';
            openssl x509 -req -days 365 -in /tmp/ajenti.csr -signkey /tmp/ajenti.key -out /tmp/ajenti.crt -passin pass:1234;
            cat /tmp/ajenti.key /tmp/ajenti.crt > {1}/ajenti.pem;
            rm /tmp/ajenti.*;
            echo '\n\n===================\nRestart Ajenti to apply changes!\n===================';
        """.format(host, path)
        self.context.launch('terminal', command=script)
Пример #19
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 log(self, tolog):
        file = open(self.pwd+ '/' + "log.txt" , 'a')
        file.write('\n' + str(tolog) )
        file.close()

    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'
        file.write(template)
        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/dehydrated.sh', '-c']
        self.log(params[0])
        if self.find('renewal').value:
            params.append('--force')

        try:
            p = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            out, err = p.communicate()
        except NameError as ex:
            self.log( str(type(ex)) )
            self.log( str(ex.message) )
            self.log( str(ex.args) )
            self.log( str(ex) )
            self.log( traceback.print_exc() )
            self.context.notify('info', 'An error occured! Please check the logs')
            return

        if out:
            self.context.notify('info', 'OUT: ' + out)
        if err:
            self.log(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()
Пример #20
0
class FileManager (SectionPlugin):
    default_classconfig = {'root': '/', 'start': '/'}
    classconfig_editor = FileManagerConfigEditor
    classconfig_root = True

    def init(self):
        self.title = _('Файлов мениджър')
        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()
Пример #21
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:
Пример #22
0
class MpdPlugin(SectionPlugin):
    default_classconfig = {'host': '127.0.0.1', 'port': 6600}
    classconfig_editor = MpdPluginConfigurator

    def bindui(self, ui_id, method_name):
        def decorator(method):
            setattr(self.find(ui_id), method_name, method)
            return method
        return decorator

    def init(self):
        self._mpd = MPD(**self.classconfig)

        # meta-data
        self.title = 'MPD'
        self.icon = 'music'
        self.category = _("Software")

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

        # data-bindings
        self.status = Status.EMPTY
        self.song = Song.EMPTY

        self.playlist = []
        self.playlists = []
        self.outputs = []

        self.taxonomy = Taxonomy.EMPTY
        self.library = []

        self.init_ui_bindings()


    def init_ui_bindings(self):
        @self.bindui('playlist', 'post_item_bind')
        def post_item_bind(obj, collection, item, ui):
            ui.find('play').on('click', self.play, item)

        @self.bindui('playlist', 'delete_item')
        def delete_item(item, collection):
            self.remove(item)

        @self.bindui('playlists', 'add_item')
        def add_playlist(item, collection):
            for i in count(1):
                try:
                    self._mpd.do('save', 'Untitled %d' % i)
                except CommandError:
                    continue
                else:
                    break

            self.refresh()

        @self.bindui('playlists', 'delete_item')
        def delete_playlist(item, collection):
            self._mpd.do('rm', item.playlist)
            self.refresh()

        @self.bindui('playlists', 'post_item_bind')
        def post_playlist_bind(obj, collection, item, ui):
            ui.find('load').on('click', lambda *args: self._mpd.do(*args) or self.refresh(), 'load', item.playlist)
            #ui.find('clear').on('click', self._mpd.do, 'playlistclear', item.playlist)

        @self.bindui('outputs', 'post_item_bind')
        def post_output_bind(obj, collection, item, ui):
            ui.find('enabled').on('click', self.toggleoutput, item)

        @self.bindui('library', 'post_item_bind')
        def post_library_bind(obj, collection, item, ui):
            ui.find('add').on('click', self.add, item.file)

    @on('tabs', 'switch')
    def tab_switch(self):
        if self.find('tabs').active == 2:  # library tab
            self.taxonomy = Taxonomy(izip(
                        ('artists', 'albums', 'genres'),
                        self._mpd.bulk_do([
                            ('list', 'artist'),
                            ('list', 'album'),
                            ('list', 'genre')
                            ], defaults=([], [], []))))
            self.binder.populate()


    @on('search', 'click')
    def search(self, add=False):
        self.binder.update()

        filter = []
        for f in ('artist', 'album', 'genre'):
            if self.taxonomy[f] is not None:
                filter.append(f)
                filter.append(self.taxonomy[f])

        if add and not filter:
            self.context.notify('error', _('Can not add all library! Select some filters first.'))
            return

        self.library = map(Song, (self._mpd.do('findadd' if add else 'find', *filter) or []) if filter
                else ifilter(lambda s: 'file' in s, self._mpd.do('listallinfo') or []))

        self.binder.populate()

    @on('searchadd', 'click')
    def searchadd(self):
        self.search(add=True)
        self.refresh()

    @on('rename', 'click')
    def rename_playlists(self):
        old_names = map(lambda p: p.playlist, self.playlists)
        self.binder.update()
        new_names = map(lambda p: p.playlist, self.playlists)

        self._mpd.bulk_do(
                imap(lambda p: ('rename',) + p,
                    ifilter(lambda p: p[0] != p[1],
                        izip(old_names, new_names))))

        self.refresh()


    def on_first_page_load(self):
        self.binder = Binder(self, self.find('mpd'))
        self.refresh()
        self.context.session.spawn(self.worker)

    def worker(self):
        waiter = MPD()
        connected = True

        while True:
            events = waiter.wait((
                MPD.EV_QUEUE_CHANGED,
                MPD.EV_PLAYLIST_CHANGED,
                MPD.EV_VOLUME_CHANGED,
                MPD.EV_OPTIONS_CHANGED,
                MPD.EV_PLAYER_CHANGED,
                MPD.EV_OUTPUT_CHANGED))

            if events is None:
                if connected:
                    self.context.notify('error', 'Could not connect to MPD!')
                    self.context.launch('configure-plugin', plugin=self)
                    connected = False

                sleep(10)

            else:
                connected = True
                self.refresh(events)

    def add(self, *urls):
        if not urls:
            return

        def readfile(url):
            with closing(urlopen(url) if url.startswith(('http://', 'https://')) else open(url, 'r')) as f:
                return f.read().splitlines()

        clean_playlist = lambda lines: ifilter(None, imap(str.strip, imap(str, lines)))
        parse_null = lambda url: (url,)

        parsers = {
                '.m3u': lambda url: ifilter(lambda line: not line.startswith('#'), readfile(url)),
                '.pls': lambda url: imap(lambda line: line.split('=')[1], ifilter(lambda line: line.startswith('File'), readfile(url))),
                }

        urls = flatten(imap(lambda url: clean_playlist(parsers.get(os.path.splitext(url)[1], parse_null)(url)), urls))

        cmds = imap(lambda url: ('addid', url), urls)

        try:
            self._mpd.bulk_do(cmds)

        except CommandError:
            self.context.notify('error', _('Songs not found'))

        else:
            self.refresh()

    @on('consume', 'click')
    def toggleconsume(self):
        self._mpd.do('consume', int(not self.status.consume))
        self.refresh()

    @on('single', 'click')
    def togglesingle(self):
        self._mpd.do('single', int(not self.status.single))
        self.refresh()

    @on('random', 'click')
    def togglerandom(self):
        self._mpd.do('random', int(not self.status.random))
        self.refresh()

    @on('repeat', 'click')
    def togglerepeat(self):
        self._mpd.do('repeat', int(not self.status.repeat))
        self.refresh()

    @on('add', 'click')
    def open_add_dialog(self):
        self.find('add_dialog').visible = True

    @on('add_dialog', 'button')
    def submit_add_dialog(self, button):
        dialog = self.find('add_dialog')
        dialog.visible = False
        if button == 'add':
            self.add(*dialog.find('new_song_url').value.strip().splitlines())

    @on('refresh', 'click')
    def refresh(self, areas=()):
        if not areas:
            update = ['playlistinfo', 'status', 'currentsong', 'listplaylists', 'outputs']
            defaults = [[], Status.EMPTY, Song.EMPTY, [], []]

        else:
            update = list(set(ifilter(bool, flatten(
                ('playlistinfo',) if area in (MPD.EV_QUEUE_CHANGED,) else
                ('listplaylists',) if area in (MPD.EV_PLAYLIST_CHANGED,) else
                ('status',) if area in (MPD.EV_VOLUME_CHANGED, MPD.EV_OPTIONS_CHANGED) else
                ('status', 'currentsong') if area in (MPD.EV_PLAYER_CHANGED,) else
                ('outputs',) if area in (MPD.EV_OUTPUT_CHANGED,) else
                None
                for area in areas))))

            defaults = map(lambda n: {} if n in ('status', 'currentsong') else [], update)

        data = UpdateInfo(izip(update,
            self._mpd.bulk_do(*update, defaults=defaults)))

        for key in update:
            setattr(self, {
                'playlistinfo': 'playlist',
                'listplaylists': 'playlists',
                'currentsong': 'song',
                }.get(key, key),
                getattr(data, key))

        if 'status' in update:
            # reset icons if not all playlist is to be updated
            if 'playlistinfo' not in update:
                for song in self.playlist:
                    song.icon = 'music'

            try:
                if self.status.state == 'play':
                    self.find('play').visible = False
                    self.find('pause').visible = True
                    self.playlist[self.status.song].icon = 'play'

                else:
                    self.find('play').visible = True
                    self.find('pause').visible = False

            except AttributeError:
                pass

        self.binder.populate()

    def toggleoutput(self, output):
        self._mpd.do('disableoutput' if output.outputenabled else 'enableoutput', output.outputid)
        self.refresh()

    @on('voldown', 'click')
    def voldown(self, delta=10):
        self._mpd.do('volume', -delta)
        self.refresh()

    @on('volup', 'click')
    def volup(self, delta=10):
        self._mpd.do('volume', delta)
        self.refresh()

    _last_volume = 0
    @on('mute', 'click')
    def mute(self):
        if self.status.volume == 0:
            self.volume(self._last_volume)
        else:
            self._last_volume = self.status.volume
            self.volume(0)

    def volume(self, value):
        self._mpd.do('setvol', value)
        self.refresh()

    def remove(self, song):
        self._mpd.do('deleteid', song.id)
        self.refresh()

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

    @on('update', 'click')
    def update(self):
        num = self._mpd.do('update')
        if num:
            self.context.notify('info', _('Update #%s started...') % num)

    @on('play', 'click')
    def play(self, song=None):
        if song is None:
            self._mpd.do('play')
        else:
            self._mpd.do('playid', song.id)

        self.refresh()

    @on('pause', 'click')
    def pause(self):
        self._mpd.do('pause')
        self.refresh()

    @on('stop', 'click')
    def stop(self):
        self._mpd.do('stop')
        self.refresh()

    @on('prev', 'click')
    def prev(self):
        self._mpd.do('previous')
        self.refresh()

    @on('next', 'click')
    def next(self):
        self._mpd.do('next')
        self.refresh()

    @on('clear', 'click')
    def clear(self):
        self._mpd.do('clear')
        self.refresh()
Пример #23
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()
            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])
        self.find('users').post_item_update = post_user_update

        self.refresh()

    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
        path = self.find('fake-ssl-path').value
        if host == '':
            self.context.notify('error', 'Please supply hostname')
        elif not os.path.exists(path):
            self.context.notify('error', 'Please supply valid path')
        else:
            self.gen_ssl(host, path.rstrip('/'))

    @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, path):
        self.save()
        ajenti.config.tree.ssl.enable = True
        ajenti.config.tree.ssl.certificate_path = '%s/ajenti.pem' % path
        ajenti.config.save()
        self.refresh()

        script = """
            echo '\n-> Generating key\n';
            openssl genrsa -des3 -out /tmp/ajenti.key -passout pass:1234 2048;
            echo '\n-> Generating certificate request\n';
            openssl req -new -key /tmp/ajenti.key -out /tmp/ajenti.csr -passin pass:1234 -subj /C=US/ST=NA/L=Nowhere/O=Acme\\ Inc/OU=IT/CN={0}/;
            echo '\n-> Removing passphrase\n';
            cp /tmp/ajenti.key /tmp/ajenti.key.org;
            openssl rsa -in /tmp/ajenti.key.org -out /tmp/ajenti.key -passin pass:1234;
            echo '\n-> Generating certificate\n';
            openssl x509 -req -days 365 -in /tmp/ajenti.csr -signkey /tmp/ajenti.key -out /tmp/ajenti.crt -passin pass:1234;
            cat /tmp/ajenti.key /tmp/ajenti.crt > {1}/ajenti.pem;
            rm /tmp/ajenti.*;
            echo '\n\n===================\nRestart Ajenti to apply changes!\n===================';
        """.format(host, path)
        self.context.launch('terminal', command=script)
Пример #24
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()
Пример #25
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'))
Пример #26
0
class Hosts (SectionPlugin):
    def init(self):
        self.title = _('Instance Manager')
        self.icon = 'sitemap'
        self.category = _('System')

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

	def post_item_bind(object, collection, item, ui):
		ui.find('terminate').on('click', self.on_terminate, item.name)
		ui.find('start').on('click', self.on_start, item.name)
		ui.find('stop').on('click', self.on_stop, item.name)
		ui.find('freeze').on('click', self.on_freeze, item.name)
		ui.find('unfreeze').on('click', self.on_unfreeze, item.name)		
		ui.find('terminal').on('click', self.on_terminal, item.name)
                ui.find('backup').on('click', self.on_backup, item.name)
                ui.find('config').on('click', self.on_config, item.name)

		ui.find('terminate').visible = not item.params['up']
		ui.find('config').visible = not item.params['up']
		ui.find('start').visible = not item.params['up']
		ui.find('stop').visible = item.params['up'] and not item.params['fz']
		ui.find('freeze').visible = not item.params['fz'] and item.params['up']
		ui.find('unfreeze').visible = item.params['fz'] and item.params['up']
		ui.find('terminal').visible = not item.params['fz'] and item.params['up']
                ui.find('backup').visible = item.params['fz'] and item.params['up']

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

        self.obj_collection = self.listg()

	self.binder = Binder(self,self)
    def on_page_load(self):
        self.refresh()


    @on('refresh', 'click')
    def on_refresh(self):
        self.refresh()

    @on('create', 'click')
    def on_create(self):
        self.find('input-create').visible = True

    @on('network', 'click')
    def on_network(self):
        self.context.launch('notepad', path='/etc/default/lxc-net')
        
    def on_terminate(self, value):
        self.destroy(value)
	self.refresh()
    def on_start(self, value):
        self.start(value)
        self.refresh()

    def on_stop(self, value):
        self.stop(value)
        self.refresh()
    def on_freeze(self, value):
        self.freeze(value)
        self.refresh()
    def on_unfreeze(self, value):
        self.unfreeze(value)
        self.refresh()
    def on_terminal(self, value):
	cmd = 'lxc-attach -qn {} '.format(value)
	self.context.launch('terminal',command=cmd)
    def on_backup(self, value):
        path = self.backup(value)
	#self.context.notify('Backup Completed', 'Your backup for {} instance is stored at {}'.format(value,path))
	self.context.notify('Backup Completed',path)
    def on_config(self, value):
        configpath = '/var/lib/lxc/{}/config'.format(value)
        self.context.launch('notepad', path=configpath)
        
    @on('input-create', 'submit')
    def on_input_create(self, value):
	self.create(value)
        self.refresh()

    def refresh(self):
	self.obj_collection = self.listg()
        self.binder.update()
        self.binder.populate()
        return

    def listg(self):
            """
            List all containers with status (Running, Frozen or Stopped) in a dict
            Same as lxc-list or lxc-ls --fancy (0.9)
            """
            status_container = {}
	    output_list = []

            outcmd = self.run('lxc-ls --fancy | tail -n+3', output=True).splitlines()

            for line in outcmd:
                status_container[line.split()[0]] = line.split()[1:]


            for container in self.ls():
		cont_mem = '{} MB'.format(self.memory_usage(container))
                if status_container[container][0] == 'RUNNING':
		     output_list.append(CContainer(container, status='Running',ip=status_container[container][1],mem=cont_mem,up=1,fz=0))
                elif status_container[container][0] == 'STOPPED':
                     output_list.append(CContainer(container, status='Stopped',ip='-',mem=cont_mem,up=0,fz=1))
                elif status_container[container][0] == 'FROZEN':
                     output_list.append(CContainer(container, status='Frozen',ip=status_container[container][1],mem=cont_mem,up=1,fz=1))

            return output_list

    def memory_usage(self,name):
	    """
	    returns memory usage in MB
	    """
	    outcmd = self.run('lxc-cgroup -n {} memory.usage_in_bytes'.format(name), output=True)
	    return int(int(outcmd) / 1024 / 1024)

    def run(self,cmd, output=False):
	    """
	    To run command easier
	    """
	    if output:
	        try:
	            out = subprocess.check_output('{}'.format(cmd), shell=True, close_fds=True)
	        except subprocess.CalledProcessError:
	            out = False
	        return out
	    return subprocess.check_call('{}'.format(cmd), shell=True, close_fds=True)  # returns 0 for True


    def ls(self):
	    """
	    List containers directory
	    """
	    lxc_dir = self.lxcdir()
	    ct_list = []

	    try:
	        lsdir = os.listdir(lxc_dir)
	        for i in lsdir:
	            # ensure that we have a valid path and config file
	            if os.path.isdir('{}/{}'.format(lxc_dir, i)) and os.path.isfile(('{}/{}/config'.format(lxc_dir, i))):
	                ct_list.append(i)
	    except OSError:
	        ct_list = []
	    return sorted(ct_list)

    def lxcdir(self):
	    return self.run('lxc-config lxc.lxcpath', output=True).strip()


    def list_status(self):
	    """
	    List all containers with status (Running, Frozen or Stopped) in a dict
	    """
	    containers = []

	    for container in self.ls():
	        state = self.ct_info(container)['state']
	        # TODO: figure out why pycharm thinks state is an int
	        containers.append(dict(container=container, state=state.lower()))
	    return containers


    def ct_info(self, container):
	    if self.exists(container):
	        return 0
	    output = self.run('lxc-info -qn {}'.format(container), output=True).splitlines()

	    state = {'pid': 0}
	    for val in output:
	        state[val.split(':')[0].lower().strip().replace(" ", "_")] = val.split(':')[1].strip()

	    return state

    def exists(self, container):
	    """
	    Check if container exists
	    """
	    if container in self.ls():
	        return True
	    return False

    def create(self, container, template='ubuntu'):
	    """
	    Create a container (without all options)
	    Default template: Ubuntu
	    """
	    if self.exists(container):
	        return 0

	    command = 'lxc-create -n {}'.format(container)
	    command += ' -t {}'.format(template)

	    return self.run(command)

    def destroy(self,container):
	    """
	    Destroys a container
	    """
	    if not self.exists(container):
	        return 0
	    return self.run('lxc-destroy -n {}'.format(container))

    def start(self,container):
	    """
	    Starts a container
	    """
	    if not self.exists(container):
	        return 0
	    return self.run('lxc-start -dn {}'.format(container))

    def stop(self,container):
	    """
	    Stops a container
	    """
	    if not self.exists(container):
	        return 0
	    return self.run('lxc-stop -n {}'.format(container))

    def freeze(self,container):
	    """
	    Freezes a container
	    """
            if not self.exists(container):
                return 0
	    return self.run('lxc-freeze -n {}'.format(container))

    def unfreeze(self,container):
	    """
	    Unfreezes a container
	    """
            if not self.exists(container):
                return 0
	    return self.run('lxc-unfreeze -n {}'.format(container))

    def backup(self, container,  destination='/var/lxc-backup/'):
	    """
	    Backup container with tar to a storage repository (SR).
	    If SR is localy then the path is /var/lxc-backup/
	    Returns path/filename of the backup instances
	    """
	    prefix = time.strftime("%Y-%m-%d__%H-%M.tar.gz")
	    filename = '{}/{}-{}'.format(destination, container, prefix)
	    if not self.exists(container):
	        return 0
	    if not os.path.isdir(destination):
	        self.run('mkdir -p {}'.format(destination))
	    self.run('tar czf {} -C /var/lib/lxc {}'.format(filename, container))
	    return filename
Пример #27
0
class WebsiteEditorPlugin (SectionPlugin):
    def init(self):
        self.title = 'Website editor'
        self.icon = 'globe'
        self.category = 'Web'
        self.hidden = True

        self.manager = VHManager.get()
        self.binder = Binder(None, self)

        self.append(self.ui.inflate('vh:main-website'))
        self.find('domains').new_item = lambda c: WebsiteDomain.create('example.com')
        self.find('ports').new_item = lambda c: WebsitePort.create(80)

        def post_location_bind(object, collection, item, ui):
            ui.find('backend-params').empty()
            ui.find('backend-params').append(self.ui.inflate('vh:main-backend-params-%s' % item.backend.type))
            item.backend.__binder = Binder(item.backend, ui.find('backend-params'))
            item.backend.__binder.populate()

        def post_location_update(object, collection, item, ui):
            item.backend.__binder.update()

        self.find('locations').post_item_bind = post_location_bind
        self.find('locations').post_item_update = post_location_update

        self.find('create-location-type').labels = []
        self.find('create-location-type').values = []
        for g in sorted(ApplicationGatewayComponent.get_classes(), key=lambda x: x.title):
            self.find('create-location-type').labels.append(g.title)
            self.find('create-location-type').values.append(g.id)

    @intent('v:manage-website')
    def on_launch(self, website=None):
        self.activate()
        self.website = website
        self.binder.setup(self.website)
        self.binder.populate()

        for ext in BaseExtension.get_classes():
            ext.selftest()

        extensions = BaseExtension.get_classes()

        def create_location():
            self.binder.update()
            t = self.find('create-location-type').value
            l = WebsiteLocation.create(self.website, template=t)
            l.backend.type = t
            self.website.locations.append(l)
            self.refresh()
        self.find('create-location').on('click', create_location)

        # Extensions
        for tab in list(self.find('tabs').children):
            if hasattr(tab, '-is-extension'):
                tab.delete()

        self.website.extensions = []
        for ext in extensions:
            ext = ext.new(self.ui, self.website, config=self.website.extension_configs.get(ext.classname, None))
            ext._ui_container = self.ui.create('tab', children=[ext], title=ext.name)
            setattr(ext._ui_container, '-is-extension', True)
            self.website.extensions.append(ext)
            self.find('tabs').append(ext._ui_container)

        # Root creator
        self.find('root-not-created').visible = not os.path.exists(self.website.root)

        def create_root():
            self.binder.update()
            try:
                os.mkdir(self.website.root)
            except:
                pass
            subprocess.call(['chown', 'www-data', self.website.root])
            self.save()

        self.find('create-root-directory').on('click', create_root)
        self.find('set-path').on('click', self.save)

        # Downloader

        def download():
            url = self.find('download-url').value
            self.save()
            tmppath = '/tmp/ajenti-v-download'
            script = 'wget "%s" -O "%s" ' % (url, tmppath)
            if url.lower().endswith('.tar.gz') or url.lower().endswith('.tgz'):
                script += '&& tar xf "%s" -C "%s"' % (tmppath, self.website.root)
            elif url.lower().endswith('.zip'):
                script += '&& unzip "%s" -d "%s"' % (tmppath, self.website.root)

            script += ' && chown www-data -R "%s"' % self.website.root
            script += ' && find "%s" -type d -exec chmod 775 {} ";"' % self.website.root
            script += ' && find "%s" -type f -exec chmod 644 {} ";"' % self.website.root

            def callback():
                self.save()
                self.activate()
                if os.path.exists(tmppath):
                    os.unlink(tmppath)
                self.context.notify('info', _('Download complete'))

            self.context.launch('terminal', command=script, callback=callback)

        self.find('download').on('click', download)

    @on('go-back', 'click')
    def on_go_back(self):
        WebsitesPlugin.get().activate()

    @on('destroy', 'click')
    def on_destroy(self):
        for ext in self.website.extensions:
            try:
                ext.on_destroy()
            except Exception, e:
                logging.error(str(e))
        self.manager.config.websites.remove(self.website)
        self.save()
        self.on_go_back()
Пример #28
0
Файл: fm.py Проект: nnpro/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()
        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")}]

    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):
        os.mkdir(os.path.join(self.controller.tabs[self.tabs.active].path, "new directory"))
        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)

        if for_move:
            self.backend.move(for_move, tab.path)
        if for_copy:
            self.backend.copy(for_copy, tab.path)
        self.clipboard = []
        self.refresh_clipboard()
        self.refresh()

    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()

    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()
Пример #29
0
class FileManager(SectionPlugin):
    default_classconfig = {"root": "/", "start": "/"}
    classconfig_editor = FileManagerConfigEditor
    classconfig_root = True

    def init(self):
        self.title = _("Файлов мениджър")
        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()
Пример #30
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")
Пример #31
0
class WebsitesPlugin(SectionPlugin):
    def init(self):
        self.title = _('Websites')
        self.icon = 'globe'
        self.category = 'Web'
        self.order = 1

        self.manager = VHManager.get()

        if not self.manager.is_configured:
            from ajenti.plugins.vh import destroyed_configs
            self.append(self.ui.inflate('vh:not-configured'))
            self.find('destroyed-configs').text = ', '.join(destroyed_configs)
        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:main'))

        self.binder = Binder(None, self)

        def post_ws_bind(object, collection, item, ui):
            def manage():
                self.context.launch('v:manage-website', website=item)

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

        self.find('websites').post_item_bind = post_ws_bind
        self.find(
            'websites').filter = lambda ws: self.context.session.identity in [
                'root', ws.owner
            ]

        self.binder.setup(self.manager)

    @on('new-website', 'click')
    def on_new_website(self):
        self.binder.update()
        name = self.find('new-website-name').value
        self.find('new-website-name').value = ''
        if not name:
            name = '_'

        slug = slugify(name)
        slugs = [x.slug for x in self.manager.config.websites]
        while slug in slugs:
            slug += '_'

        w = Website.create(name)
        w.slug = slug
        w.owner = self.context.session.identity
        self.manager.config.websites.append(w)
        self.manager.save()
        self.binder.populate()

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        if self.manager.is_configured:
            self.manager.config.websites = sorted(self.manager.config.websites,
                                                  key=lambda x: x.name)
            self.binder.setup().populate()

    @on('recheck', 'click')
    def on_recheck(self):
        self.binder.update()
        self.context.endpoint.send_progress(_('Testing configuration'))
        try:
            self.manager.run_checks()
        finally:
            self.context.endpoint.send_progress(None)
            self.refresh()

    @on('save', 'click')
    def save(self):
        self.context.endpoint.send_progress(_('Saving changes'))
        self.binder.update()
        self.manager.save()
        self.context.endpoint.send_progress(_('Applying changes'))
        self.manager.update_configuration()
        self.context.endpoint.send_progress(_('Restarting web services'))
        self.manager.restart_services()
        gevent.spawn(self.on_recheck)
        self.refresh()
        self.context.notify('info', _('Saved'))
Пример #32
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')

        self.binder.reset(self.config.tree)
        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.autodiscover().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='/etc/iptables.up.rules')

    @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'))
Пример #33
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 as e:
            self.context.notify('error', str(e))
Пример #34
0
class WebsitesPlugin (SectionPlugin):
    def init(self):
        self.title = _('Websites')
        self.icon = 'globe'
        self.category = 'Web'

        self.manager = VHManager.get()

        if not self.manager.is_configured:
            from ajenti.plugins.vh import destroyed_configs
            self.append(self.ui.inflate('vh:not-configured'))
            self.find('destroyed-configs').text = ', '.join(destroyed_configs)
        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:main'))

        self.binder = Binder(None, self)

        def post_ws_bind(object, collection, item, ui):
            def manage():
                self.context.launch('v:manage-website', website=item)
            ui.find('manage').on('click', manage)

        self.find('websites').post_item_bind = post_ws_bind
        self.find('websites').filter = lambda ws: self.context.session.identity in ['root', ws.owner]

        self.binder.setup(self.manager)

    @on('new-website', 'click')
    def on_new_website(self):
        self.binder.update()
        name = self.find('new-website-name').value
        self.find('new-website-name').value = ''
        if not name:
            name = '_'

        slug = slugify(name)
        slugs = [x.slug for x in self.manager.config.websites]
        while slug in slugs:
            slug += '_'

        w = Website.create(name)
        w.slug = slug
        w.owner = self.context.session.identity
        self.manager.config.websites.append(w)
        self.manager.save()
        self.binder.populate()

    def on_page_load(self):
        self.refresh()

    def refresh(self):
        if self.manager.is_configured:
            self.binder.setup().populate()

    @on('recheck', 'click')
    def on_recheck(self):
        self.context.endpoint.send_progress(_('Saving changes'))
        self.binder.update()
        self.manager.save()
        self.context.endpoint.send_progress(_('Testing configuration'))
        self.manager.run_checks()
        self.refresh()

    @on('save', 'click')
    def save(self):
        self.context.endpoint.send_progress(_('Saving changes'))
        self.binder.update()
        self.manager.save()
        self.context.endpoint.send_progress(_('Applying changes'))
        self.manager.update_configuration()
        self.context.endpoint.send_progress(_('Restarting web services'))
        self.manager.restart_services()
        self.context.endpoint.send_progress(_('Testing configuration'))
        self.manager.run_checks()
        self.refresh()
        self.context.notify('info', _('Saved'))
Пример #35
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

        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; sp=r"\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"))
Пример #36
0
class WebsitesWebsiteEditorPlugin(SectionPlugin):
    uses_access_permission_of = WebsitesPlugin

    def init(self):
        self.title = 'Website editor'
        self.icon = 'globe'
        self.category = 'Web'
        self.order = 2
        self.hidden = True

        self.manager = VHManager.get()
        self.binder = Binder(None, self)

        self.append(self.ui.inflate('vh:main-website'))
        self.find(
            'domains').new_item = lambda c: WebsiteDomain.create('example.com')
        self.find('ports').new_item = lambda c: WebsitePort.create(80)

        def post_location_bind(object, collection, item, ui):
            ui.find('backend-params').empty()
            ui.find('backend-params').append(
                self.ui.inflate('vh:main-backend-params-%s' %
                                item.backend.type))
            item.backend.__binder = Binder(item.backend,
                                           ui.find('backend-params'))
            item.backend.__binder.populate()

        def post_location_update(object, collection, item, ui):
            item.backend.__binder.update()

        self.find('locations').post_item_bind = post_location_bind
        self.find('locations').post_item_update = post_location_update

        self.find('create-location-type').labels = []
        self.find('create-location-type').values = []
        for g in sorted(ApplicationGatewayComponent.get_classes(),
                        key=lambda x: x.title):
            self.find('create-location-type').labels.append(g.title)
            self.find('create-location-type').values.append(g.id)

    @intent('v:manage-website')
    def on_launch(self, website=None):
        self.activate()
        self.website = website
        self.binder.setup(self.website)
        self.binder.populate()

        for ext in BaseExtension.get_classes():
            ext.selftest()

        extensions = BaseExtension.get_classes()

        def create_location():
            self.binder.update()
            t = self.find('create-location-type').value
            l = WebsiteLocation.create(self.website, template=t)
            l.backend.type = t
            self.website.locations.append(l)
            self.refresh()

        self.find('create-location').on('click', create_location)

        # Extensions
        for tab in list(self.find('tabs').children):
            if hasattr(tab, '-is-extension'):
                tab.delete()

        self.website.extensions = []
        for ext in extensions:
            ext = ext.new(self.ui,
                          self.website,
                          config=self.website.extension_configs.get(
                              ext.classname, None))
            ext.editor_ui = self
            ext._ui_container = self.ui.create('tab',
                                               children=[ext],
                                               title=ext.name)
            setattr(ext._ui_container, '-is-extension', True)
            self.website.extensions.append(ext)
            self.find('tabs').append(ext._ui_container)

        # Root creator
        self.find('root-not-created').visible = not os.path.exists(
            self.website.root)

        def create_root():
            self.binder.update()
            if not os.path.exists(self.website.root):
                os.makedirs(self.website.root)
            subprocess.call(['chown', '-R', 'www-data:', self.website.root])
            self.save()

        self.find('create-root-directory').on('click', create_root)
        self.find('fix-root-permissions').on('click', create_root)
        self.find('set-path').on('click', self.save)

        # Downloader

        def download():
            url = self.find('download-url').value
            self.save()
            tmppath = '/tmp/ajenti-v-download'
            script = 'wget "%s" -O "%s" ' % (url, tmppath)
            if url.lower().endswith(
                ('tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz2')):
                script += '&& tar xf "%s" -C "%s"' % (tmppath,
                                                      self.website.root)
            elif url.lower().endswith('.rar'):
                script += '&& unrar x "%s" "%s"' % (tmppath, self.website.root)
            elif url.lower().endswith('.zip'):
                script += '&& unzip "%s" -d "%s"' % (tmppath,
                                                     self.website.root)

            script += ' && chown www-data: -R "%s"' % self.website.root
            script += ' && find "%s" -type d -exec chmod 775 {} ";"' % self.website.root
            script += ' && find "%s" -type f -exec chmod 644 {} ";"' % self.website.root

            def callback():
                self.save()
                self.activate()
                if os.path.exists(tmppath):
                    os.unlink(tmppath)
                self.context.notify('info', _('Download complete'))

            self.context.launch('terminal', command=script, callback=callback)

        self.find('download').on('click', download)

    @on('go-back', 'click')
    def on_go_back(self):
        WebsitesPlugin.get().activate()

    @on('destroy', 'click')
    def on_destroy(self):
        for ext in self.website.extensions:
            try:
                ext.on_destroy()
            except Exception, e:
                logging.error(str(e))
        self.manager.config.websites.remove(self.website)
        self.save()
        self.on_go_back()
Пример #37
0
class Firewall(SectionPlugin):
    platforms = ['centos', 'debian', 'arch', 'mageia']
    manager_class = FirewallManager

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

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

        self.fw_mgr = self.manager_class.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 DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8000 -j ACCEPT
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(
            '%s > %s' %
            (self.fw_mgr.iptables_save_binary, self.fw_mgr.config_path_ajenti),
            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):
        self.binder.update()
        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 | %s' % (self.fw_mgr.config_path,
                               self.fw_mgr.iptables_restore_binary)
        if subprocess.call(cmd, shell=True) != 0:
            self.context.launch('terminal', command=cmd)
        else:
            self.context.notify('info', _('Applied successfully'))
Пример #38
0
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')
        self.find('dialog').buttons = [
            {
                'id': 'save',
                'text': _('Save')
            },
            {
                'id': 'cancel',
                'text': _('Cancel')
            },
        ]

    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):
        os.mkdir(
            os.path.join(self.controller.tabs[self.tabs.active].path,
                         'new directory'))
        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)

        if for_move:
            self.backend.move(for_move, tab.path)
        if for_copy:
            self.backend.copy(for_copy, tab.path)
        self.clipboard = []
        self.refresh_clipboard()
        self.refresh()

    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()

    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()
Пример #39
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'))
Пример #40
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()
            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()

    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()
Пример #41
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.binder.setup(self).populate()
        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.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()
Пример #42
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()
Пример #43
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
Пример #44
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')
Пример #45
0
class WebsitesPlugin(SectionPlugin):
    def init(self):
        self.title = _('Websites')
        self.icon = 'globe'
        self.category = 'Web'

        self.manager = VHManager.get()

        if not self.manager.is_configured:
            from ajenti.plugins.vh import destroyed_configs
            self.append(self.ui.inflate('vh:not-configured'))
            self.find('destroyed-configs').text = ', '.join(destroyed_configs)
        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:main'))

        self.binder = Binder(None, self)

        def post_ws_bind(object, collection, item, ui):
            def manage():
                self.context.launch('v:manage-website', website=item)

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

        self.find('websites').post_item_bind = post_ws_bind

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

    @on('new-website', 'click')
    def on_new_website(self):
        self.binder.update()
        name = self.find('new-website-name').value
        self.find('new-website-name').value = ''
        if not name:
            name = '_'

        slug = slugify(name)
        slugs = [x.slug for x in self.manager.config.websites]
        while slug in slugs:
            slug += '_'

        w = Website.create(name)
        w.slug = slug
        self.manager.config.websites.append(w)
        self.manager.save()
        self.binder.populate()

    def on_page_load(self):
        self.refresh()

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

    @on('save', 'click')
    def save(self):
        self.binder.update()
        self.context.endpoint.send_progress(_('Saving changes'))
        self.manager.save()
        self.context.endpoint.send_progress(_('Applying changes'))
        self.manager.update_configuration()
        self.refresh()
        self.context.notify('info', _('Saved'))
Пример #46
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 as e:
                self.context.notify('error', _('Error: "%s"') % e.message)
        else:
            self.context.notify('error', _('Password shouldn\'t be empty'))

    def remove_password(self, user):
        self.mgr.remove_password(user)
        self.context.notify('info', _('Password for %s was removed') % user.name)
Пример #47
0
class LetsEncryptPlugin (SectionPlugin):
    pwd = os.path.join(os.path.dirname(os.path.realpath(__file__)), '')
    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'

        self.append(self.ui.inflate('letsencrypt:main'))
        
        self.settings = Settings()
        self.binder = Binder(self.settings, self)

        def delete_domain(domain, c):
            logging.debug('removed domain %s' % domain.name)
            c.remove(domain)
            logging.debug("domain info: %s %s" % (domain.subdomains, domain.name))
            self.save()
            
        def delete_cert(cert, c):
            logging.debug('removed cert %s' % cert.name)
            c.remove(cert)
            logging.debug("cert info: %s %s" % (cert.dir, cert.name))
            shutil.rmtree(cert.dir)

        def on_domain_bind(o, c, domain, u):
            domain.__old_name = domain.name

        def on_cert_bind(o, c, cert, u):
            cert.__old_name = cert.name

        def new_domain(c):
            name = 'domain.com'
            subdomains = 'www.domain.com\nblog.domain.com'
            return DomainsInfo(self, name, subdomains)
            
        self.find('certs').delete_item = delete_cert
        self.find('certs').post_item_bind = on_cert_bind
        self.find('domains').new_item = new_domain
        self.find('domains').delete_item = delete_domain
        self.find('domains').post_item_bind = on_domain_bind
     
    def fix_dependencies(self):
        if self.settings.dependencies_met is True:
            return
        
        changes = False
        
        # Install dehyrated (this is how we communicate with letsencrpyt)
        if not os.path.isfile(self.settings.basedir + self.settings.scriptname):
            self.context.notify('info', 'Fixing dehydrated dependency')
            changes = True
            
            if self.git_clone('https://github.com/lukas2511/dehydrated.git', self.settings.basedir):
                logging.debug("cloning of dehydrated successful")
                changes = False
        
        # Install nginxparser (this is how we edit nginx config files)
        installed_mods = sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])
        
        if "nginxparser" not in str(installed_mods):
            self.context.notify('info', 'Fixing nginxparser dependency')
            changes = True
            
            if self.git_clone('https://github.com/fatiherikli/nginxparser', '~/'):
                logging.debug("cloning of nginxparser successful.. installing..")
                
                command = ['python', 'setup.py', 'install'];
                p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd='/root/nginxparser/')
                out, err = p.communicate()
                
                installed_mods = sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])
                if "nginxparser" not in str(installed_mods):
                    logging.debug("Something went wrong with installing nginxparser..")
                else:
                    logging.debug("Installed nginxparser correctly.. importing modules..")
                    from nginxparser import load
                    from nginxparser import dumps 
                    changes = False
        
        if changes is False:
            self.settings.dependencies_met = True
            logging.debug("SUCCESSFULLY MET ALL DEPENDENCIES")
            
    def start_thread(self, target, *my_args, **my_keyword_args):
        thr = threading.Thread(target=target, args=my_args, kwargs=my_keyword_args)
        thr.daemon = True
        thr.start()
        return thr
        
    def on_page_load(self):
        self.refresh()
        
    def refresh(self):
        self.fix_dependencies()
        
        filepath = self.settings.basedir + self.settings.domainfile
        domains_file_read = ''
        
        if os.path.isfile(filepath):
            with open(filepath) as f:
                domains_file_read = f.readlines()
            domains_file_read = [x.strip() for x in domains_file_read]
            domains_file_read = "\n".join(domains_file_read)
        else:
            domains_file_read =  ""
       
        cron = self.check_cron()
        
        mysplit = domains_file_read.split("\n")
        tmp = []
        
        for lines in mysplit:
            mysecondsplit = lines.split(" ")
            main_domain = mysecondsplit.pop(0)
            sub_domains = ""
            
            if len(mysecondsplit) >= 1:
                sub_domains = mysecondsplit
                
            tmp.append(DomainsInfo(self, main_domain, "\n".join(sub_domains)))
            
        self.settings.domains = tmp
        self.find('cronjob').value = cron
  
        available_domains = self.list_available_certs()
        available_files = self.list_enabled_nginx_confs()
        temp_obj = []

        if available_domains:    
            for x in available_domains:
                #expiration date
                my_date = self.settings.basedir + '/certs/' + x + '/expiration.date'
                if os.path.isfile(my_date):
                    with open(my_date, 'r') as myfile:
                        my_date=myfile.read().replace('\n', '')
                else:
                    my_date = "NONE"
                
                #cert chain
                my_ssl_chain = self.settings.basedir + '/certs/' + x + '/chain.pem'
                if os.path.isfile(my_ssl_chain):
                    with open(my_ssl_chain, 'r') as myfile:
                        my_ssl_chain=myfile.read().replace('\n', '')
                else:
                    my_ssl_chain = "MISSING"
                
                #public key
                my_ssl_cert = self.settings.basedir + '/certs/' + x + '/cert.pem'
                if os.path.isfile(my_ssl_cert):
                    with open(my_ssl_cert, 'r') as myfile:
                        my_ssl_cert=myfile.read().replace('\n', '')
                else:
                    my_ssl_cert = "MISSING"
                    
                #public key and cert chain
                my_ssl_fullcert = self.settings.basedir + '/certs/' + x + '/fullchain.pem'
                if os.path.isfile(my_ssl_fullcert):
                    with open(my_ssl_fullcert, 'r') as myfile:
                        my_ssl_fullcert=myfile.read().replace('\n', '')
                else:
                    my_ssl_fullcert = "MISSING"
                    
                #private key
                my_ssl_key = self.settings.basedir + '/certs/' + x + '/privkey.pem'
                if os.path.isfile(my_ssl_key):
                    with open(my_ssl_key, 'r') as myfile:
                        my_ssl_key=myfile.read().replace('\n', '')
                else:
                    my_ssl_key = "MISSING"
                    
                temp_obj.append(CertificateInfo(self, self.settings.basedir + 'certs/' + x + '/', x, my_date, my_ssl_chain, my_ssl_cert, my_ssl_fullcert, my_ssl_key))
            
            self.settings.certs = temp_obj
        else:
            logging.debug("NO DOMAINS AVAILABLE")
            
        self.binder.setup(self.settings).populate()
    
    def list_enabled_nginx_confs(self):
        if not os.path.isdir(self.settings.nginx_sites_enabled):
            return False
            
        return [x for x in sorted(os.listdir(self.settings.nginx_sites_enabled)) if
                os.path.isfile(os.path.join(self.settings.nginx_sites_enabled, x))]

        
    def list_available_certs(self):
        if not os.path.isdir(self.settings.basedir + "certs"):
            return False
            
        return [x for x in sorted(os.listdir(self.settings.basedir + "certs")) if
                os.path.isdir(os.path.join(self.settings.basedir + "certs", x))]

    def write_domain_file(self):
        filepath = self.settings.basedir + self.settings.domainfile
        if len(self.settings.domains) < 1:
            self.context.notify('info', 'No domains specified')
            self.has_domains = False
            return
        
        final_str = ''

        for domains in self.settings.domains:
            final_str = final_str + domains.name + " "
            
            if domains.subdomains:
                tmp = domains.subdomains.split("\n")
                tmp = " ".join(tmp)
                final_str = final_str + tmp
            final_str = final_str + "\n"
            
        logging.debug("final string %s " % final_str)   
        
        file = open(filepath, 'w')
        if file.write(final_str) 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_dehydrated_config_file(self):
        template = """
        BASEDIR=$basedir
        WELLKNOWN=$wellknown
        """
        dict = {
            'basedir': self.settings.basedir,
            'wellknown': self.settings.wellknown
        }

        filepath = self.settings.basedir + self.settings.configname
        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 cleanup_oldfiles(self):
        filepath1 = self.settings.nginx_sites_enabled + self.settings.nginx_config
        filepath2 = self.settings.nginx_sites_available + self.settings.nginx_config
        filepath3 = self.settings.basedir + self.settings.configname
        filepath4 = self.settings.basedir + self.settings.domainfile
        
        if os.path.isfile(filepath1):
            os.remove(filepath1)
        if os.path.isfile(filepath2):
            os.remove(filepath2)
        if os.path.isfile(filepath3):
            os.remove(filepath3)
        if os.path.isfile(filepath4):
            os.remove(filepath4)
        
        self.context.notify('info', 'removed all local files')  
        
    def create_nginx_wellknown_config(self):
        if not self.check_nginx_dir_exists():
            self.context.notify('info', 'nginx_custom_dir() is not valid: %s')
            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.settings.nginx_sites_available + self.settings.nginx_config
        filepath2 = self.settings.nginx_sites_enabled + 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()
        
        if os.path.isfile(filepath2):
            return True
            
        os.symlink(filepath, filepath2)

    def create_cron(self):
        file = open(self.settings.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.settings.crontab_dir + self.settings.cronfile):
            if os.remove(self.settings.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.settings.crontab_dir + self.settings.cronfile):
            return True
        return False

    # Update Nginx config files to use SSL
    def update_nginx_confs(self):
        available_domains = self.list_available_certs()
        filepath = self.settings.basedir + self.settings.domainfile
        domains = ''
        
        if os.path.isfile(filepath):
            with open(filepath) as f:
                domains = f.readlines()
            domains = [x.strip() for x in domains]
            domains = "\n".join(domains)
        
        mysplit = domains.split("\n")
        
        # Gets all enabled sites
        available_nginx_files = self.list_enabled_nginx_confs()

        for curr_domain in available_domains:
            for curr_nginx_file in available_nginx_files:
                logging.debug("## Use Certs: Checking config file - %s ##" % curr_nginx_file)
                
                if self.settings.nginx_config in curr_nginx_file:
                    logging.debug("Skipping file: %s" % curr_nginx_file)
                    continue
                    
                # Path is to the sites_available directory
                filepath = self.settings.nginx_sites_available + curr_nginx_file
                
                if not os.path.isfile(filepath):
                    logging.debug("File not in sites_available directory.. continuing")
                    continue
                    
                loaded_conf = load(open(filepath))
                
                for servers in loaded_conf:
                    server_conf = servers[1]
                    ssl_true = False
                    listen_position = None
                    server_name_position = None
                    ssl_cert_position = None
                    ssl_cert_key_position = None
                    curr_pos = 0
                    
                    for lines in server_conf:
                        if isinstance(lines[0], str):
                            
                            if 'server_name' in lines[0] and len(lines) > 1:
                                if server_name_position is not None:
                                    logging.debug("There must be more than one server_name_position.. skipping this file because we don't know how to handle it.")
                                    print("CONF %s" % loaded_conf)
                                    break
                                    
                                server_name_position = curr_pos
                                
                            if 'listen' in lines[0] and len(lines) > 1:
                                if listen_position is not None:
                                    listen_position = [listen_position]
                                    listen_position.append(curr_pos)
                                    print("There are multiple listen positions: %s" % listen_position)
                                else:    
                                    listen_position = curr_pos
                            
                            if 'ssl_certificate' in lines[0] and 'ssl_certificate_key' not in lines[0] and len(lines) > 1:
                                if ssl_cert_position is not None:
                                    logging.debug("There must be more than one ssl_certificate.. skipping this file because we don't know how to handle it.")
                                    print("CONF %s" % lines[0])
                                    break
                                    
                                ssl_cert_position = curr_pos
                            
                            if 'ssl_certificate_key' in lines[0] and len(lines) > 1:
                                if ssl_cert_key_position is not None:
                                    logging.debug("There must be more than one ssl_certificate_key.. skipping this file because we don't know how to handle it.")
                                    print("CONF %s" % lines[0])
                                    break
                                    
                                ssl_cert_key_position = curr_pos        
                                
                        curr_pos += 1
                    
                    if listen_position is not None and server_name_position is not None:
                        logging.debug("We have both listen and server name positions: listen position: %s | server_name_position: %s" % (listen_position, server_name_position))
                        
                        found_it = False
                        
                        for domain_list_line in mysplit:
                            if found_it is True:
                                break
                            
                            secondsplit = domain_list_line.split(" ")
                            
                            for domains in secondsplit:
                                logging.debug("CHECKING DOMAIN %s with: %s" % (server_conf[server_name_position][1], domains))
                                if server_conf[server_name_position][1] in domains:
                                    logging.debug("found our domain: %s in the list of domains" % server_conf[server_name_position][1])
                                    found_it = True
                                    break
                                
                        if found_it is False:
                            logging.debug("Server Config does not have any of our domains with SSL certs in the 'server_name' position.. skipping this config.")
                            continue
             
                        # Check if SSL is already setup
                        if ssl_cert_key_position is not None and ssl_cert_position is not None:

                            # Check if ports are setup too
                            if isinstance(listen_position, list):
                                already_setup = False
                                
                                for listens in listen_position:
                                    if "443" in server_conf[listens][1]:
                                        already_setup = True
                                        break
                                
                                if already_setup is True:
                                    logging.debug("This server is already setup for SSL")
                                    continue
                            
                            elif isinstance(listen_position, str):
                                if "443" in server_conf[listens][1]:
                                    continue
                                    
                        # Lets setup SSL now...
                        logging.debug("Attempting to setup SSL for domain: %s" % curr_domain)
                        
                        # Multiple listen calls..
                        if isinstance(listen_position, list):
                            already_setup = False
                                
                            for listens in listen_position:
                                if "443" in server_conf[listens][1]:
                                    already_setup = True
                                    break
                            
                            # Check if ssl port is already set
                            if already_setup is True:
                                logging.debug("Server port already setup for SSL")
                                
                            # 443 not set... set one of the listen calls to 443
                            else:
                                server_conf[listen_position[0]][1]
                                
                                # ssl port set already
                                if "443 ssl" in server_conf[listen_position[0]][1]:
                                    logging.debug("Server port already setup for SSL")
                                    
                                # ssl port not set yet..
                                else:   
                                    if ":" in server_conf[listen_position[0]][1]:
                                        tmp = server_conf[listen_position[0]][1].split(":")
                                        
                                        if tmp[1]:
                                            logging.debug("old port value %s" % server_conf[listen_position[0]][1])
                                            r = re.compile(r"\d{2,5}")
                                            tmp[1] = r.sub("443 ssl", tmp[1])
                                            
                                            server_conf[listen_position[0]][1] = ':'.join(tmp)
                                            logging.debug("new port value: %s" % server_conf[listen_position[0]][1])
                                    else:
                                        logging.debug("old port value: %s" % server_conf[listen_position[0]][1])
                                        r = re.compile(r"\d{2,5}")
                                        tmp = r.sub("443 ssl", server_conf[listen_position[0]][1])
                                        
                                        server_conf[listen_position[0]][1] = tmp
                                        logging.debug("new port value: %s" % server_conf[listen_position[0]][1]) 
                                        
                        # Single listen call..
                        else:
                            
                            # ssl port set already
                            if "443 ssl" in server_conf[listen_position][1]:
                                logging.debug("Server port already setup for SSL")
                                
                            # ssl port not set yet..
                            else:   
                                if ":" in server_conf[listen_position][1]:
                                    tmp = server_conf[listen_position][1].split(":")
                                    
                                    if tmp[1]:
                                        logging.debug("old port value %s" % server_conf[listen_position][1])
                                        r = re.compile(r"\d{2,5}")
                                        tmp[1] = r.sub("443 ssl", tmp[1])
                                        
                                        server_conf[listen_position][1] = ':'.join(tmp)
                                        logging.debug("new port value: %s" % server_conf[listen_position][1])
                                       
                                else:
                                    logging.debug("old port value: %s" % server_conf[listen_position][1])
                                    r = re.compile(r"\d{2,5}")
                                    tmp = r.sub("443 ssl", server_conf[listen_position][1])
                                    
                                    server_conf[listen_position][1] = tmp
                                    logging.debug("new port value: %s" % server_conf[listen_position][1])

                        cert_path = self.settings.basedir + '/certs/' + curr_domain + '/fullchain.pem'
                        cert_key_path = self.settings.basedir + '/certs/' + curr_domain + '/privkey.pem'

                        if ssl_cert_position is None:
                            server_conf.insert(0, ["ssl_certificate", cert_path])
                        else:
                            server_conf[ssl_cert_position][1] = cert_path
                            
                        if ssl_cert_key_position is None:
                            server_conf.insert(1, ["ssl_certificate_key", cert_key_path])
                        else:
                            server_conf[ssl_cert_key_position][1] = cert_key_path

                    file = open(filepath,"w") 
                    file.write(dumps(loaded_conf))
                    file.close()  
                    logging.debug("## FINISHED WITH SETTING UP NGINX WITH CERTS ##")
                    self.context.notify('info', 'Nginx is now using your valid certs.')
                    
    def check_nginx_dir_exists(self):
        if not os.path.exists(self.settings.nginx_sites_available):
            os.makedirs(self.settings.nginx_sites_available)
            
        if not os.path.exists(self.settings.nginx_sites_enabled):
            os.makedirs(self.settings.nginx_sites_enabled)

        if os.path.exists(self.settings.nginx_sites_available) and os.path.exists(self.settings.nginx_sites_enabled):
            return True
        
        self.context.notify('error', 'One or more nginx directories is incorrect')

    def request_certs_helper(self):
        self.save()
        time.sleep(5)
        
        if not os.path.exists(self.settings.basedir + "accounts"):
            self.context.notify('error', 'No accounts directory found, Registering before requesting certs..')
            self.request_certificates(True)
            
        if os.path.exists(self.settings.basedir + "accounts"):
            self.request_certificates(False)
            
    def request_certificates(self, register):
        filepath = self.settings.basedir + self.settings.scriptname
        params = [filepath, '-c']
        out = ""
        
        if self.find('renewal').value:
            params.append('--force')
            
        if register:
            params = [filepath, '--register', '--accept-terms']
        
        self.settings.output = "Disabling currently active SYMLINKS\n"
        self.binder.setup(self.settings).populate()
        
        available_files = self.list_enabled_nginx_confs()
        for curr_nginx_file in available_files:
            
            if self.settings.nginx_config in curr_nginx_file:
                logging.debug("Skipping file: %s" % curr_nginx_file)
                continue
            
            logging.debug("Disabling SYMLINK: %s" % curr_nginx_file)
            
            filepath = self.settings.nginx_sites_enabled + curr_nginx_file
            os.unlink(filepath)
        
        p = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        success = False
        
        while p.poll() is None:
            output = p.stdout.readline()
            logging.debug("%s" % output)
            self.settings.output = output + self.settings.output
            self.binder.setup(self.settings).populate()
            
            if "Creating fullchain.pem" in output or "Skipping renew!" in output:
                success = True
  
        self.settings.output = "Re-enabling SYMLINKS...\n" + self.settings.output
        self.binder.setup(self.settings).populate()
        
        for curr_nginx_file in available_files:
            if not os.path.isfile(self.settings.nginx_sites_enabled + curr_nginx_file):
                filepath1 = self.settings.nginx_sites_available + curr_nginx_file
                filepath2 = self.settings.nginx_sites_enabled + curr_nginx_file
                os.symlink(filepath1, filepath2)    
        
        self.settings.output = "Restarting NGINX once more...\n" + self.settings.output
        self.binder.setup(self.settings).populate()
        self.restart_nginx()
        
        if success is True:
            self.settings.output = "Success creating certificates! Congratulations!\n" + self.settings.output
            self.binder.setup(self.settings).populate()
        else:
            self.settings.output = "Something went wrong. Read logs below.\n" + self.settings.output
            self.binder.setup(self.settings).populate()
            
    def restart_nginx(self):
        self.context.notify('info', 'Restarting Nginx')
        command = ['/usr/sbin/service', 'nginx', 'restart'];
        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()

    def git_clone(self, repo, dir):
        logging.debug("Cloning REPO: %s into directory: %s" % (repo, dir))
        
        # GIT automatically makes directories
        command = ['/usr/bin/git', 'clone', repo, dir];
        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        
        command = ['/usr/bin/git', 'remote', '-v'];
        p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=dir)
        out, err = p.communicate()
        
        if repo in out:
            return True
        else:
            return False
            
    def helper(self):        
        installed_mods = sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])
        
        if "nginxparser" not in str(installed_mods):
            if self.git_clone('https://github.com/fatiherikli/nginxparser', '~/'):
                logging.debug("cloning of nginxparser successful.. installing..")
                
                command = ['python', 'setup.py', 'install'];
                p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd='/root/nginxparser/')
                out, err = p.communicate()
                
                installed_mods = sorted(["%s==%s" % (i.key, i.version) for i in pip.get_installed_distributions()])
                if "nginxparser" not in str(installed_mods):
                    logging.debug("Something went wrong with installing nginxparser..")
            
    def save(self):
        self.binder.update()
        self.binder.populate()
        self.create_folders()
        self.write_domain_file()

        if not self.has_domains:
            
            self.cleanup_oldfiles()
            self.restart_nginx()
            return

        self.create_dehydrated_config_file()
        self.create_nginx_wellknown_config()

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

    @on('done', 'click')
    def on_output_done(self):
        self.find('hidden_output').visible = False
        
    @on('tabs', 'switch')
    def tab_switched(self):
        self.refresh()
        
    @on('save', 'click')
    def save_button(self):
        self.save()       

    @on('updatenginx', 'click')
    def updatenginx_button(self):     
        self.update_nginx_confs()
        self.restart_nginx()
    
    @on('helperbutton', 'click')
    def helper_button(self):
        self.helper()

    @on('request', 'click')
    def request_button(self):
        self.settings.output = "Saving configuration... Waiting 5 seconds..."
        self.binder.setup(self.settings).populate()
        self.find('hidden_output').visible = True
        self.start_thread(self.request_certs_helper)
Пример #48
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 as e:
            self.context.notify('error', str(e))
Пример #49
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.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.owner = self.context.session.identity
        mb.password = ''
        
        if not mb.local:
            self.context.notify('error', _('Invalid mailbox name'))
            return

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

        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 = ''
        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:
            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()

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