Ejemplo n.º 1
0
    def get_form(self):
        data = current_state.backend.perform("sample", "get_slices")

        if self.data:
            # Update from post (used when the form is updated via ajax)
            data.update(self.data)

        form = fapi.ForisForm("sample", data)
        section = form.add_section(
            name="main_section",
            title=self.userfriendly_title,
        )
        # _() translates the string immediatelly
        # it is also used for detecting translations during foris_make_messages cmd
        section.add_field(Number,
                          name="slices",
                          label=_("Number of slices"),
                          required=True,
                          validators=validators.InRange(2, 15))

        def form_cb(data):
            res = current_state.backend.perform(
                "sample", "set_slices", {"slices": int(data["slices"])})

            return "save_result", res  # store {"result": ...} to be used in SamplePluginPage save() method

        form.add_callback(form_cb)
        return form
Ejemplo n.º 2
0
    def get_form(self):
        data = copy.deepcopy(self.backend_data)

        data["enabled"] = "1" if data["enabled"] else "0"
        data["approval_status"] = data["approval_settings"]["status"]
        if "delay" in data["approval_settings"]:
            data["approval_delay"] = data["approval_settings"]["delay"]
        for userlist in [e for e in data['user_lists'] if not e["hidden"]]:
            data["install_%s" % userlist["name"]] = userlist["enabled"]
        for lang in data["languages"]:
            data["language_%s" % lang["code"]] = lang["enabled"]

        if self.data:
            # Update from post
            data.update(self.data)
            self.updater_enabled = True if data["enabled"] == "1" else False
            self.approval_setting_status = data["approval_status"]
            self.approval_setting_delay = data.get("approval_delay",
                                                   self.APPROVAL_DEFAULT_DELAY)

        form = fapi.ForisForm("updater", data)
        main_section = form.add_section(
            name="main",
            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 bundles 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."))
        main_section.add_field(
            Radio,
            name="enabled",
            label=_("I agree"),
            default="1",
            args=(("1", _("Use automatic updates (recommended)")),
                  ("0", _("Turn automatic updates off"))),
        )

        approval_section = main_section.add_section(
            name="approvals", title=_("Update approvals"))
        approval_section.add_field(
            RadioSingle,
            name=UpdaterHandler.APPROVAL_NO,
            group="approval_status",
            label=_("Automatic installation"),
            hint=_("Updates will be installed without user's intervention."),
            default=data["approval_status"],
        )

        approval_section.add_field(
            RadioSingle,
            name=UpdaterHandler.APPROVAL_TIMEOUT,
            group="approval_status",
            label=_("Delayed updates"),
            hint=_("Updates will be installed with an adjustable delay. "
                   "You can also approve them manually."),
            default=data["approval_status"],
        )
        approval_section.add_field(
            Number,
            name="approval_delay",
            validators=[validators.InRange(1, 24 * 7)],
            default=UpdaterHandler.APPROVAL_DEFAULT_DELAY,
            min=1,
            max=24 * 7,
            required=True,
        ).requires(UpdaterHandler.APPROVAL_TIMEOUT,
                   UpdaterHandler.APPROVAL_TIMEOUT).requires(
                       UpdaterHandler.APPROVAL_NO,
                       UpdaterHandler.APPROVAL_TIMEOUT).requires(
                           UpdaterHandler.APPROVAL_NEEDED,
                           UpdaterHandler.APPROVAL_TIMEOUT)

        approval_section.add_field(
            RadioSingle,
            name=UpdaterHandler.APPROVAL_NEEDED,
            group="approval_status",
            label=_("Update approval needed"),
            hint=
            _("You have to approve the updates, otherwise they won't be installed."
              ),
            default=data["approval_status"],
        )

        package_lists_main = main_section.add_section(
            name="select_package_lists",
            title=None,
        )
        for userlist in [e for e in data['user_lists'] if not e["hidden"]]:
            package_lists_main.add_field(Checkbox,
                                         name="install_%s" % userlist["name"],
                                         label=userlist["title"],
                                         hint=userlist["msg"]).requires(
                                             "enabled", "1")

        language_lists_main = main_section.add_section(
            name="select_languages",
            title=_(
                "If you want to use other language than English you can select it from the "
                "following list:"))
        for lang in data["languages"]:
            language_lists_main.add_field(Checkbox,
                                          name="language_%s" % lang["code"],
                                          label=lang["code"].upper())

        if self.backend_data["approval"]["present"]:
            # field for hidden approval
            current_approval_section = main_section.add_section(
                name="current_approval", title="")
            current_approval_section.add_field(
                Hidden,
                name="approval-id",
                default=self.backend_data["approval"]["hash"])

        # this will be filled according to action
        main_section.add_field(Hidden, name="target")

        def form_cb(data):
            data["enabled"] = True if data["enabled"] == "1" else False
            if data["enabled"] and data["target"] == "save":
                if data[self.APPROVAL_NEEDED] == self.APPROVAL_NEEDED:
                    data["approval_settings"] = {
                        "status": self.APPROVAL_NEEDED
                    }
                elif data[self.APPROVAL_TIMEOUT] == self.APPROVAL_TIMEOUT:
                    data["approval_settings"] = {
                        "status": self.APPROVAL_TIMEOUT
                    }
                    data["approval_settings"]["delay"] = int(
                        data["approval_delay"])
                elif data[self.APPROVAL_NO] == self.APPROVAL_NO:
                    data["approval_settings"] = {"status": self.APPROVAL_NO}

                if self.agreed_collect:
                    data["enabled"] = True

                languages = [
                    k[9:] for k, v in data.items()
                    if v and k.startswith("language_")
                ]
                user_lists = [
                    k[8:] for k, v in data.items()
                    if v and k.startswith("install_")
                ]
                # merge with enabled hidden user lists
                user_lists += [
                    e["name"] for e in self.backend_data["user_lists"]
                    if e["hidden"] and e["enabled"]
                ]

                res = current_state.backend.perform(
                    "updater", "update_settings", {
                        "enabled": True,
                        "approval_settings": data["approval_settings"],
                        "user_lists": user_lists,
                        "languages": languages,
                    })
            elif data["enabled"] and data["target"] in ["grant", "deny"]:
                res = current_state.backend.perform(
                    "updater", "resolve_approval", {
                        "hash": data["approval-id"],
                        "solution": data["target"]
                    })
            else:
                res = current_state.backend.perform("updater",
                                                    "update_settings", {
                                                        "enabled": False,
                                                    })

            res["target"] = data["target"]
            return "save_result", res

        form.add_callback(form_cb)
        return form
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
0
Archivo: wan.py Proyecto: CZ-NIC/foris
    def get_form(self):
        data = WanHandler._convert_backend_data_to_form_data(self.backend_data)

        if self.data:
            # Update from post
            data.update(self.data)

        # WAN
        wan_form = fapi.ForisForm("wan", data)
        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 these "
              "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_6TO4 = "6to4"
        WAN6_6IN4 = "6in4"

        WAN6_OPTIONS = (
            (WAN6_DHCP, _("DHCPv6 (automatic configuration)")),
            (WAN6_STATIC, _("Static IP address (manual configuration)")),
            (WAN6_6TO4, _("6to4 (public IPv4 address required)")),
            (WAN6_6IN4, _("6in4 (public IPv4 address required)")),
        )

        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"),
                           args=WAN_OPTIONS,
                           default=WAN_DHCP)

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

        wan_main.add_field(
            Textbox,
            name="hostname",
            label=_("DHCP hostname"),
            validators=validators.Domain(),
            hint=_("Hostname which will be provided to DHCP server."),
        ).requires("proto", WAN_DHCP)

        # DNS servers
        wan_main.add_field(
            Textbox,
            name="ipv4_dns1",
            label=_("DNS server 1 (IPv4)"),
            validators=validators.IPv4(),
            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="ipv4_dns2",
            label=_("DNS server 2 (IPv4)"),
            validators=validators.IPv4(),
            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"),
            required=True,
        ).requires("proto", WAN_PPPOE)
        wan_main.add_field(
            PasswordWithHide,
            name="password",
            label=_("PAP/CHAP password"),
            required=True,
        ).requires("proto", WAN_PPPOE)

        # IPv6 configuration
        wan_main.add_field(
            Dropdown,
            name="wan6_proto",
            label=_("IPv6 protocol"),
            args=WAN6_OPTIONS,
            default=WAN6_NONE,
        )
        wan_main.add_field(
            Textbox,
            name="ip6addr",
            label=_("IPv6 address"),
            validators=validators.IPv6Prefix(),
            required=True,
            hint=_("IPv6 address and prefix length for WAN interface, "
                   "e.g. 2001:db8:be13:37da::1/64"),
        ).requires("wan6_proto", WAN6_STATIC)
        wan_main.add_field(
            Textbox,
            name="ip6gw",
            label=_("IPv6 gateway"),
            validators=validators.IPv6(),
            required=True,
        ).requires("wan6_proto", WAN6_STATIC)
        wan_main.add_field(
            Textbox,
            name="ip6prefix",
            label=_("IPv6 prefix"),
            validators=validators.IPv6Prefix(),
            hint=_("Address range for local network, "
                   "e.g. 2001:db8:be13:37da::/64"),
        ).requires("wan6_proto", WAN6_STATIC)
        # DNS servers
        wan_main.add_field(
            Textbox,
            name="ipv6_dns1",
            label=_("DNS server 1 (IPv6)"),
            validators=validators.IPv6(),
            hint=_("DNS server address is not required as the built-in "
                   "DNS resolver is capable of working without it."),
        ).requires("wan6_proto", WAN6_STATIC)
        wan_main.add_field(
            Textbox,
            name="ipv6_dns2",
            label=_("DNS server 2 (IPv6)"),
            validators=validators.IPv6(),
            hint=_("DNS server address is not required as the built-in "
                   "DNS resolver is capable of working without it."),
        ).requires("wan6_proto", WAN6_STATIC)
        wan_main.add_field(
            Textbox,
            name="ip6duid",
            label=_("Custom DUID"),
            validators=validators.Duid(),
            placeholder=self.status_data["last_seen_duid"],
            hint=_("DUID which will be provided to the DHCPv6 server."),
        ).requires("wan6_proto", WAN6_DHCP)
        wan_main.add_field(
            Textbox,
            name="6to4_ipaddr",
            label=_("Public IPv4"),
            validators=validators.IPv4(),
            hint=
            _("In order to use 6to4 protocol, you might need to specify your public IPv4 "
              "address manually (e.g. when your WAN interface has a private address which "
              "is mapped to public IP)."),
            placeholder=_("use autodetection"),
            required=False,
        ).requires("wan6_proto", WAN6_6TO4)
        wan_main.add_field(
            Textbox,
            name="6in4_server_ipv4",
            label=_("Provider IPv4"),
            validators=validators.IPv4(),
            hint=
            _("This address will be used as a endpoint of the tunnel on the provider's side."
              ),
            required=True,
        ).requires("wan6_proto", WAN6_6IN4)
        wan_main.add_field(
            Textbox,
            name="6in4_ipv6_prefix",
            label=_("Routed IPv6 prefix"),
            validators=validators.IPv6Prefix(),
            hint=_("IPv6 addresses which will be routed to your network."),
            required=True,
        ).requires("wan6_proto", WAN6_6IN4)
        wan_main.add_field(
            Number,
            name="6in4_mtu",
            label=_("MTU"),
            validators=validators.InRange(1280, 1500),
            hint=_("Maximum Transmission Unit in the tunnel (in bytes)."),
            required=True,
            default="1480",
        ).requires("wan6_proto", WAN6_6IN4)
        wan_main.add_field(
            Checkbox,
            name="6in4_dynamic_enabled",
            label=_("Dynamic IPv4 handling"),
            hint=_(
                "Some tunnel providers allow you to have public dynamic IPv4. "
                "Note that you need to fill in some extra fields to make it work."
            ),
            default=False,
        ).requires("wan6_proto", WAN6_6IN4)
        wan_main.add_field(
            Textbox,
            name="6in4_tunnel_id",
            label=_("Tunnel ID"),
            validators=validators.NotEmpty(),
            hint=_(
                "ID of your tunnel which was assigned to you by the provider."
            ),
            required=True,
        ).requires("6in4_dynamic_enabled", True)
        wan_main.add_field(
            Textbox,
            name="6in4_username",
            label=_("Username"),
            validators=validators.NotEmpty(),
            hint=
            _("Username which will be used to provide credentials to your tunnel provider."
              ),
            required=True,
        ).requires("6in4_dynamic_enabled", True)
        wan_main.add_field(
            Textbox,
            name="6in4_key",
            label=_("Key"),
            validators=validators.NotEmpty(),
            hint=
            _("Key which will be used to provide credentials to your tunnel provider."
              ),
            required=True,
        ).requires("6in4_dynamic_enabled", True)

        # custom MAC
        wan_main.add_field(
            Checkbox,
            name="custom_mac",
            label=_("Custom MAC address"),
            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"),
            validators=validators.MacAddress(),
            required=True,
            hint=_(
                "Colon is used as a separator, for example 00:11:22:33:44:55"),
        ).requires("custom_mac", True)

        def wan_form_cb(data):
            backend_data = WanHandler._convert_form_data_to_backend_data(data)
            res = current_state.backend.perform("wan", "update_settings",
                                                backend_data)

            return "save_result", res  # store {"result": ...} to be used later...

        wan_form.add_callback(wan_form_cb)

        return wan_form
Ejemplo n.º 6
0
    def get_form(self):
        data = {}
        data["mode"] = self.backend_data["mode"]
        data["router_ip"] = self.backend_data["mode_managed"]["router_ip"]
        data["router_netmask"] = self.backend_data["mode_managed"]["netmask"]
        data["router_dhcp_enabled"] = self.backend_data["mode_managed"][
            "dhcp"]["enabled"]
        data["router_dhcp_start"] = self.backend_data["mode_managed"]["dhcp"][
            "start"]
        data["router_dhcp_limit"] = self.backend_data["mode_managed"]["dhcp"][
            "limit"]
        data["router_dhcp_leasetime"] = self.backend_data["mode_managed"]["dhcp"]["lease_time"] \
            // (60 * 60)
        data["client_proto_4"] = self.backend_data["mode_unmanaged"][
            "lan_type"]
        data["client_ip_4"] = self.backend_data["mode_unmanaged"][
            "lan_static"]["ip"]
        data["client_netmask_4"] = self.backend_data["mode_unmanaged"][
            "lan_static"]["netmask"]
        data["client_gateway_4"] = self.backend_data["mode_unmanaged"][
            "lan_static"]["gateway"]
        dns1 = self.backend_data["mode_unmanaged"]["lan_static"].get("dns1")
        if dns1:
            data["client_dns1_4"] = dns1
        dns2 = self.backend_data["mode_unmanaged"]["lan_static"].get("dns2")
        if dns2:
            data["client_dns2_4"] = dns2
        data["client_hostname_4"] = self.backend_data["mode_unmanaged"][
            "lan_dhcp"].get("hostname", "")

        if self.data:
            # Update from post
            data.update(self.data)

        lan_form = fapi.ForisForm(
            "lan",
            data,
            validators=[
                validators.DhcpRangeValidator(
                    'router_netmask', 'router_dhcp_start', 'router_dhcp_limit',
                    gettext(
                        "<strong>DHCP start</strong> and <strong>DHCP max leases</strong> "
                        "does not fit into <strong>Network netmask</strong>!"),
                    [
                        lambda data: data['mode'] != 'managed',
                        lambda data: not data['router_dhcp_enabled'],
                    ])
            ])
        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(
            Dropdown,
            name="mode",
            label=_("LAN mode"),
            args=[
                ("managed", _("Router")),
                ("unmanaged", _("Computer")),
            ],
            hint=
            _("Router mode means that this devices manages the LAN "
              "(acts as a router, can assing IP addresses, ...). "
              "Computer mode means that this device acts as a client in this network. "
              "It acts in a similar way as WAN, but it has opened ports for configuration "
              "interface and other services. "),
            default="managed",
        )

        # managed options
        lan_main.add_field(
            Textbox,
            name="router_ip",
            label=_("Router IP address"),
            validators=validators.IPv4(),
            hint=_("Router's IP address in the inner network.")).requires(
                "mode", "managed")
        lan_main.add_field(
            Textbox,
            name="router_netmask",
            label=_("Network netmask"),
            validators=validators.IPv4Netmask(),
            hint=_("Network mask of the inner network.")).requires(
                "mode", "managed")
        lan_main.add_field(
            Checkbox,
            name="router_dhcp_enabled",
            label=_("Enable DHCP"),
            preproc=lambda val: bool(int(val)),
            default=True,
            hint=_(
                "Enable this option to automatically assign IP addresses to "
                "the devices connected to the router.")).requires(
                    "mode", "managed")
        lan_main.add_field(
            Number,
            name="router_dhcp_start",
            label=_("DHCP start"),
        ).requires("router_dhcp_enabled", True)
        lan_main.add_field(
            Number,
            name="router_dhcp_limit",
            label=_("DHCP max leases"),
        ).requires("router_dhcp_enabled", True)
        lan_main.add_field(Number,
                           name="router_dhcp_leasetime",
                           label=_("Lease time (hours)"),
                           validators=[validators.InRange(1, 7 * 24)
                                       ]).requires("router_dhcp_enabled", True)

        # unmanaged options
        LAN_DHCP = "dhcp"
        LAN_STATIC = "static"
        LAN_NONE = "none"
        LAN_OPTIONS = (
            (LAN_DHCP, _("DHCP (automatic configuration)")),
            (LAN_STATIC, _("Static IP address (manual configuration)")),
            (LAN_NONE, _("Don't connect this device to LAN")),
        )
        lan_main.add_field(Dropdown,
                           name="client_proto_4",
                           label=_("IPv4 protocol"),
                           args=LAN_OPTIONS,
                           default=LAN_DHCP).requires("mode", "unmanaged")
        # unmanaged static
        lan_main.add_field(Textbox,
                           name="client_ip_4",
                           label=_("IPv4 address"),
                           required=True,
                           validators=validators.IPv4()).requires(
                               "client_proto_4", LAN_STATIC)
        lan_main.add_field(Textbox,
                           name="client_netmask_4",
                           label=_("Network mask"),
                           required=True,
                           validators=validators.IPv4Netmask()).requires(
                               "client_proto_4", LAN_STATIC)
        lan_main.add_field(
            Textbox,
            name="client_gateway_4",
            label=_("Gateway"),
            required=True,
            validators=validators.IPv4(),
        ).requires("client_proto_4", LAN_STATIC)
        lan_main.add_field(
            Textbox,
            name="client_dns1_4",
            label=_("DNS server 1 (IPv4)"),
            validators=validators.IPv4(),
            hint=_("DNS server address is not required as the built-in "
                   "DNS resolver is capable of working without it.")).requires(
                       "client_proto_4", LAN_STATIC)
        lan_main.add_field(
            Textbox,
            name="client_dns2_4",
            label=_("DNS server 2 (IPv4)"),
            validators=validators.IPv4(),
            hint=_("DNS server address is not required as the built-in "
                   "DNS resolver is capable of working without it.")).requires(
                       "client_proto_4", LAN_STATIC)
        # unamanaged dhcp
        lan_main.add_field(
            Textbox,
            name="client_hostname_4",
            label=_("DHCP hostname"),
            validators=validators.Domain(),
            hint=_(
                "Hostname which will be provided to DHCP server.")).requires(
                    "client_proto_4", LAN_DHCP)

        def lan_form_cb(data):
            msg = {"mode": data["mode"]}
            if msg["mode"] == "managed":
                dhcp = {
                    "enabled": data["router_dhcp_enabled"],
                }
                if dhcp["enabled"]:
                    dhcp["start"] = int(data["router_dhcp_start"])
                    dhcp["limit"] = int(data["router_dhcp_limit"])
                    dhcp["lease_time"] = int(
                        data.get("router_dhcp_leasetime", 12)) * 60 * 60
                msg["mode_managed"] = {
                    "router_ip": data["router_ip"],
                    "netmask": data["router_netmask"],
                    "dhcp": dhcp,
                }
            elif data["mode"] == "unmanaged":
                msg["mode_unmanaged"] = {
                    "lan_type": data["client_proto_4"],
                }
                if data["client_proto_4"] == "static":
                    msg["mode_unmanaged"]["lan_static"] = {
                        "ip": data["client_ip_4"],
                        "netmask": data["client_netmask_4"],
                        "gateway": data["client_gateway_4"],
                    }
                    dns1 = data.get("client_dns1_4")
                    if dns1:
                        msg["mode_unmanaged"]["lan_static"]["dns1"] = dns1

                    dns2 = data.get("client_dns2_4")
                    if dns2:
                        msg["mode_unmanaged"]["lan_static"]["dns2"] = dns2

                elif data["client_proto_4"] == "dhcp":
                    hostname = data.get("client_hostname_4")
                    msg["mode_unmanaged"]["lan_dhcp"] = {
                        "hostname": hostname
                    } if hostname else {}

            res = current_state.backend.perform("lan", "update_settings", msg)
            return "save_result", res  # store {"result": ...} to be used later...

        lan_form.add_callback(lan_form_cb)

        return lan_form
Ejemplo n.º 7
0
    def get_form(self):
        data = {}
        data["guest_enabled"] = self.backend_data["enabled"]
        data["guest_ipaddr"] = self.backend_data["ip"]
        data["guest_netmask"] = self.backend_data["netmask"]
        data["guest_dhcp_enabled"] = self.backend_data["dhcp"]["enabled"]
        data["guest_dhcp_start"] = self.backend_data["dhcp"]["start"]
        data["guest_dhcp_limit"] = self.backend_data["dhcp"]["limit"]
        data["guest_dhcp_leasetime"] = self.backend_data["dhcp"]["lease_time"] // 60 // 60
        data["guest_qos_enabled"] = self.backend_data["qos"]["enabled"]
        data["guest_qos_download"] = self.backend_data["qos"]["download"]
        data["guest_qos_upload"] = self.backend_data["qos"]["upload"]

        if self.data:
            # Update from post
            data.update(self.data)

        guest_form = fapi.ForisForm(
            "guest",
            data,
            validators=[
                validators.DhcpRangeValidator(
                    "guest_netmask",
                    "guest_dhcp_start",
                    "guest_dhcp_limit",
                    gettext(
                        "<strong>DHCP start</strong> and <strong>DHCP max leases</strong> "
                        "does not fit into <strong>Guest network netmask</strong>!"
                    ),
                    [
                        lambda data: not data.get("guest_enabled"),
                        lambda data: not data.get("guest_dhcp_enabled"),
                    ],
                ),
                validators.DhcpRangeRouterIpValidator(
                    "guest_ipaddr",
                    "guest_netmask",
                    "guest_dhcp_start",
                    "guest_dhcp_limit",
                    gettext(
                        "<strong>Router IP</strong> should not be within DHCP range "
                        "defined by <strong>DHCP start</strong> and <strong>DHCP max leases "
                        "</strong>"
                    ),
                    [
                        lambda data: not data.get("guest_dhcp_enabled"),
                        lambda data: not data.get("guest_enabled"),
                    ],
                ),
            ],
        )
        guest_network_section = guest_form.add_section(
            name="guest_network",
            title=_(self.userfriendly_title),
            description=_(
                "Guest network is used for <a href='%(url)s'>guest Wi-Fi</a>. It is separated  "
                "from your ordinary LAN. Devices connected to this network are allowed "
                "to access the internet, but are not allowed to access the configuration "
                "interface of this device nor the devices in LAN."
            )
            % dict(url=reverse("config_page", page_name="wifi")),
        )
        guest_network_section.add_field(
            Checkbox, name="guest_enabled", label=_("Enable guest network"), default=False
        )
        guest_network_section.add_field(
            Textbox,
            name="guest_ipaddr",
            label=_("Router IP in guest network"),
            default=DEFAULT_GUEST_IP,
            validators=validators.IPv4(),
            hint=_(
                "Router's IP address in the guest network. It is necessary that "
                "the guest network IPs are different from other networks "
                "(LAN, WAN, VPN, etc.)."
            ),
        ).requires("guest_enabled", True)
        guest_network_section.add_field(
            Textbox,
            name="guest_netmask",
            label=_("Guest network netmask"),
            default=DEFAULT_GUEST_MASK,
            validators=validators.IPv4Netmask(),
            hint=_("Network mask of the guest network."),
        ).requires("guest_enabled", True)

        guest_network_section.add_field(
            Checkbox,
            name="guest_dhcp_enabled",
            label=_("Enable DHCP"),
            preproc=lambda val: bool(int(val)),
            default=True,
            hint=_(
                "Enable this option to automatically assign IP addresses to "
                "the devices connected to the router."
            ),
        ).requires("guest_enabled", True)
        guest_network_section.add_field(
            Textbox, name="guest_dhcp_start", label=_("DHCP start")
        ).requires("guest_dhcp_enabled", True)
        guest_network_section.add_field(
            Textbox, name="guest_dhcp_limit", label=_("DHCP max leases")
        ).requires("guest_dhcp_enabled", True)
        guest_network_section.add_field(
            Textbox,
            name="guest_dhcp_leasetime",
            label=_("Lease time (hours)"),
            validators=[validators.InRange(1, 7 * 24)],
        ).requires("guest_dhcp_enabled", True)

        guest_network_section.add_field(
            Checkbox,
            name="guest_qos_enabled",
            label=_("Guest Lan QoS"),
            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_enabled", True)

        guest_network_section.add_field(
            Number,
            name="guest_qos_download",
            label=_("Download (kb/s)"),
            validators=[validators.PositiveInteger()],
            hint=_("Download speed in guest network (in kilobits per second)."),
            default=1024,
        ).requires("guest_qos_enabled", True)
        guest_network_section.add_field(
            Number,
            name="guest_qos_upload",
            label=_("Upload (kb/s)"),
            validators=[validators.PositiveInteger()],
            hint=_("Upload speed in guest network (in kilobits per second)."),
            default=1024,
        ).requires("guest_qos_enabled", True)

        def guest_form_cb(data):
            if data["guest_enabled"]:
                msg = {
                    "enabled": data["guest_enabled"],
                    "ip": data["guest_ipaddr"],
                    "netmask": data["guest_netmask"],
                    "dhcp": {"enabled": data["guest_dhcp_enabled"]},
                    "qos": {"enabled": data["guest_qos_enabled"]},
                }
                if data["guest_dhcp_enabled"]:
                    msg["dhcp"]["start"] = int(data["guest_dhcp_start"])
                    msg["dhcp"]["limit"] = int(data["guest_dhcp_limit"])
                    msg["dhcp"]["lease_time"] = int(data["guest_dhcp_leasetime"]) * 60 * 60

                if data["guest_qos_enabled"]:
                    msg["qos"]["download"] = int(data["guest_qos_download"])
                    msg["qos"]["upload"] = int(data["guest_qos_upload"])
            else:
                msg = {"enabled": False}

            res = current_state.backend.perform("guest", "update_settings", msg)
            return "save_result", res  # store {"result": ...} to be used later...

        guest_form.add_callback(guest_form_cb)

        return guest_form
Ejemplo n.º 8
0
    def get_form(self):
        data = current_state.backend.perform("router_notifications",
                                             "get_settings")
        data["enable_smtp"] = data["emails"]["enabled"]
        data["use_turris_smtp"] = "1" if data["emails"][
            "smtp_type"] == "turris" else "0"
        data["to"] = " ".join(data["emails"]["common"]["to"])
        data["sender_name"] = data["emails"]["smtp_turris"]["sender_name"]
        data["severity"] = data["emails"]["common"]["severity_filter"]
        data["news"] = data["emails"]["common"]["send_news"]
        data["from"] = data["emails"]["smtp_custom"]["from"]
        data["server"] = data["emails"]["smtp_custom"]["host"]
        data["port"] = data["emails"]["smtp_custom"]["port"]
        data["security"] = data["emails"]["smtp_custom"]["security"]
        data["username"] = data["emails"]["smtp_custom"]["username"]
        data["password"] = data["emails"]["smtp_custom"]["password"]
        data["delay"] = str(data["reboots"]["delay"])
        data["reboot_time"] = data["reboots"]["time"]

        if self.data:
            # Update from post
            data.update(self.data)

        notifications_form = fapi.ForisForm("notifications", data)

        notifications = notifications_form.add_section(
            name="notifications", title=_("Notifications settings"))
        # notifications settings
        notifications.add_field(Checkbox,
                                name="enable_smtp",
                                label=_("Enable notifications"),
                                default=False)

        notifications.add_field(
            Radio,
            name="use_turris_smtp",
            label=_("SMTP provider"),
            default="0",
            args=(("1", _("Turris")), ("0", _("Custom"))),
            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"),
            hint=
            _("Email address of recipient. Separate multiple addresses by spaces."
              ),
            required=True,
            validators=[
                validators.RegExp(
                    _("Doesn't contain a list of emails separated by spaces"),
                    r"^([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)( +[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+ *)*$",
                )
            ],
        ).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.'),
            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"),
                                args=SEVERITY_OPTIONS,
                                default=1).requires("enable_smtp", True)
        notifications.add_field(
            Checkbox,
            name="news",
            label=_("Send news"),
            hint=_("Send emails about new features."),
            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 send from."),
            required=True,
            placeholder="*****@*****.**",
        ).requires("enable_smtp", True).requires("use_turris_smtp", "0")
        smtp.add_field(Textbox,
                       name="server",
                       label=_("Server address"),
                       placeholder="example.com").requires(
                           "enable_smtp",
                           True).requires("use_turris_smtp", "0")
        smtp.add_field(
            Number,
            name="port",
            label=_("Server 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"),
                       args=SECURITY_OPTIONS,
                       default="none").requires("enable_smtp", True).requires(
                           "use_turris_smtp", "0")

        smtp.add_field(Textbox, name="username", label=_("Username")).requires(
            "enable_smtp", True).requires("use_turris_smtp", "0")
        smtp.add_field(Password,
                       name="password", label=_("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."),
            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."),
            validators=[validators.Time()],
            required=True,
        )

        def notifications_form_cb(data):
            msg = {
                "reboots": {
                    "delay": int(data["delay"]),
                    "time": data["reboot_time"]
                },
                "emails": {
                    "enabled": data["enable_smtp"]
                },
            }
            if data["enable_smtp"]:
                msg["emails"]["smtp_type"] = (
                    "turris" if data["use_turris_smtp"] == "1" else "custom")
                msg["emails"]["common"] = {
                    "to": [e for e in data["to"].split(" ") if e],
                    "severity_filter": int(data["severity"]),
                    "send_news": data["news"],
                }
                if msg["emails"]["smtp_type"] == "turris":
                    msg["emails"]["smtp_turris"] = {
                        "sender_name": data["sender_name"]
                    }
                elif msg["emails"]["smtp_type"] == "custom":
                    msg["emails"]["smtp_custom"] = {
                        "from": data["from"],
                        "host": data["server"],
                        "port": int(data["port"]),
                        "security": data["security"],
                        "username": data["username"],
                        "password": data["password"],
                    }

            res = current_state.backend.perform("router_notifications",
                                                "update_settings", msg)

            return "save_result", res  # store {"result": ...} to be used later...

        notifications_form.add_callback(notifications_form_cb)

        return notifications_form
Ejemplo n.º 9
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