Пример #1
0
    def get_form(self):
        form = fapi.ForisForm("registration_check",
                              self.data,
                              filter=create_config_filter("foris"))
        main_section = form.add_section(name="check_email",
                                        title=_(self.userfriendly_title))
        main_section.add_field(Email, name="email", label=_("Email"))

        def form_cb(data):
            result = client.get_registration_status(data.get("email"),
                                                    bottle.request.app.lang)
            return "save_result", {
                'success': result[0],
                'response': result[1],
            }

        form.add_callback(form_cb)
        return form
Пример #2
0
    def get_form(self):
        dns_form = fapi.ForisForm("dns", self.data,
                                  filter=create_config_filter("unbound"))
        dns_main = dns_form.add_section(name="set_dns",
                                        title=_(self.userfriendly_title))
        dns_main.add_field(Checkbox, name="forward_upstream", label=_("Use forwarding"),
                           nuci_path="uci.unbound.server.forward_upstream",
                           nuci_preproc=lambda val: bool(int(val.value)), default=True)

        def dns_form_cb(data):
            uci = Uci()
            unbound = Config("unbound")
            uci.add(unbound)
            server = Section("server", "unbound")
            unbound.add(server)
            server.add(Option("forward_upstream", data['forward_upstream']))
            return "edit_config", uci

        dns_form.add_callback(dns_form_cb)
        return dns_form
Пример #3
0
    def get_form(self):
        ucollect_form = fapi.ForisForm(
            "ucollect",
            self.data,
            filter=filters.create_config_filter("ucollect"))
        fakes = ucollect_form.add_section(
            name="fakes",
            title=_("Emulated services"),
            description=
            _("One of uCollect's features is emulation of some commonly abused "
              "services. If this function is enabled, uCollect is listening for "
              "incoming connection attempts to these services. Enabling of the "
              "emulated services has no effect if another service is already "
              "listening on its default port (port numbers are listed below)."
              ))

        SERVICES_OPTIONS = (
            ("23tcp", _("Telnet (23/TCP)")),
            ("2323tcp", _("Telnet - alternative port (2323/TCP)")),
            ("80tcp", _("HTTP (80/TCP)")),
            ("3128tcp", _("Squid HTTP proxy (3128/TCP)")),
            ("8123tcp", _("Polipo HTTP proxy (8123/TCP)")),
            ("8080tcp", _("HTTP proxy (8080/TCP)")),
        )

        def get_enabled_services(disabled_list):
            disabled_services = map(lambda value: value.content,
                                    disabled_list.children)
            res = [
                x[0] for x in SERVICES_OPTIONS if x[0] not in disabled_services
            ]
            return res

        fakes.add_field(MultiCheckbox,
                        name="services",
                        label=_("Emulated services"),
                        args=SERVICES_OPTIONS,
                        multifield=True,
                        nuci_path="uci.ucollect.fakes.disable",
                        nuci_preproc=get_enabled_services,
                        default=[x[0] for x in SERVICES_OPTIONS])

        fakes.add_field(
            Checkbox,
            name="log_credentials",
            label=_("Collect credentials"),
            hint=
            _("If this option is enabled, user names and passwords are collected "
              "and sent to server in addition to the IP address of the client."
              ),
            nuci_path="uci.ucollect.fakes.log_credentials",
            nuci_preproc=parse_uci_bool)

        def ucollect_form_cb(data):
            uci = Uci()
            ucollect = Config("ucollect")
            uci.add(ucollect)

            fakes = Section("fakes", "fakes")
            ucollect.add(fakes)

            disable = List("disable")

            disabled_services = [
                x[0] for x in SERVICES_OPTIONS if x[0] not in data['services']
            ]
            for i, service in enumerate(disabled_services):
                disable.add(Value(i, service))

            if len(disabled_services):
                fakes.add_replace(disable)
            else:
                fakes.add_removal(disable)

            fakes.add(Option("log_credentials", data['log_credentials']))

            return "edit_config", uci

        ucollect_form.add_callback(ucollect_form_cb)

        return ucollect_form
Пример #4
0
    def get_form(self):
        region_form = fapi.ForisForm(
            "region", self.data, filter=filters.create_config_filter("system"))
        timezone = region_form.add_section(
            name="timezone",
            title=_(self.userfriendly_title),
            description=_(
                "Please select the timezone the router is being operated in. "
                "Correct setting is required to display the right time and for related functions."
            ))

        lang = bottle.request.app.lang

        def construct_args(items,
                           translation_function=_,
                           key_getter=lambda x: x):
            """
            Helper function that builds args for country/timezone dropdowns.
            If there's only one item, dropdown should contain only that item.
            Otherwise the list of items should be prepended by an empty value.

            :param items: list of filtered TZ data
            :param translation_function: function that returns displayed choice from TZ data
            :param key_getter:
            :return: list of args
            """
            args = localized_sorted(
                ((key_getter(x), translation_function(x)) for x in items),
                lang=lang,
                key=lambda x: x[1])
            if len(args) > 1:
                return [(None, "-" * 16)] + args
            return args

        timezone.add_field(Hidden,
                           name="system_name",
                           nuci_path="uci.system.@system[0]",
                           nuci_preproc=lambda val: val.name)

        regions = localized_sorted(((x, _(x)) for x in tzinfo.regions),
                                   lang=lang,
                                   key=lambda x: x[1])
        timezone.add_field(Dropdown,
                           name="region",
                           label=_("Continent or ocean"),
                           required=True,
                           args=regions,
                           nuci_path="uci.system.@system[0].zonename",
                           nuci_preproc=lambda x: x.value.split("/")[0])

        # Get region and offer available countries
        region = region_form.current_data.get('region')
        countries = construct_args(tzinfo.countries_in_region(region),
                                   lambda x: _(tzinfo.countries[x]))
        timezone.add_field(Dropdown, name="country", label=_("Country"), required=True,
                           default=None, args=countries,
                           nuci_path="uci.system.@system[0].zonename",
                           nuci_preproc=lambda x: tzinfo.get_country_for_tz(x.value))\
            .requires("region")

        # Get country and offer available timezones
        country = region_form.current_data.get("country", countries[0][0])

        # It's possible that data contain country from the previous request,
        # in that case fall back to the first item in list of available countries
        if country not in (x[0] for x in countries):
            country = countries[0][0]
        timezones = construct_args(tzinfo.timezones_in_region_and_country(
            region, country),
                                   translation_function=lambda x: _(x[2]),
                                   key_getter=lambda x: x[0])

        # Offer timezones - but only if a country is selected and is not None (ensured by the
        # requires() method)
        timezone.add_field(Dropdown, name="zonename", label=_("Timezone"), required=True,
                           default=None,
                           args=timezones, nuci_path="uci.system.@system[0].zonename")\
            .requires("country", lambda x: country and x is not None)

        def region_form_cb(data):
            uci = Uci()
            system = Config("system")
            uci.add(system)
            system_section = Section(data['system_name'], "system")
            system.add(system_section)
            zonename = data['zonename']
            system_section.add(Option("zonename", zonename))
            system_section.add(
                Option("timezone", tzinfo.get_zoneinfo_for_tz(zonename)))
            return "edit_config", uci

        region_form.add_callback(region_form_cb)
        return region_form
Пример #5
0
    def get_form(self):
        notifications_form = fapi.ForisForm(
            "notifications",
            self.data,
            filter=create_config_filter("user_notify"))

        notifications = notifications_form.add_section(
            name="notifications", title=_("Notifications settings"))
        # notifications settings
        notifications.add_field(Checkbox,
                                name="enable_smtp",
                                label=_("Enable notifications"),
                                nuci_path="uci.user_notify.smtp.enable",
                                nuci_preproc=lambda val: bool(int(val.value)),
                                default=False)

        notifications.add_field(
            Radio,
            name="use_turris_smtp",
            label=_("SMTP provider"),
            default="0",
            args=(("1", _("Turris")), ("0", _("Custom"))),
            nuci_path="uci.user_notify.smtp.use_turris_smtp",
            hint=_("If you set SMTP provider to \"Turris\", the servers provided to members of the "
                   "Turris project would be used. These servers do not require any additional "
                   "settings. If you want to set your own SMTP server, please select \"Custom\" "
                   "and enter required settings."))\
            .requires("enable_smtp", True)

        notifications.add_field(
            Textbox,
            name="to",
            label=_("Recipient's email"),
            nuci_path="uci.user_notify.smtp.to",
            nuci_preproc=lambda x: " ".join(
                map(lambda value: value.content, x.children)),
            hint=
            _("Email address of recipient. Separate multiple addresses by spaces."
              ),
            required=True).requires("enable_smtp", True)

        # sender's name for CZ.NIC SMTP only
        notifications.add_field(
            Textbox,
            name="sender_name",
            label=_("Sender's name"),
            hint=_("Name of the sender - will be used as a part of the "
                   "sender's email address before the \"at\" sign."),
            nuci_path="uci.user_notify.smtp.sender_name",
            validators=[validators.RegExp(_("Sender's name can contain only "
                                            "alphanumeric characters, dots "
                                            "and underscores."),
                                          r"^[0-9a-zA-Z_\.-]+$")],
            required=True
        )\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "1")

        SEVERITY_OPTIONS = (
            (1, _("Reboot is required")),
            (2, _("Reboot or attention is required")),
            (3, _("Reboot or attention is required or update was installed")),
        )
        notifications.add_field(Dropdown, name="severity", label=_("Importance"),
                                nuci_path="uci.user_notify.notifications.severity",
                                nuci_preproc=lambda val: int(val.value),
                                args=SEVERITY_OPTIONS, default=1)\
            .requires("enable_smtp", True)
        notifications.add_field(Checkbox, name="news", label=_("Send news"),
                                hint=_("Send emails about new features."),
                                nuci_path="uci.user_notify.notifications.news",
                                nuci_preproc=lambda val: bool(int(val.value)),
                                default=True)\
            .requires("enable_smtp", True)

        # SMTP settings (custom server)
        smtp = notifications_form.add_section(name="smtp",
                                              title=_("SMTP settings"))
        smtp.add_field(Email, name="from", label=_("Sender address (From)"),
                       hint=_("This is the address notifications are sent from."),
                       nuci_path="uci.user_notify.smtp.from",
                       required=True)\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")
        smtp.add_field(Textbox, name="server", label=_("Server address"),
                                nuci_path="uci.user_notify.smtp.server",
                                required=True)\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")
        smtp.add_field(Number, name="port", label=_("Server port"),
                       nuci_path="uci.user_notify.smtp.port",
                       validators=[validators.PositiveInteger()],
                       required=True) \
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")

        SECURITY_OPTIONS = (
            ("none", _("None")),
            ("ssl", _("SSL/TLS")),
            ("starttls", _("STARTTLS")),
        )
        smtp.add_field(Dropdown, name="security", label=_("Security"),
                       nuci_path="uci.user_notify.smtp.security",
                       args=SECURITY_OPTIONS, default="none") \
            .requires("enable_smtp", True).requires("use_turris_smtp", "0")

        smtp.add_field(Textbox, name="username", label=_("Username"),
                       nuci_path="uci.user_notify.smtp.username")\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")
        smtp.add_field(Password, name="password", label=_("Password"),
                       nuci_path="uci.user_notify.smtp.password")\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")

        # reboot time
        reboot = notifications_form.add_section(
            name="reboot", title=_("Automatic restarts after software update"))
        reboot.add_field(
            Number,
            name="delay",
            label=_("Delay (days)"),
            hint=_(
                "Number of days that must pass between receiving the request "
                "for restart and the automatic restart itself."),
            nuci_path="uci.user_notify.reboot.delay",
            validators=[
                validators.PositiveInteger(),
                validators.InRange(0, 10)
            ],
            required=True)
        reboot.add_field(
            Time,
            name="reboot_time",
            label=_("Reboot time"),
            hint=_("Time of day of automatic reboot in HH:MM format."),
            nuci_path="uci.user_notify.reboot.time",
            validators=[validators.Time()],
            required=True)

        def notifications_form_cb(data):
            uci = Uci()
            user_notify = Config("user_notify")
            uci.add(user_notify)

            smtp = Section("smtp", "smtp")
            user_notify.add(smtp)
            smtp.add(Option("enable", data['enable_smtp']))

            reboot = Section("reboot", "reboot")
            user_notify.add(reboot)
            reboot.add(Option("time", data['reboot_time']))
            reboot.add(Option("delay", data['delay']))

            if data['enable_smtp']:
                smtp.add(Option("use_turris_smtp", data['use_turris_smtp']))
                if data['use_turris_smtp'] == "0":
                    smtp.add(Option("server", data['server']))
                    smtp.add(Option("port", data['port']))
                    smtp.add(Option("username", data['username']))
                    smtp.add(Option("password", data['password']))
                    smtp.add(Option("security", data['security']))
                    smtp.add(Option("from", data['from']))
                else:
                    smtp.add(Option("sender_name", data['sender_name']))
                to = List("to")
                for i, to_item in enumerate(data['to'].split(" ")):
                    if to_item:
                        to.add(Value(i, to_item))
                smtp.add_replace(to)
                # notifications section
                notifications = Section("notifications", "notifications")
                user_notify.add(notifications)
                notifications.add(Option("severity", data['severity']))
                notifications.add(Option("news", data['news']))

            return "edit_config", uci

        notifications_form.add_callback(notifications_form_cb)

        return notifications_form
Пример #6
0
    def get_form(self):
        dns_form = fapi.ForisForm("dns",
                                  self.data,
                                  filter=create_config_filter(
                                      "resolver", "dhcp"))
        dns_main = dns_form.add_section(name="set_dns",
                                        title=_(self.userfriendly_title))
        dns_main.add_field(Checkbox,
                           name="forward_upstream",
                           label=_("Use forwarding"),
                           nuci_path="uci.resolver.common.forward_upstream",
                           nuci_preproc=lambda val: bool(int(val.value)),
                           default=True)

        if not contract_valid():
            dns_main.add_field(
                Checkbox,
                name="ignore_root_key",
                label=_("Disable DNSSEC"),
                nuci_path="uci.resolver.common.ignore_root_key",
                nuci_preproc=lambda val: bool(int(val.value)),
                default=False,
            )

        resolver = dns_form.nuci_config.find_child(
            "uci.resolver.common.prefered_resolver")
        if resolver and resolver.value in ["kresd", "unbound"]:
            dns_main.add_field(
                Checkbox,
                name="dhcp_from_dns",
                label=_("Enable DHCP clients in DNS"),
                hint=_(
                    "This will enable your DNS resolver to place DHCP client's "
                    "names among the local DNS records."),
                nuci_path="uci.resolver.common.dynamic_domains",
                nuci_preproc=lambda val: bool(int(val.value)),
                default=False,
            )
            dns_main.add_field(
                Textbox,
                name="dhcp_dns_domain",
                label=_("Domain of DHCP clients in DNS"),
                hint=_(
                    "This domain will be used as TLD. E.g. The result for client \"android-123\" "
                    "and domain \"lan\" will be \"android-123.lan\"."),
                nuci_path="uci.dhcp.@dnsmasq[0].local",
                nuci_preproc=lambda val: val.value.strip("/")
                if val else "lan",
                default="lan",
                validators=[validators.Domain()],
            ).requires("dhcp_from_dns", True)

        resolver = dns_form.nuci_config.find_child("uci.dhcp.@dnsmasq[0]")

        def dns_form_cb(data):
            uci = Uci()
            resolver = Config("resolver")
            uci.add(resolver)
            server = Section("common", "resolver")
            resolver.add(server)
            server.add(Option("forward_upstream", data['forward_upstream']))
            if not contract_valid():
                server.add(Option("ignore_root_key", data['ignore_root_key']))

            if 'dhcp_from_dns' in data:
                server.add(Option("dynamic_domains", data['dhcp_from_dns']))

            if 'dhcp_dns_domain' in data:
                dhcp = uci.add(Config("dhcp"))
                dnsmasq_section = dns_form.nuci_config.find_child(
                    "uci.dhcp.@dnsmasq[0]")
                dnsmasq = dhcp.add(
                    Section(dnsmasq_section.name, "dnsmasq", anonymous=True))
                dnsmasq.add(
                    Option("local",
                           "/%s/" % data["dhcp_dns_domain"].strip("/")))

            return "edit_config", uci

        dns_form.add_callback(dns_form_cb)
        return dns_form
Пример #7
0
    def get_form(self):
        lan_form = fapi.ForisForm(
            "lan", self.data, filter=create_config_filter("dhcp", "network", "firewall", "sqm"))
        lan_main = lan_form.add_section(
            name="set_lan",
            title=_(self.userfriendly_title),
            description=_("This section contains settings for the local network (LAN). The provided"
                          " defaults are suitable for most networks. <br><strong>Note:</strong> If "
                          "you change the router IP address, all computers in LAN, probably "
                          "including the one you are using now, will need to obtain a <strong>new "
                          "IP address</strong> which does <strong>not</strong> happen <strong>"
                          "immediately</strong>. It is recommended to disconnect and reconnect all "
                          "LAN cables after submitting your changes to force the update. The next "
                          "page will not load until you obtain a new IP from DHCP (if DHCP enabled)"
                          " and you might need to <strong>refresh the page</strong> in your "
                          "browser.")
        )

        lan_main.add_field(Textbox, name="lan_ipaddr", label=_("Router IP address"),
                           nuci_path="uci.network.lan.ipaddr",
                           validators=validators.IPv4(),
                           hint=_("Router's IP address in inner network. Also defines the range of "
                                  "assigned IP addresses."))
        lan_main.add_field(Checkbox, name="dhcp_enabled", label=_("Enable DHCP"),
                           nuci_path="uci.dhcp.lan.ignore",
                           nuci_preproc=lambda val: not bool(int(val.value)), default=True,
                           hint=_("Enable this option to automatically assign IP addresses to "
                                  "the devices connected to the router."))
        lan_main.add_field(Textbox, name="dhcp_min", label=_("DHCP start"),
                           nuci_path="uci.dhcp.lan.start")\
            .requires("dhcp_enabled", True)
        lan_main.add_field(Textbox, name="dhcp_max", label=_("DHCP max leases"),
                           nuci_path="uci.dhcp.lan.limit")\
            .requires("dhcp_enabled", True)

        guest_network_section = lan_form.add_section(
            name="guest_network",
            title=_("Guest network"),
        )
        guest_network_section.add_field(
            Checkbox, name="guest_network_enabled",
            label=_("Enable guest network"), default=False,
            hint=_(
                "Guest network is used for <a href='%(url)s'>guest Wi-Fi</a>. It is separated  "
                "from your ordinary LAN network. Devices connected to this network are allowed "
                "to access the internet, but are not allowed to access other devices and "
                "the configuration interface of the router."
            ) % dict(url=reverse("config_page", page_name="wifi")),
            nuci_preproc=guest_network_enabled,
        )
        guest_network_section.add_field(
            Textbox, name="guest_network_subnet", label=_("Guest network"),
            nuci_preproc=generate_network_preprocessor(
                "uci.network.guest_turris.ipaddr",
                "uci.network.guest_turris.netmask",
                DEFAULT_GUEST_NETWORK,
                DEFAULT_GUEST_MASK,
            ),
            validators=[validators.IPv4Prefix()],
            hint=_(
                "You need to set the IP range for your guest network. It is necessary that "
                "the range is different than ranges on your other networks (LAN, WAN, VPN, etc.)."
            ),
        ).requires("guest_network_enabled", True)
        guest_network_section.add_field(
            Checkbox, name="guest_network_shapping", label=_("Guest Lan QoS"),
            nuci_preproc=parse_uci_bool,
            nuci_path="uci.sqm.guest_limit_turris.enabled",
            hint=_(
                "This option enables you to set a bandwidth limit for the guest network, "
                "so that your main network doesn't get slowed-down by it."
            ),
        ).requires("guest_network_enabled", True)
        guest_network_section.add_field(
            Number,
            name="guest_network_download", label=_("Download (kb/s)"),
            validators=[validators.PositiveInteger()],
            hint=_(
                "Download speed in guest network (in kilobits per second)."
            ),
            default=1024,
            nuci_path="uci.sqm.guest_limit_turris.upload",
        ).requires("guest_network_shapping", True)
        guest_network_section.add_field(
            Number,
            name="guest_network_upload", label=_("Upload (kb/s)"),
            validators=[validators.PositiveInteger()],
            hint=_(
                "Upload speed in guest network (in kilobits per second)."
            ),
            default=1024,
            nuci_path="uci.sqm.guest_limit_turris.download",
        ).requires("guest_network_shapping", True)

        def lan_form_cb(data):
            uci = Uci()
            config = Config("dhcp")
            uci.add(config)

            dhcp = Section("lan", "dhcp")
            config.add(dhcp)
            # FIXME: this would overwrite any unrelated DHCP options the user might have set.
            # Maybe we should get the current values, scan them and remove selectively the ones
            # with 6 in front of them? Or have some support for higher level of stuff in nuci.
            options = List("dhcp_option")
            options.add(Value(0, "6," + data['lan_ipaddr']))
            dhcp.add_replace(options)
            network = Config("network")
            uci.add(network)
            interface = Section("lan", "interface")
            network.add(interface)
            interface.add(Option("ipaddr", data['lan_ipaddr']))
            if data['dhcp_enabled']:
                dhcp.add(Option("ignore", "0"))
                dhcp.add(Option("start", data['dhcp_min']))
                dhcp.add(Option("limit", data['dhcp_max']))
            else:
                dhcp.add(Option("ignore", "1"))

            # qos data
            qos = {'enabled': False}
            if 'guest_network_shapping' in data and data['guest_network_shapping']:
                qos['enabled'] = True
                qos['download'] = data['guest_network_download']
                qos['upload'] = data['guest_network_upload']

            # update guest network configs
            guest_enabled = data.get("guest_network_enabled")
            guest_network_subnet = data.get("guest_network_subnet")
            if guest_network_subnet:
                network, prefix = data.get("guest_network_subnet").split("/")
            else:
                network, prefix = DEFAULT_GUEST_NETWORK, DEFAULT_GUEST_PREFIX

            # disable guest wifi when guest network is not enabled
            data = client.get(filter=wifi_filter())
            card_count = 0
            while data.find_child("uci.wireless.@wifi-device[%d]" % card_count):
                card_count += 1
            if not guest_enabled and card_count > 0:
                wireless = uci.add(Config("wireless"))
                for i in range(card_count):
                    guest_iface = wireless.add(Section("guest_iface_%d" % i, "wifi-iface"))
                    guest_iface.add(Option("disabled", "1"))

            guest_interfaces = ["guest_turris_%d" % e for e in range(card_count)]

            LanHandler.prepare_guest_configs(
                uci, guest_enabled, network, prefix, guest_interfaces, qos)

            return "edit_config", uci

        lan_form.add_callback(lan_form_cb)

        return lan_form
Пример #8
0
    def get_form(self):
        def approval_preproc_approve_status(nuci_config):
            """Preprocess approval status """
            # try to obtain status from the form data
            if self.data and "approval_status" in self.data:
                return self.data["approval_status"]

            need_item = nuci_config.find_child("uci.updater.approvals.need")
            if not need_item:
                return UpdaterAutoUpdatesHandler.APPROVAL_NO
            if not parse_uci_bool(need_item.value):
                return UpdaterAutoUpdatesHandler.APPROVAL_NO
            seconds_item = nuci_config.find_child(
                "uci.updater.approvals.auto_grant_seconds")
            if not seconds_item:
                return UpdaterAutoUpdatesHandler.APPROVAL_NEEDED

            try:
                hours = int(seconds_item.value)
            except ValueError:
                return UpdaterAutoUpdatesHandler.APPROVAL_NEEDED

            if hours < 0:
                return UpdaterAutoUpdatesHandler.APPROVAL_NEEDED

            return UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT

        form = fapi.ForisForm("updater_eula",
                              self.data,
                              filter=filters.create_config_filter(
                                  "updater", "foris"))
        main_section = form.add_section(name="agree_eula",
                                        title=_(self.userfriendly_title))
        main_section.add_field(
            Radio,
            name="agreed",
            label=_("I agree"),
            default="1",
            args=(("1", _("Use automatic updates (recommended)")),
                  ("0", _("Turn automatic updates off"))),
            nuci_preproc=lambda x: "1"
            if preproc_disabled_to_agreed(x) else "0")
        approval_section = form.add_section(name="approvals",
                                            title=_("Update approvals"))
        main_section.add_section(approval_section)
        approval_section.add_field(
            RadioSingle,
            name=UpdaterAutoUpdatesHandler.APPROVAL_NO,
            group="approval_status",
            label=_("Automatic installation"),
            hint=_("Updates will be installed without user's intervention."),
            nuci_preproc=lambda e: approval_preproc_approve_status(e),
        ).requires("agreed", "1")

        approval_section.add_field(
            RadioSingle,
            name=UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT,
            group="approval_status",
            label=_("Delayed updates"),
            hint=
            _("Updates will be installed with an adjustable delay. You can also approve them manually."
              ),
            nuci_preproc=lambda e: approval_preproc_approve_status(e),
        ).requires("agreed", "1")
        approval_section.add_field(
            Number,
            name="approval_timeout",
            nuci_path="uci.updater.approvals.auto_grant_seconds",
            nuci_preproc=lambda val: int(val.value) / 60 /
            60,  # seconds to hours
            validators=[validators.InRange(1, 24 * 7)],
            default=24,
            required=True,
            min=1,
            max=24 * 7,
        ).requires(UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT,
                   UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT).requires(
                       UpdaterAutoUpdatesHandler.APPROVAL_NO,
                       UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT).requires(
                           UpdaterAutoUpdatesHandler.APPROVAL_NEEDED,
                           UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT)

        approval_section.add_field(
            RadioSingle,
            name=UpdaterAutoUpdatesHandler.APPROVAL_NEEDED,
            group="approval_status",
            label=_("Update approval needed"),
            hint=
            _("You have to approve the updates, otherwise they won't be installed."
              ),
            nuci_preproc=lambda e: approval_preproc_approve_status(e),
        ).requires("agreed", "1")

        def form_cb(data):
            agreed = bool(int(data.get("agreed", "0")))
            approval_status = data.get(UpdaterAutoUpdatesHandler.APPROVAL_NO,
                                       UpdaterAutoUpdatesHandler.APPROVAL_NO)
            auto_grant_seconds = int(data.get("approval_timeout",
                                              24)) * 60 * 60

            uci = Uci()
            updater = uci.add(Config("updater"))
            override = updater.add(Section("override", "override"))
            override.add(Option("disable", not agreed))

            approvals = updater.add_replace(Section("approvals", "approvals"))
            if approval_status == UpdaterAutoUpdatesHandler.APPROVAL_NO:
                approvals.add(Option("need", "0"))
            elif approval_status == UpdaterAutoUpdatesHandler.APPROVAL_NEEDED:
                approvals.add(Option("need", "1"))
            elif approval_status == UpdaterAutoUpdatesHandler.APPROVAL_TIMEOUT:
                approvals.add(Option("need", "1"))
                approvals.add(Option("auto_grant_seconds", auto_grant_seconds))

            return "edit_config", uci

        def save_result_cb(data):
            return "save_result", {
                'agreed': bool(int(data.get("agreed", "0")))
            }

        form.add_callback(form_cb)
        form.add_callback(save_result_cb)
        return form
Пример #9
0
    def get_form(self):
        pkg_list = client.get(filter=filters.updater).find_child("updater").pkg_list

        package_lists_form = fapi.ForisForm("package_lists", self.data,
                                            filter=create_config_filter("updater"))
        package_lists_main = package_lists_form.add_section(
            name="select_package_lists",
            title=_(self.userfriendly_title),
            description=_("Updater is a service that keeps all TurrisOS "
                          "software up to date. Apart from the standard "
                          "installation, you can optionally select lists of "
                          "additional software that'd be installed on the "
                          "router. This software can be selected from the "
                          "following list. "
                          "Please note that only software that is part of "
                          "TurrisOS or that has been installed from a package "
                          "list is maintained by Updater. Software that has "
                          "been installed manually or using opkg is not "
                          "affected.")
        )

        def make_preproc(list_name):
            """Make function for preprocessing value of single pkglist."""
            def preproc(list):
                enabled_names = map(lambda x: x.content, list.children)
                return list_name in enabled_names
            return preproc

        for pkg_list_item in pkg_list:
            package_lists_main.add_field(
                Checkbox,
                name="install_%s" % pkg_list_item.name,
                label=pkg_list_item.title,
                hint=pkg_list_item.description,
                nuci_path="uci.updater.pkglists.lists",
                nuci_preproc=make_preproc(pkg_list_item.name)
            )

        def package_lists_form_cb(data):
            uci = Uci()
            updater = Config("updater")
            uci.add(updater)

            pkglists = Section("pkglists", "pkglists")
            updater.add(pkglists)
            lists = List("lists")

            # create List with selected packages
            i = 0
            for k, v in data.iteritems():
                if v and k.startswith("install_"):
                    lists.add(Value(i, k[8:]))
                    i += 1
            if i == 0:
                pkglists.add_removal(lists)
            else:
                pkglists.add_replace(lists)

            return "edit_config", uci

        def package_lists_run_updater_cb(data):
            logger.info("Checking for updates.")
            client.check_updates()
            return "none", None

        package_lists_form.add_callback(package_lists_form_cb)
        package_lists_form.add_callback(package_lists_run_updater_cb)
        return package_lists_form
Пример #10
0
    def get_form(self):
        notifications_form = fapi.ForisForm("notifications", self.data,
                                            filter=create_config_filter("user_notify"))

        notifications = notifications_form.add_section(name="notifications",
                                                       title=_("Notifications settings"))
        # notifications settings
        notifications.add_field(Checkbox, name="enable_smtp", label=_("Enable notifications"),
                                nuci_path="uci.user_notify.smtp.enable",
                                nuci_preproc=lambda val: bool(int(val.value)),
                                default=False)

        notifications.add_field(
            Radio,
            name="use_turris_smtp",
            label=_("SMTP provider"),
            default="0",
            args=(("1", _("Turris")), ("0", _("Custom"))),
            nuci_path="uci.user_notify.smtp.use_turris_smtp",
            hint=_("If you set SMTP provider to \"Turris\", the servers provided to members of the "
                   "Turris project would be used. These servers do not require any additional "
                   "settings. If you want to set your own SMTP server, please select \"Custom\" "
                   "and enter required settings."))\
            .requires("enable_smtp", True)

        notifications.add_field(
            Textbox,
            name="to",
            label=_("Recipient's email"),
            nuci_path="uci.user_notify.smtp.to",
            nuci_preproc=lambda x: " ".join(map(lambda value: value.content, x.children)),
            hint=_("Email address of recipient. Separate multiple addresses by spaces."),
            required=True
        ).requires("enable_smtp", True)

        # sender's name for CZ.NIC SMTP only
        notifications.add_field(
            Textbox,
            name="sender_name",
            label=_("Sender's name"),
            hint=_("Name of the sender - will be used as a part of the "
                   "sender's email address before the \"at\" sign."),
            nuci_path="uci.user_notify.smtp.sender_name",
            validators=[validators.RegExp(_("Sender's name can contain only "
                                            "alphanumeric characters, dots "
                                            "and underscores."),
                                          r"^[0-9a-zA-Z_\.-]+$")],
            required=True
        )\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "1")

        SEVERITY_OPTIONS = (
            (1, _("Reboot is required")),
            (2, _("Reboot or attention is required")),
            (3, _("Reboot or attention is required or update was installed")),
        )
        notifications.add_field(Dropdown, name="severity", label=_("Importance"),
                                nuci_path="uci.user_notify.notifications.severity",
                                nuci_preproc=lambda val: int(val.value),
                                args=SEVERITY_OPTIONS, default=1)\
            .requires("enable_smtp", True)
        notifications.add_field(Checkbox, name="news", label=_("Send news"),
                                hint=_("Send emails about new features."),
                                nuci_path="uci.user_notify.notifications.news",
                                nuci_preproc=lambda val: bool(int(val.value)),
                                default=False)\
            .requires("enable_smtp", True)

        # SMTP settings (custom server)
        smtp = notifications_form.add_section(name="smtp", title=_("SMTP settings"))
        smtp.add_field(Email, name="from", label=_("Sender address (From)"),
                       hint=_("This is the address notifications are send from."),
                       nuci_path="uci.user_notify.smtp.from",
                       required=True)\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")
        smtp.add_field(Textbox, name="server", label=_("Server address"),
                                nuci_path="uci.user_notify.smtp.server",
                                required=True)\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")
        smtp.add_field(Number, name="port", label=_("Server port"),
                       nuci_path="uci.user_notify.smtp.port",
                       validators=[validators.PositiveInteger()],
                       required=True) \
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")

        SECURITY_OPTIONS = (
            ("none", _("None")),
            ("ssl", _("SSL/TLS")),
            ("starttls", _("STARTTLS")),
        )
        smtp.add_field(Dropdown, name="security", label=_("Security"),
                       nuci_path="uci.user_notify.smtp.security",
                       args=SECURITY_OPTIONS, default="none") \
            .requires("enable_smtp", True).requires("use_turris_smtp", "0")

        smtp.add_field(Textbox, name="username", label=_("Username"),
                       nuci_path="uci.user_notify.smtp.username")\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")
        smtp.add_field(Password, name="password", label=_("Password"),
                       nuci_path="uci.user_notify.smtp.password")\
            .requires("enable_smtp", True)\
            .requires("use_turris_smtp", "0")

        # reboot time
        reboot = notifications_form.add_section(name="reboot",
                                                title=_("Automatic restarts"))
        reboot.add_field(Number, name="delay", label=_("Delay (days)"),
                         hint=_("Number of days that must pass between receiving the request "
                                "for restart and the automatic restart itself."),
                         nuci_path="uci.user_notify.reboot.delay",
                         validators=[validators.PositiveInteger(),
                                     validators.InRange(0, 10)],
                         required=True)
        reboot.add_field(Time, name="reboot_time", label=_("Reboot time"),
                         hint=_("Time of day of automatic reboot in HH:MM format."),
                         nuci_path="uci.user_notify.reboot.time",
                         validators=[validators.Time()],
                         required=True)

        def notifications_form_cb(data):
            uci = Uci()
            user_notify = Config("user_notify")
            uci.add(user_notify)

            smtp = Section("smtp", "smtp")
            user_notify.add(smtp)
            smtp.add(Option("enable", data['enable_smtp']))

            reboot = Section("reboot", "reboot")
            user_notify.add(reboot)
            reboot.add(Option("time", data['reboot_time']))
            reboot.add(Option("delay", data['delay']))

            if data['enable_smtp']:
                smtp.add(Option("use_turris_smtp", data['use_turris_smtp']))
                if data['use_turris_smtp'] == "0":
                    smtp.add(Option("server", data['server']))
                    smtp.add(Option("port", data['port']))
                    smtp.add(Option("username", data['username']))
                    smtp.add(Option("password", data['password']))
                    smtp.add(Option("security", data['security']))
                    smtp.add(Option("from", data['from']))
                else:
                    smtp.add(Option("sender_name", data['sender_name']))
                to = List("to")
                for i, to_item in enumerate(data['to'].split(" ")):
                    if to_item:
                        to.add(Value(i, to_item))
                smtp.add_replace(to)
                # notifications section
                notifications = Section("notifications", "notifications")
                user_notify.add(notifications)
                notifications.add(Option("severity", data['severity']))
                notifications.add(Option("news", data['news']))

            return "edit_config", uci

        notifications_form.add_callback(notifications_form_cb)

        return notifications_form
Пример #11
0
    def get_form(self):
        stats = client.get(filter=filters.stats).find_child("stats")
        if len(stats.data['wireless-cards']) < 1:
            return None

        wifi_form = fapi.ForisForm("wifi", self.data,
                                   filter=create_config_filter("wireless"))
        wifi_main = wifi_form.add_section(
            name="set_wifi",
            title=_(self.userfriendly_title),
            description=_("If you want to use your router as a Wi-Fi access point, enable Wi-Fi "
                          "here and fill in an SSID (the name of the access point) and a "
                          "corresponding password. You can then set up your mobile devices, "
                          "using the QR code available next to the form.")
        )
        wifi_main.add_field(Hidden, name="iface_section", nuci_path="uci.wireless.@wifi-iface[0]",
                            nuci_preproc=lambda val: val.name)
        wifi_main.add_field(Checkbox, name="wifi_enabled", label=_("Enable Wi-Fi"), default=True,
                            nuci_path="uci.wireless.@wifi-iface[0].disabled",
                            nuci_preproc=lambda val: not bool(int(val.value)))
        wifi_main.add_field(Textbox, name="ssid", label=_("SSID"),
                            nuci_path="uci.wireless.@wifi-iface[0].ssid",
                            required=True, validators=validators.ByteLenRange(1, 32))\
            .requires("wifi_enabled", True)
        wifi_main.add_field(Checkbox, name="ssid_hidden", label=_("Hide SSID"), default=False,
                            nuci_path="uci.wireless.@wifi-iface[0].hidden",
                            hint=_("If set, network is not visible when scanning for available "
                                   "networks."))\
            .requires("wifi_enabled", True)

        channels_2g4 = [("auto", _("auto"))]
        channels_5g = []
        for channel in stats.data['wireless-cards'][0]['channels']:
            if channel['disabled']:
                continue
            pretty_channel = "%s (%s MHz)" % (channel['number'], channel['frequency'])
            if channel['frequency'] < 2500:
                channels_2g4.append((str(channel['number']), pretty_channel))
            else:
                channels_5g.append((str(channel['number']), pretty_channel))

        is_dual_band = False
        # hwmode choice for dual band devices
        if len(channels_2g4) > 1 and len(channels_5g) > 1:
            is_dual_band = True
            wifi_main.add_field(Radio, name="hwmode", label=_("Wi-Fi mode"), default="11ng",
                                args=(("11g", "2.4 GHz (g)"), ("11a", "5 GHz (a)")),
                                nuci_path="uci.wireless.radio0.hwmode",
                                nuci_preproc=lambda x: x.value.replace("n", ""),  # old configs used
                                                                                  # 11ng/11na
                                hint=_("The 2.4 GHz band is more widely supported by clients, but "
                                       "tends to have more interference. The 5 GHz band is a newer"
                                       " standard and may not be supported by all your devices. It "
                                       "usually has less interference, but the signal does not "
                                       "carry so well indoors."))\
                .requires("wifi_enabled", True)
        wifi_main.add_field(
            Dropdown, name="htmode", label=_("802.11n mode"),
            args=(("NOHT", _("Disabled")),
                  ("HT20", _("Enabled (20 MHz wide channel)")),
                  ("HT40", _("Enabled (40 MHz wide channel)"))),
            nuci_path="uci.wireless.radio0.htmode",
            hint=_("Change this to adjust 802.11n mode of operation. 802.11n with 40 MHz wide "
                   "channels can yield higher throughput but can cause more interference in the "
                   "network. If you don't know what to choose, use the default option with "
                   "20 MHz wide channel.")
        ).requires("wifi_enabled", True)
        # 2.4 GHz channels
        if len(channels_2g4) > 1:
            field_2g4 = wifi_main.add_field(Dropdown, name="channel2g4", label=_("Network channel"),
                                            default=channels_2g4[0][0], args=channels_2g4,
                                            nuci_path="uci.wireless.radio0.channel")\
                .requires("wifi_enabled", True)
            if is_dual_band:
                field_2g4.requires("hwmode", "11g")
        # 5 GHz channels
        if len(channels_5g) > 1:
            field_5g = wifi_main.add_field(Dropdown, name="channel5g", label=_("Network channel"),
                                           default=channels_5g[0][0], args=channels_5g,
                                           nuci_path="uci.wireless.radio0.channel")\
                .requires("wifi_enabled", True)
            if is_dual_band:
                field_5g.requires("hwmode", "11a")
        wifi_main.add_field(Password, name="key", label=_("Network password"),
                            nuci_path="uci.wireless.@wifi-iface[0].key",
                            required=True,
                            validators=validators.ByteLenRange(8, 63),
                            hint=_("WPA2 pre-shared key, that is required to connect to the "
                                   "network. Minimum length is 8 characters."))\
            .requires("wifi_enabled", True)

        def wifi_form_cb(data):
            uci = Uci()
            wireless = Config("wireless")
            uci.add(wireless)

            iface = Section(data['iface_section'], "wifi-iface")
            wireless.add(iface)
            device = Section("radio0", "wifi-device")
            wireless.add(device)
            # we must toggle both wifi-iface and device
            iface.add(Option("disabled", not data['wifi_enabled']))
            device.add(Option("disabled", not data['wifi_enabled']))
            if data['wifi_enabled']:
                iface.add(Option("ssid", data['ssid']))
                iface.add(Option("hidden", data['ssid_hidden']))
                iface.add(Option("encryption", "psk2+tkip+aes"))
                iface.add(Option("key", data['key']))
                if data.get('channel2g4'):
                    channel = data['channel2g4']
                elif data.get('channel5g'):
                    channel = data['channel5g']
                else:
                    logger.critical("Saving form without Wi-Fi channel: %s", data)
                    channel = "auto"
                hwmode = data.get('hwmode')
                if hwmode:
                    # change hwmode only if we had the choice
                    device.add(Option("hwmode", hwmode))
                device.add(Option("htmode", data['htmode']))
                # channel is in wifi-device section
                device.add(Option("channel", channel))
            else:
                pass  # wifi disabled

            return "edit_config", uci

        wifi_form.add_callback(wifi_form_cb)

        return wifi_form
Пример #12
0
    def get_form(self):
        lan_form = fapi.ForisForm("lan", self.data,
                                  filter=create_config_filter("dhcp", "network"))
        lan_main = lan_form.add_section(
            name="set_lan",
            title=_(self.userfriendly_title),
            description=_("This section contains settings for the local network (LAN). The provided"
                          " defaults are suitable for most networks. <br><strong>Note:</strong> If "
                          "you change the router IP address, all computers in LAN, probably "
                          "including the one you are using now, will need to obtain a <strong>new "
                          "IP address</strong> which does <strong>not</strong> happen <strong>"
                          "immediately</strong>. It is recommended to disconnect and reconnect all "
                          "LAN cables after submitting your changes to force the update. The next "
                          "page will not load until you obtain a new IP from DHCP (if DHCP enabled)"
                          " and you might need to <strong>refresh the page</strong> in your "
                          "browser.")
        )

        lan_main.add_field(Textbox, name="lan_ipaddr", label=_("Router IP address"),
                           nuci_path="uci.network.lan.ipaddr",
                           validators=validators.IPv4(),
                           hint=_("Router's IP address in inner network. Also defines the range of "
                                  "assigned IP addresses."))
        lan_main.add_field(Checkbox, name="dhcp_enabled", label=_("Enable DHCP"),
                           nuci_path="uci.dhcp.lan.ignore",
                           nuci_preproc=lambda val: not bool(int(val.value)), default=True,
                           hint=_("Enable this option to automatically assign IP addresses to "
                                  "the devices connected to the router."))
        lan_main.add_field(Textbox, name="dhcp_min", label=_("DHCP start"),
                           nuci_path="uci.dhcp.lan.start")\
            .requires("dhcp_enabled", True)
        lan_main.add_field(Textbox, name="dhcp_max", label=_("DHCP max leases"),
                           nuci_path="uci.dhcp.lan.limit")\
            .requires("dhcp_enabled", True)

        def lan_form_cb(data):
            uci = Uci()
            config = Config("dhcp")
            uci.add(config)

            dhcp = Section("lan", "dhcp")
            config.add(dhcp)
            # FIXME: this would overwrite any unrelated DHCP options the user might have set.
            # Maybe we should get the current values, scan them and remove selectively the ones
            # with 6 in front of them? Or have some support for higher level of stuff in nuci.
            options = List("dhcp_option")
            options.add(Value(0, "6," + data['lan_ipaddr']))
            dhcp.add_replace(options)
            network = Config("network")
            uci.add(network)
            interface = Section("lan", "interface")
            network.add(interface)
            interface.add(Option("ipaddr", data['lan_ipaddr']))
            if data['dhcp_enabled']:
                dhcp.add(Option("ignore", "0"))
                dhcp.add(Option("start", data['dhcp_min']))
                dhcp.add(Option("limit", data['dhcp_max']))
            else:
                dhcp.add(Option("ignore", "1"))

            return "edit_config", uci

        lan_form.add_callback(lan_form_cb)

        return lan_form
Пример #13
0
    def get_form(self):
        # WAN
        wan_form = fapi.ForisForm("wan", self.data,
                                  filter=create_config_filter("network", "smrtd", "ucollect"))
        wan_main = wan_form.add_section(
            name="set_wan",
            title=_(self.userfriendly_title),
            description=_("Here you specify your WAN port settings. Usually, you can leave this "
                          "options untouched unless instructed otherwise by your internet service "
                          "provider. Also, in case there is a cable or DSL modem connecting your "
                          "router to the network, it is usually not necessary to change this "
                          "setting."))
        WAN_DHCP = "dhcp"
        WAN_STATIC = "static"
        WAN_PPPOE = "pppoe"
        WAN_OPTIONS = (
            (WAN_DHCP, _("DHCP (automatic configuration)")),
            (WAN_STATIC, _("Static IP address (manual configuration)")),
            (WAN_PPPOE, _("PPPoE (for DSL bridges, Modem Turris, etc.)")),
        )

        # protocol
        wan_main.add_field(Dropdown, name="proto", label=_("Protocol"),
                           nuci_path="uci.network.wan.proto",
                           args=WAN_OPTIONS, default=WAN_DHCP)

        # static ipv4
        wan_main.add_field(Textbox, name="ipaddr", label=_("IP address"),
                           nuci_path="uci.network.wan.ipaddr",
                           required=True, validators=validators.IPv4())\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="netmask", label=_("Network mask"),
                           nuci_path="uci.network.wan.netmask",
                           required=True, validators=validators.IPv4Netmask())\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="gateway", label=_("Gateway"),
                           nuci_path="uci.network.wan.gateway",
                           validators=validators.IPv4(),
                           required=True)\
            .requires("proto", WAN_STATIC)

        def extract_dns_item(dns_string, index, default=None):
            try:
                return dns_string.split(" ")[index]
            except IndexError:
                return default

        # DNS servers
        wan_main.add_field(Textbox, name="dns1", label=_("DNS server 1"),
                           nuci_path="uci.network.wan.dns",
                           nuci_preproc=lambda val: extract_dns_item(val.value, 0),
                           validators=validators.AnyIP(),
                           hint=_("DNS server address is not required as the built-in "
                                  "DNS resolver is capable of working without it."))\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="dns2", label=_("DNS server 2"),
                           nuci_path="uci.network.wan.dns",
                           nuci_preproc=lambda val: extract_dns_item(val.value, 1),
                           validators=validators.AnyIP(),
                           hint=_("DNS server address is not required as the built-in "
                                  "DNS resolver is capable of working without it."))\
            .requires("proto", WAN_STATIC)

        # static ipv6
        wan_main.add_field(Checkbox, name="static_ipv6", label=_("Use IPv6"),
                           nuci_path="uci.network.wan.ip6addr",
                           nuci_preproc=lambda val: bool(val.value))\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="ip6addr", label=_("IPv6 address"),
                           nuci_path="uci.network.wan.ip6addr",
                           validators=validators.IPv6Prefix(),
                           hint=_("IPv6 address and prefix length for WAN interface, "
                                  "e.g. 2001:db8:be13:37da::1/64"),
                           required=True)\
            .requires("proto", WAN_STATIC)\
            .requires("static_ipv6", True)
        wan_main.add_field(Textbox, name="ip6gw", label=_("IPv6 gateway"),
                           validators=validators.IPv6(),
                           nuci_path="uci.network.wan.ip6gw")\
            .requires("proto", WAN_STATIC)\
            .requires("static_ipv6", True)
        wan_main.add_field(Textbox, name="ip6prefix", label=_("IPv6 prefix"),
                           validators=validators.IPv6Prefix(),
                           nuci_path="uci.network.wan.ip6prefix",
                           hint=_("Address range for local network, "
                                  "e.g. 2001:db8:be13:37da::/64"))\
            .requires("proto", WAN_STATIC)\
            .requires("static_ipv6", True)

        # xDSL settings
        wan_main.add_field(Textbox, name="username", label=_("PAP/CHAP username"),
                           nuci_path="uci.network.wan.username")\
            .requires("proto", WAN_PPPOE)
        wan_main.add_field(Textbox, name="password", label=_("PAP/CHAP password"),
                           nuci_path="uci.network.wan.password")\
            .requires("proto", WAN_PPPOE)
        wan_main.add_field(Checkbox, name="ppp_ipv6", label=_("Enable IPv6"),
                           nuci_path="uci.network.wan.ipv6",
                           nuci_preproc=lambda val: bool(int(val.value)))\
            .requires("proto", WAN_PPPOE)

        # enable SMRT settings only if smrtd config is present
        has_smrtd = wan_form.nuci_config.find_child("uci.smrtd") is not None

        if has_smrtd:
            wan_main.add_field(Hidden, name="has_smrtd", default="1")
            wan_main.add_field(Checkbox, name="use_smrt", label=_("Use Modem Turris"),
                               nuci_path="uci.smrtd.global.enabled",
                               nuci_preproc=lambda val: bool(int(val.value)),
                               hint=_("Modem Turris (aka SMRT - Small Modem for Router Turris), "
                                      "a simple ADSL/VDSL modem designed specially for router "
                                      "Turris. Enable this option if you have Modem Turris "
                                      "connected to your router."))\
                .requires("proto", WAN_PPPOE)

            def get_smrtd_param(param_name):
                """Helper function for getting SMRTd params for "connections" list."""
                def wrapped(conn_list):
                    # internet connection must be always first list element
                    vlan_id, vpi, vci = (conn_list.children[0].content.split(" ")
                                         if conn_list else (None, None, None))
                    if param_name == "VPI":
                        return vpi
                    elif param_name == "VCI":
                        return vci
                    elif param_name == "VLAN":
                        return vlan_id
                    raise ValueError("Unknown SMRTd connection parameter.")
                return wrapped

            def get_smrtd_vlan(data):
                """Helper function for getting VLAN number from Uci data."""
                ifname = data.find_child("uci.network.wan.ifname")
                if ifname:
                    ifname = ifname.value
                    matches = re.match("eth2.(\d+)", ifname)
                    if matches:
                        return matches.group(1)

                connections = data.find_child("uci.smrtd.eth2.connections")
                result = get_smrtd_param("VLAN")(connections)
                return result

            # 802.1Q VLAN number is 12-bit, 0x0 and 0xFFF reserved
            wan_main.add_field(Textbox, name="smrt_vlan", label=_("xDSL VLAN number"),
                               nuci_preproc=get_smrtd_vlan,
                               validators=[validators.PositiveInteger(),
                                           validators.InRange(1, 4095)],
                               hint=_("VLAN number for your internet connection. Your ISP might "
                                      "have provided you this number. If you have VPI and VCI "
                                      "numbers instead, leave this field empty, a default value "
                                      "will be used automatically."))\
                .requires("use_smrt", True)

            vpi_vci_validator = validators.RequiredWithOtherFields(
                ("smrt_vpi", "smrt_vci"),
                _("Both VPI and VCI must be filled or both must be empty.")
            )

            wan_main.add_field(
                Textbox, name="smrt_vpi", label=_("VPI"),
                nuci_path="uci.smrtd.eth2.connections",
                nuci_preproc=get_smrtd_param("VPI"),
                validators=[validators.PositiveInteger(),
                            validators.InRange(0, 255),
                            vpi_vci_validator],
                hint=_("Virtual Path Identifier (VPI) is a parameter that you might have received "
                       "from your ISP. If you have a VLAN number instead, leave this field empty. "
                       "You need to fill in both VPI and VCI together.")
            ) \
                .requires("use_smrt", True)
            wan_main.add_field(
                Textbox, name="smrt_vci", label=_("VCI"),
                nuci_path="uci.smrtd.eth2.connections",
                nuci_preproc=get_smrtd_param("VCI"),
                validators=[validators.PositiveInteger(),
                            validators.InRange(32, 65535),
                            vpi_vci_validator],
                hint=_("Virtual Circuit Identifier (VCI) is a parameter that you might have "
                       "received from your ISP. If you have a VLAN number instead, leave this "
                       "field empty. You need to fill in both VPI and VCI together.")
            )\
                .requires("use_smrt", True)

        # custom MAC
        wan_main.add_field(Checkbox, name="custom_mac", label=_("Custom MAC address"),
                           nuci_path="uci.network.wan.macaddr",
                           nuci_preproc=lambda val: bool(val.value),
                           hint=_("Useful in cases, when a specific MAC address is required by "
                                  "your internet service provider."))

        wan_main.add_field(Textbox, name="macaddr", label=_("MAC address"),
                           nuci_path="uci.network.wan.macaddr",
                           validators=validators.MacAddress(),
                           hint=_("Separator is a colon, for example 00:11:22:33:44:55"),
                           required=True)\
            .requires("custom_mac", True)

        def wan_form_cb(data):
            uci = Uci()
            network = Config("network")
            uci.add(network)

            wan = Section("wan", "interface")
            network.add(wan)

            wan.add(Option("proto", data['proto']))
            if data['custom_mac'] is True:
                wan.add(Option("macaddr", data['macaddr']))
            else:
                wan.add_removal(Option("macaddr", None))

            ucollect_ifname = "eth2"

            if data['proto'] == WAN_PPPOE:
                wan.add(Option("username", data['username']))
                wan.add(Option("password", data['password']))
                wan.add(Option("ipv6", data['ppp_ipv6']))
                ucollect_ifname = "pppoe-wan"
            elif data['proto'] == WAN_STATIC:
                wan.add(Option("ipaddr", data['ipaddr']))
                wan.add(Option("netmask", data['netmask']))
                wan.add(Option("gateway", data['gateway']))
                dns_string = " ".join([data.get("dns1", ""), data.get("dns2", "")]).strip()
                wan.add(Option("dns", dns_string))
                if data.get("static_ipv6") is True:
                    wan.add(Option("ip6addr", data['ip6addr']))
                    wan.add(Option("ip6gw", data['ip6gw']))
                    wan.add(Option("ip6prefix", data['ip6prefix']))
                else:
                    wan.add_removal(Option("ip6addr", None))
                    wan.add_removal(Option("ip6gw", None))
                    wan.add_removal(Option("ip6prefix", None))

            if has_smrtd:
                smrtd = Config("smrtd")
                uci.add(smrtd)

                smrt_vlan = data.get("smrt_vlan")
                use_smrt = data.get("use_smrt", False)
                wan_ifname = "eth2"

                eth2 = Section("eth2", "interface")
                smrtd.add(eth2)
                eth2.add(Option("name", "eth2"))

                if use_smrt:
                    if not smrt_vlan:
                        # "proprietary" number - and also a common VLAN ID in CZ
                        smrt_vlan = "848"
                    wan_ifname += ".%s" % smrt_vlan

                vpi, vci = data.get("smrt_vpi"), data.get("smrt_vci")
                connections = List("connections")
                if vpi and vci:
                    eth2.add(connections)
                    connections.add(Value(1, "%s %s %s" % (smrt_vlan, vpi, vci)))
                elif use_smrt:
                    eth2.add_removal(connections)

                smrtd_global = Section("global", "global")
                smrtd.add(smrtd_global)
                smrtd_global.add(Option("enabled", use_smrt))

                # set correct ifname for WAN - must be changed when disabling SMRT
                wan.add(Option("ifname", wan_ifname))

            # set interface for ucollect to listen on
            interface_if_name = None
            ucollect_interface0 = wan_form.nuci_config.find_child("uci.ucollect.@interface[0]")
            if ucollect_interface0:
                interface_if_name = ucollect_interface0.name

            ucollect = Config("ucollect")
            uci.add(ucollect)
            interface = Section(interface_if_name, "interface", True)
            ucollect.add(interface)
            interface.add(Option("ifname", ucollect_ifname))

            return "edit_config", uci

        wan_form.add_callback(wan_form_cb)

        return wan_form
Пример #14
0
    def get_form(self):
        # WAN
        wan_form = fapi.ForisForm("wan",
                                  self.data,
                                  filter=create_config_filter(
                                      "network", "smrtd", "ucollect"))
        wan_main = wan_form.add_section(
            name="set_wan",
            title=_(self.userfriendly_title),
            description=
            _("Here you specify your WAN port settings. Usually, you can leave this "
              "options untouched unless instructed otherwise by your internet service "
              "provider. Also, in case there is a cable or DSL modem connecting your "
              "router to the network, it is usually not necessary to change this "
              "setting."))
        WAN_DHCP = "dhcp"
        WAN_STATIC = "static"
        WAN_PPPOE = "pppoe"
        WAN_OPTIONS = (
            (WAN_DHCP, _("DHCP (automatic configuration)")),
            (WAN_STATIC, _("Static IP address (manual configuration)")),
            (WAN_PPPOE, _("PPPoE (for DSL bridges, Modem Turris, etc.)")),
        )

        WAN6_NONE = "none"
        WAN6_DHCP = "dhcpv6"
        WAN6_STATIC = "static"

        WAN6_OPTIONS = (
            (WAN6_DHCP, _("DHCPv6 (automatic configuration)")),
            (WAN6_STATIC, _("Static IP address (manual configuration)")),
        )

        if not self.hide_no_wan:
            WAN6_OPTIONS = ((WAN6_NONE, _("Disable IPv6")), ) + WAN6_OPTIONS

        # protocol
        wan_main.add_field(Dropdown,
                           name="proto",
                           label=_("IPv4 protocol"),
                           nuci_path="uci.network.wan.proto",
                           args=WAN_OPTIONS,
                           default=WAN_DHCP)

        # static ipv4
        wan_main.add_field(Textbox, name="ipaddr", label=_("IP address"),
                           nuci_path="uci.network.wan.ipaddr",
                           required=True, validators=validators.IPv4())\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="netmask", label=_("Network mask"),
                           nuci_path="uci.network.wan.netmask",
                           required=True, validators=validators.IPv4Netmask())\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="gateway", label=_("Gateway"),
                           nuci_path="uci.network.wan.gateway",
                           validators=validators.IPv4(),
                           required=True)\
            .requires("proto", WAN_STATIC)

        def extract_dns_item(dns_option, index, default=None):
            if isinstance(dns_option, List):
                dns_list = [e.content for e in dns_option.children]
            elif isinstance(dns_option, Option):
                dns_list = dns_option.value.split(" ")
            else:
                return default

            # Server with higher priority should be last
            dns_list.reverse()

            try:
                return dns_list[index]
            except IndexError:
                return default

        # DNS servers
        wan_main.add_field(Textbox, name="dns1", label=_("DNS server 1"),
                           nuci_path="uci.network.wan.dns",
                           nuci_preproc=lambda val: extract_dns_item(val, 0),
                           validators=validators.AnyIP(),
                           hint=_("DNS server address is not required as the built-in "
                                  "DNS resolver is capable of working without it."))\
            .requires("proto", WAN_STATIC)
        wan_main.add_field(Textbox, name="dns2", label=_("DNS server 2"),
                           nuci_path="uci.network.wan.dns",
                           nuci_preproc=lambda val: extract_dns_item(val, 1),
                           validators=validators.AnyIP(),
                           hint=_("DNS server address is not required as the built-in "
                                  "DNS resolver is capable of working without it."))\
            .requires("proto", WAN_STATIC)

        # xDSL settings
        wan_main.add_field(Textbox, name="username", label=_("PAP/CHAP username"),
                           nuci_path="uci.network.wan.username")\
            .requires("proto", WAN_PPPOE)
        wan_main.add_field(Textbox, name="password", label=_("PAP/CHAP password"),
                           nuci_path="uci.network.wan.password")\
            .requires("proto", WAN_PPPOE)

        # IPv6 configuration
        wan_main.add_field(Dropdown,
                           name="wan6_proto",
                           label=_("IPv6 protocol"),
                           args=WAN6_OPTIONS,
                           default=WAN6_NONE,
                           nuci_path="uci.network.wan6.proto")
        wan_main.add_field(Textbox, name="ip6addr", label=_("IPv6 address"),
                           nuci_path="uci.network.wan6.ip6addr",
                           validators=validators.IPv6Prefix(),
                           hint=_("IPv6 address and prefix length for WAN interface, "
                                  "e.g. 2001:db8:be13:37da::1/64"),
                           required=True)\
            .requires("wan6_proto", WAN6_STATIC)
        wan_main.add_field(Textbox, name="ip6gw", label=_("IPv6 gateway"),
                           validators=validators.IPv6(),
                           nuci_path="uci.network.wan6.ip6gw")\
            .requires("wan6_proto", WAN6_STATIC)
        wan_main.add_field(Textbox, name="ip6prefix", label=_("IPv6 prefix"),
                           validators=validators.IPv6Prefix(),
                           nuci_path="uci.network.wan6.ip6prefix",
                           hint=_("Address range for local network, "
                                  "e.g. 2001:db8:be13:37da::/64"))\
            .requires("wan6_proto", WAN6_STATIC)

        # enable SMRT settings only if smrtd config is present
        has_smrtd = wan_form.nuci_config.find_child("uci.smrtd") is not None

        if has_smrtd:
            wan_main.add_field(Hidden, name="has_smrtd", default="1")
            wan_main.add_field(Checkbox, name="use_smrt", label=_("Use Modem Turris"),
                               nuci_path="uci.smrtd.global.enabled",
                               nuci_preproc=lambda val: bool(int(val.value)),
                               hint=_("Modem Turris (aka SMRT - Small Modem for Router Turris), "
                                      "a simple ADSL/VDSL modem designed specially for router "
                                      "Turris. Enable this option if you have Modem Turris "
                                      "connected to your router."))\
                .requires("proto", WAN_PPPOE)

            def get_smrtd_param(param_name):
                """Helper function for getting SMRTd params for "connections" list."""
                def wrapped(conn_list):
                    # internet connection must be always first list element
                    vlan_id, vpi, vci = (
                        conn_list.children[0].content.split(" ")
                        if conn_list else (None, None, None))
                    if param_name == "VPI":
                        return vpi
                    elif param_name == "VCI":
                        return vci
                    elif param_name == "VLAN":
                        return vlan_id
                    raise ValueError("Unknown SMRTd connection parameter.")

                return wrapped

            def get_smrtd_vlan(data):
                """Helper function for getting VLAN number from Uci data."""
                ifname = data.find_child("uci.network.wan.ifname")
                if ifname:
                    ifname = ifname.value
                    matches = re.match("%s.(\d+)" % self.wan_ifname, ifname)
                    if matches:
                        return matches.group(1)

                connections = data.find_child("uci.smrtd.%s.connections" %
                                              self.wan_ifname)
                result = get_smrtd_param("VLAN")(connections)
                return result

            # 802.1Q VLAN number is 12-bit, 0x0 and 0xFFF reserved
            wan_main.add_field(Textbox, name="smrt_vlan", label=_("xDSL VLAN number"),
                               nuci_preproc=get_smrtd_vlan,
                               validators=[validators.PositiveInteger(),
                                           validators.InRange(1, 4095)],
                               hint=_("VLAN number for your internet connection. Your ISP might "
                                      "have provided you this number. If you have VPI and VCI "
                                      "numbers instead, leave this field empty, a default value "
                                      "will be used automatically."))\
                .requires("use_smrt", True)

            vpi_vci_validator = validators.RequiredWithOtherFields(
                ("smrt_vpi", "smrt_vci"),
                _("Both VPI and VCI must be filled or both must be empty."))

            wan_main.add_field(
                Textbox, name="smrt_vpi", label=_("VPI"),
                nuci_path="uci.smrtd.%s.connections" % self.wan_ifname,
                nuci_preproc=get_smrtd_param("VPI"),
                validators=[validators.PositiveInteger(),
                            validators.InRange(0, 255),
                            vpi_vci_validator],
                hint=_("Virtual Path Identifier (VPI) is a parameter that you might have received "
                       "from your ISP. If you have a VLAN number instead, leave this field empty. "
                       "You need to fill in both VPI and VCI together.")
            ) \
                .requires("use_smrt", True)
            wan_main.add_field(
                Textbox, name="smrt_vci", label=_("VCI"),
                nuci_path="uci.smrtd.%s.connections" % self.wan_ifname,
                nuci_preproc=get_smrtd_param("VCI"),
                validators=[validators.PositiveInteger(),
                            validators.InRange(32, 65535),
                            vpi_vci_validator],
                hint=_("Virtual Circuit Identifier (VCI) is a parameter that you might have "
                       "received from your ISP. If you have a VLAN number instead, leave this "
                       "field empty. You need to fill in both VPI and VCI together.")
            )\
                .requires("use_smrt", True)

        # custom MAC
        wan_main.add_field(
            Checkbox,
            name="custom_mac",
            label=_("Custom MAC address"),
            nuci_path="uci.network.wan.macaddr",
            nuci_preproc=lambda val: bool(val.value),
            hint=_(
                "Useful in cases, when a specific MAC address is required by "
                "your internet service provider."))

        wan_main.add_field(Textbox, name="macaddr", label=_("MAC address"),
                           nuci_path="uci.network.wan.macaddr",
                           validators=validators.MacAddress(),
                           hint=_("Separator is a colon, for example 00:11:22:33:44:55"),
                           required=True)\
            .requires("custom_mac", True)

        def wan_form_cb(data):
            uci = Uci()
            network = Config("network")
            uci.add(network)

            wan = Section("wan", "interface")
            network.add(wan)

            wan.add(Option("proto", data['proto']))
            if data['custom_mac'] is True:
                wan.add(Option("macaddr", data['macaddr']))
            else:
                wan.add_removal(Option("macaddr", None))

            ucollect_ifname = self.wan_ifname

            if data['proto'] == WAN_PPPOE:
                wan.add(Option("username", data['username']))
                wan.add(Option("password", data['password']))
                wan.add(Option("ipv6",
                               data.get("wan6_proto") is not WAN6_NONE))
                ucollect_ifname = "pppoe-wan"
            elif data['proto'] == WAN_STATIC:
                wan.add(Option("ipaddr", data['ipaddr']))
                wan.add(Option("netmask", data['netmask']))
                wan.add(Option("gateway", data['gateway']))
                dns_list = List("dns")
                dns2 = data.get("dns2", None)
                if dns2:
                    dns_list.add(Value(0, dns2))
                dns1 = data.get("dns1", None)
                if dns1:
                    dns_list.add(Value(
                        1,
                        dns1))  # dns with higher priority should be added last
                if not dns_list.children:
                    wan.add_removal(dns_list)
                else:
                    wan.add_replace(dns_list)

            # IPv6 configuration
            wan6 = Section("wan6", "interface")
            network.add(wan6)
            wan6.add(Option("ifname", "@wan"))
            wan6.add(Option("proto", data['wan6_proto']))

            if data.get("wan6_proto") == WAN6_STATIC:
                wan6.add(Option("ip6addr", data['ip6addr']))
                wan6.add(Option("ip6gw", data['ip6gw']))
                wan6.add(Option("ip6prefix", data['ip6prefix']))
            else:
                wan6.add_removal(Option("ip6addr", None))
                wan6.add_removal(Option("ip6gw", None))
                wan6.add_removal(Option("ip6prefix", None))

            if has_smrtd:
                smrtd = Config("smrtd")
                uci.add(smrtd)

                smrt_vlan = data.get("smrt_vlan")
                use_smrt = data.get("use_smrt", False)

                wan_if = Section(self.wan_ifname, "interface")
                smrtd.add(wan_if)
                wan_if.add(Option("name", self.wan_ifname))

                if use_smrt:
                    if not smrt_vlan:
                        # "proprietary" number - and also a common VLAN ID in CZ
                        smrt_vlan = "848"
                        self.wan_ifname += ".%s" % smrt_vlan

                vpi, vci = data.get("smrt_vpi"), data.get("smrt_vci")
                connections = List("connections")
                if vpi and vci:
                    wan_if.add(connections)
                    connections.add(
                        Value(1, "%s %s %s" % (smrt_vlan, vpi, vci)))
                elif use_smrt:
                    wan_if.add_removal(connections)

                smrtd_global = Section("global", "global")
                smrtd.add(smrtd_global)
                smrtd_global.add(Option("enabled", use_smrt))

                # set correct ifname for WAN - must be changed when disabling SMRT
                wan.add(Option("ifname", self.wan_ifname))

            # set interface for ucollect to listen on
            interface_if_name = None
            ucollect_interface0 = wan_form.nuci_config.find_child(
                "uci.ucollect.@interface[0]")
            if ucollect_interface0:
                interface_if_name = ucollect_interface0.name

            ucollect = Config("ucollect")
            uci.add(ucollect)
            interface = Section(interface_if_name, "interface", True)
            ucollect.add(interface)
            interface.add(Option("ifname", ucollect_ifname))

            return "edit_config", uci

        wan_form.add_callback(wan_form_cb)

        return wan_form
Пример #15
0
    def get_form(self):
        ucollect_form = fapi.ForisForm("ucollect", self.data,
                                       filter=filters.create_config_filter("ucollect"))
        fakes = ucollect_form.add_section(
            name="fakes",
            title=_("Emulated services"),
            description=_("One of uCollect's features is emulation of some commonly abused "
                          "services. If this function is enabled, uCollect is listening for "
                          "incoming connection attempts to these services. Enabling of the "
                          "emulated services has no effect if another service is already "
                          "listening on its default port (port numbers are listed below).")
        )

        SERVICES_OPTIONS = (
            ("23tcp", _("Telnet (23/TCP)")),
        )

        def get_enabled_services(disabled_list):
            disabled_services = map(lambda value: value.content, disabled_list.children)
            res = [x[0] for x in SERVICES_OPTIONS if x[0] not in disabled_services]
            return res

        fakes.add_field(
            MultiCheckbox,
            name="services",
            label=_("Emulated services"),
            args=SERVICES_OPTIONS,
            multifield=True,
            nuci_path="uci.ucollect.fakes.disable",
            nuci_preproc=get_enabled_services,
            default=[x[0] for x in SERVICES_OPTIONS]
        )

        fakes.add_field(
            Checkbox,
            name="log_credentials",
            label=_("Collect credentials"),
            hint=_("If this option is enabled, user names and passwords are collected "
                   "and sent to server in addition to the IP address of the client."),
            nuci_path="uci.ucollect.fakes.log_credentials",
            nuci_preproc=parse_uci_bool
        )

        def ucollect_form_cb(data):
            uci = Uci()
            ucollect = Config("ucollect")
            uci.add(ucollect)

            fakes = Section("fakes", "fakes")
            ucollect.add(fakes)

            disable = List("disable")

            disabled_services = [x[0] for x in SERVICES_OPTIONS
                                 if x[0] not in data['services']]
            for i, service in enumerate(disabled_services):
                disable.add(Value(i, service))

            if len(disabled_services):
                fakes.add_replace(disable)
            else:
                # TODO: workaround for Nuci bug #3984 - remove when fixed
                fakes_section = ucollect_form.nuci_config.find_child("uci.ucollect.fakes")
                if fakes_section:
                    fakes.add_removal(disable)

            fakes.add(Option("log_credentials", data['log_credentials']))

            return "edit_config", uci

        ucollect_form.add_callback(ucollect_form_cb)

        return ucollect_form
Пример #16
0
    def get_form(self):
        form = fapi.ForisForm("enable_collection",
                              self.data,
                              filter=filters.create_config_filter(
                                  "foris", "updater"))

        section = form.add_section(
            name="collection_toggle",
            title=_(self.userfriendly_title),
        )
        section.add_field(Checkbox,
                          name="enable",
                          label=_("Enable data collection"),
                          nuci_path="uci.foris.eula.agreed_collect",
                          nuci_preproc=lambda val: bool(int(val.value)))

        def form_cb(data):
            uci = build_option_uci_tree("foris.eula.agreed_collect", "config",
                                        data.get("enable"))
            return "edit_config", uci

        def adjust_lists_cb(data):
            uci = Uci()
            # All enabled lists
            enabled_lists = map(
                lambda x: x.content,
                form.nuci_config.find_child(
                    "uci.updater.pkglists.lists").children)
            # Lists that do not need agreement
            enabled_no_agree = filter(lambda x: not x.startswith("i_agree_"),
                                      enabled_lists)
            # Lists that need agreement
            enabled_i_agree = filter(lambda x: x.startswith("i_agree_"),
                                     enabled_lists)

            # Always install lists that do not need agreement - create a copy of the list
            installed_lists = enabled_no_agree[:]
            logger.warning("no agree: %s", enabled_no_agree)
            logger.warning("installed: %s", installed_lists)
            if data.get("enable", False):
                # Include i_agree lists if user agreed with EULA
                installed_lists.extend(enabled_i_agree)
                # Add main data collection list if it's not present
                logger.warning(installed_lists)
                logger.warning("i_agree_datacollect" not in installed_lists)
                logger.warning("i_agree_datacollect" in installed_lists)
                if "i_agree_datacollect" not in installed_lists:
                    logger.warning("appending")
                    installed_lists.append("i_agree_datacollect")
            logger.warning("saving %s", installed_lists)
            # Reconstruct list of package lists
            updater = uci.add(Config("updater"))
            pkglists = updater.add(Section("pkglists", "pkglists"))
            lists = List("lists")
            for i, name in enumerate(installed_lists):
                lists.add(Value(i, name))

            # If there's anything to add, replace the list, otherwise remove it completely
            if len(installed_lists) > 0:
                pkglists.add_replace(lists)
            else:
                pkglists.add_removal(lists)

            return "edit_config", uci

        def run_updater_cb(data):
            logger.info("Checking for updates.")
            client.check_updates()
            return "none", None

        form.add_callback(form_cb)
        form.add_callback(adjust_lists_cb)
        form.add_callback(run_updater_cb)

        return form
Пример #17
0
    def get_form(self):
        pkg_list = lazy_cache.nuci_updater.pkg_list

        updater_form = fapi.ForisForm("package_lists",
                                      self.data,
                                      filter=filters.create_config_filter(
                                          "updater", "foris"))
        updater_main = updater_form.add_section(
            name="updater_section",
            title=_(self.userfriendly_title),
            description=_("Updater is a service that keeps all TurrisOS "
                          "software up to date. Apart from the standard "
                          "installation, you can optionally select lists of "
                          "additional software that'd be installed on the "
                          "router. This software can be selected from the "
                          "following list. "
                          "Please note that only software that is part of "
                          "TurrisOS or that has been installed from a package "
                          "list is maintained by Updater. Software that has "
                          "been installed manually or using opkg is not "
                          "affected."))

        package_lists_main = updater_main.add_section(
            name="select_package_lists",
            title=None,
        )

        language_lists_main = updater_main.add_section(
            name="select_languages",
            title=_(
                "If you want to use other language than English you can select it from the "
                "following list:"))

        def make_preproc(list_name):
            """Make function for preprocessing value of single pkglist."""
            def preproc(list):
                enabled_names = map(lambda x: x.content, list.children)
                return list_name in enabled_names

            return preproc

        if not contract_valid():
            agreed_collect_opt = updater_form.nuci_config \
                .find_child("uci.foris.eula.agreed_collect")
            agreed_collect = agreed_collect_opt and bool(
                int(agreed_collect_opt.value))
        else:
            agreed_collect = True

        for pkg_list_item in pkg_list:
            if not contract_valid():
                if pkg_list_item.name == "i_agree_datacollect":
                    # This has special meaning - it's affected by foris.eula.agreed_collect
                    continue
                elif pkg_list_item.name.startswith(
                        "i_agree_") and not agreed_collect:
                    # Data collection is not enabled - do not show items prefixed i_agree_
                    continue
            package_lists_main.add_field(
                Checkbox,
                name="install_%s" % pkg_list_item.name,
                label=pkg_list_item.title,
                hint=pkg_list_item.description,
                nuci_path="uci.updater.pkglists.lists",
                nuci_preproc=make_preproc(pkg_list_item.name))

        def make_lang_preproc(lang_name):
            """Make function for preprocessing value of single language."""
            def preproc(lang):
                enabled_langs = map(lambda x: x.content, lang.children) \
                    if lang and lang.children else []
                return lang_name in enabled_langs

            return preproc

        with open(L10N_SUPPORTED_PATH) as f:
            supported_languages = [e.strip() for e in f.readlines()]
        for language in supported_languages:
            language_lists_main.add_field(
                Checkbox,
                name="language_%s" % language,
                label=language,
                nuci_path="uci.updater.l10n.langs",
                nuci_preproc=make_lang_preproc(language),
            )

        def package_lists_form_cb(data):
            uci = Uci()
            updater = Config("updater")
            uci.add(updater)

            pkglists = Section("pkglists", "pkglists")
            updater.add(pkglists)
            new_package_list = List("lists")

            langlists = Section("l10n", "l10n")
            updater.add(langlists)
            new_language_list = List("langs")

            # create List with selected packages
            i = 0
            for k, v in [(k, v) for k, v in data.iteritems()
                         if v and k.startswith("install_")]:
                new_package_list.add(Value(i, k[8:]))
                i += 1
            # If user agreed with data collection, add i_agree_datacollect list
            if agreed_collect:
                new_package_list.add(Value(i, "i_agree_datacollect"))
                i += 1
            if i == 0:
                pkglists.add_removal(new_package_list)
            else:
                pkglists.add_replace(new_package_list)

            # create language list
            i = 0
            for k, v in [(k, v) for k, v in data.iteritems()
                         if v and k.startswith("language_")]:
                new_language_list.add(Value(i, k[9:]))
                i += 1
            if i == 0:
                langlists.add_removal(new_language_list)
            else:
                langlists.add_replace(new_language_list)

            return "edit_config", uci

        def package_lists_run_updater_cb(data):
            logger.info("Checking for updates.")
            client.check_updates()
            return "none", None

        updater_form.add_callback(package_lists_form_cb)
        updater_form.add_callback(package_lists_run_updater_cb)
        return updater_form