示例#1
0
    def get_form(self):
        data = current_state.backend.perform("data_collect", "get")
        if self.data and "enable" in self.data:
            data["enable"] = self.data["enable"]
        else:
            data["enable"] = data["agreed"]

        form = fapi.ForisForm("enable_collection", data)

        section = form.add_section(
            name="collection_toggle",
            title=_(self.userfriendly_title),
        )
        section.add_field(Checkbox,
                          name="enable",
                          label=_("Enable data collection"),
                          preproc=lambda val: bool(int(val)))

        def form_cb(data):
            data = current_state.backend.perform("data_collect", "set",
                                                 {"agreed": data["enable"]})
            return "save_result", data  # store {"result": ...} to be used later...

        form.add_callback(form_cb)

        return form
示例#2
0
    def get_form(self):
        form = fapi.ForisForm("registration_check", self.data)
        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):
            data = current_state.backend.perform(
                "data_collect", "get_registered", {
                    "email": data.get("email"),
                    "language": current_state.language
                })
            error = None
            registration_number = None
            url = None
            if data["status"] == "unknown":
                error = _("Failed to query the server.")
            elif data["status"] == "not_valid":
                error = _("Failed to verify the router's registration.")
            elif data["status"] in ["free", "foreign"]:
                url = data["url"]
                registration_number = data["registration_number"]

            return "save_result", {
                'success': data["status"] not in ["unknown", "not_valid"],
                'status': data["status"],
                'error': error,
                'url': url,
                'registration_number': registration_number,
            }

        form.add_callback(form_cb)
        return form
示例#3
0
 def get_serial_form(self, data=None):
     generate_serial_form = fapi.ForisForm("serial_form", data)
     serial_section = generate_serial_form.add_section("serial_section", title=None)
     serial_section.add_field(
         Textbox, name="serial", label=" ", required=True, validators=[validators.MacAddress()]
     )
     return generate_serial_form
示例#4
0
    def get_form(self):
        form = fapi.ForisForm("create_and_upload", self.data)
        section = form.add_section(
            name="passwords",
            title=self.userfriendly_title,
        )
        section.add_field(
            Password, name="password", label=_("Password"), required=True,
            validators=validators.LenRange(6, 128)
        )
        section.add_field(
            Password, name="password_validation", label=_("Password (repeat)"), required=True,
            validators=validators.EqualTo(
                "password", "password_validation", _("Passwords are not equal.")
            )
        )

        def form_cb(data):
            res = current_state.backend.perform(
                "ssbackups", "set_password",
                {"password": base64.b64encode(data["password"].encode()).decode()}
            )
            return "save_result", res  # store {"result": ...} to be used later...

        form.add_callback(form_cb)
        return form
示例#5
0
    def get_form(self):
        system_pw_form = fapi.ForisForm("system_password", self.data)
        system_pw_main = system_pw_form.add_section(
            name="set_password",
            title=_(self.userfriendly_title),
            description=
            _("In order to access the advanced configuration possibilities which are "
              "not present here, you must set the root user's password. The advanced "
              "configuration options can be managed either through the "
              "<a href=\"//%(host)s/%(path)s\">LuCI web interface</a> "
              "or over SSH.") % {
                  'host': bottle.request.get_header('host'),
                  'path': 'cgi-bin/luci'
              })
        system_pw_main.add_field(Password,
                                 name="password",
                                 label=_("Password"),
                                 required=True,
                                 validators=validators.LenRange(6, 128))
        system_pw_main.add_field(Password,
                                 name="password_validation",
                                 label=_("Password (repeat)"),
                                 required=True,
                                 validators=validators.EqualTo(
                                     "password", "password_validation",
                                     _("Passwords are not equal.")))

        def system_pw_form_cb(data):
            client.set_password("root", data["password"])
            return "none", None

        system_pw_form.add_callback(system_pw_form_cb)
        return system_pw_form
示例#6
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
示例#7
0
文件: wifi.py 项目: CZ-NIC/foris
    def make_form(self, data: typing.Optional[dict]) -> fapi.ForisForm:

        backend_data = current_state.backend.perform(
            "wifi", "get_settings", controller_id=self.controller_id
        )
        form_data = self.convert_data_from_backend_to_form(backend_data)
        if data:
            form_data.update(data)

        used_bands = []
        for field_name, band in [(k, v) for k, v in form_data.items() if k.endswith("hwmode")]:
            # radioX-hwmode => X
            radio_number = field_name.split("-", 1)[0][len("radio"):]
            radio_enabled = form_data.get(f"radio{radio_number}-device_enabled", False)
            if (isinstance(radio_enabled, bool) and radio_enabled) or radio_enabled == "1":
                used_bands.append(band)

        wifi_form = fapi.ForisForm("wifi", form_data)

        # display conflict message when two wifis are using the same band
        wifi_form.band_conflict = not (len(used_bands) == len(set(used_bands)))

        wifi_form.add_section(
            name="wifi",
            title=_("Wi-Fi"),
            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 within the form."
            ),
        )

        # Add wifi section
        wifi_section = wifi_form.add_section(name="wifi_settings", title=_("Wi-Fi settings"))

        for idx, device in enumerate(backend_data["devices"]):
            prefix = WifiEditForm.prefixed(device["id"], "")
            device_form_data = {
                k[len(prefix) :]: v for k, v in form_data.items() if k.startswith(prefix)
            }  # prefix removed
            self._prepare_device_fields(
                wifi_section, device, device_form_data, len(backend_data["devices"]) - 1 == idx
            )

        def form_cb(data):
            update_data = self.convert_data_from_form_to_backend(
                data, [e["id"] for e in backend_data["devices"]]
            )
            res = current_state.backend.perform(
                "wifi", "update_settings", update_data, controller_id=self.controller_id
            )
            return "save_result", res

        wifi_form.add_callback(form_cb)
        return wifi_form
示例#8
0
    def get_form(self):

        form = fapi.ForisForm("netboot", {})
        form.add_section(name="main_section", title=self.userfriendly_title)

        def form_cb(data):
            return "save_result", {}

        form.add_callback(form_cb)
        return form
示例#9
0
文件: misc.py 项目: CZ-NIC/foris
    def get_form(self):
        finished_form = fapi.ForisForm("guide_finished", {})
        finished_form.add_section(name="guide_finished",
                                  title=_(self.userfriendly_title))

        def guide_finished_cb(data):
            res = current_state.backend.perform("web", "update_guide",
                                                {"enabled": False})
            return "save_result", res  # store {"result": ...} to be used later...

        finished_form.add_callback(guide_finished_cb)
        return finished_form
示例#10
0
文件: remote.py 项目: erdoukki/foris
    def get_form(self):
        data = {
            "enabled": self.backend_data["enabled"],
            "port": self.backend_data["port"],
            "wan_access": self.backend_data["wan_access"],
        }

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

        form = fapi.ForisForm("remote", data)
        config_section = form.add_section(name="set_remote",
                                          title=_(self.userfriendly_title))
        config_section.add_field(
            Checkbox,
            name="enabled",
            label=_("Enable remote access"),
        )
        config_section.add_field(
            Checkbox,
            name="wan_access",
            label=_("Accessible via WAN"),
            hint=
            _("If this option is check the device in the WAN network will be able to connect "
              "to the configuration interface. Otherwise only devices on LAN will be able to "
              "access the configuration interface."),
        ).requires("enabled", True)
        config_section.add_field(
            Number,
            name="port",
            label=_("Port"),
            hint=_("A port which will be opened for the remote configuration "
                   "of this device."),
            validator=[InRange(1, 2**16 - 1)],
            default=11884,
        ).requires("enabled", True)

        def form_callback(data):
            msg = {"enabled": data['enabled']}

            if msg["enabled"]:
                msg["port"] = int(data["port"])
                msg["wan_access"] = data['wan_access']

            res = current_state.backend.perform("remote", "update_settings",
                                                msg)
            res['enabled'] = msg['enabled']

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

        form.add_callback(form_callback)
        return form
示例#11
0
    def get_form(self):
        data = current_state.backend.perform("netmetr", "get_settings")
        # init hours
        for i in range(24):
            data["hour_to_run_%d" % i] = False
        # update the enabled
        for e in data["hours_to_run"]:
            data["hour_to_run_%d" % e] = True

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

        form = fapi.ForisForm("netmetr", data)
        main = form.add_section(name="set_netmetr",
                                title=_(self.userfriendly_title))
        autostart_section = main.add_section(name="autostart",
                                             title=_("Autostart"))
        autostart_section.add_field(
            Checkbox,
            name="autostart_enabled",
            label=_("Autostart enabled"),
            preproc=lambda val: bool(int(val)),
            hint=
            _("Measuring will start about selected hour (time is no exact for load distribution)"
              ))
        hours = main.add_section(name="hours", title=_("Autostart times"))
        for i in range(24):
            hours.add_field(
                Checkbox,
                name="hour_to_run_%d" % i,
                label="%02d:00" % i,
                preproc=lambda val: bool(int(val)),
            ).requires("autostart_enabled", True)

        def form_cb(data):
            msg = {"autostart_enabled": data["autostart_enabled"]}
            if data["autostart_enabled"]:
                msg["hours_to_run"] = []
                for i in range(24):
                    name = "hour_to_run_%d" % i
                    if name in data and data[name]:
                        msg["hours_to_run"].append(i)
            current_state.backend.perform("netmetr", "update_settings", msg)
            messages.success(_("Netmetr settings were updated."))
            return "none", None

        form.add_callback(form_cb)

        return form
示例#12
0
    def get_form(self):
        maintenance_form = fapi.ForisForm("maintenance", self.data)
        maintenance_main = maintenance_form.add_section(
            name="restore_backup", title=_(self.userfriendly_title))
        maintenance_main.add_field(File,
                                   name="backup_file",
                                   label=_("Backup file"),
                                   required=True)

        def maintenance_form_cb(data):
            result = client.load_config_backup(data['backup_file'].file)
            return "save_result", {'new_ip': result}

        maintenance_form.add_callback(maintenance_form_cb)
        return maintenance_form
示例#13
0
    def get_form(self):
        maintenance_form = fapi.ForisForm("maintenance", self.data)
        maintenance_main = maintenance_form.add_section(
            name="restore_backup", title=_(self.userfriendly_title)
        )
        maintenance_main.add_field(File, name="backup_file", label=_("Backup file"), required=True)

        def maintenance_form_cb(data):
            data = current_state.backend.perform(
                "maintain",
                "restore_backup",
                {"backup": base64.b64encode(data["backup_file"].file.read()).decode("utf-8")},
            )
            return "save_result", {"result": data["result"]}

        maintenance_form.add_callback(maintenance_form_cb)
        return maintenance_form
示例#14
0
    def get_form(self):
        data = copy.deepcopy(self.backend_data)

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

        networks_form = fapi.ForisForm("networks", self.data)
        ports_section = networks_form.add_section(
            name="set_ports", title=_(self.userfriendly_title))
        checkboxes = []
        for kind in ["wan", "lan", "guest", "none"]:
            checkboxes += [(e["id"], e["id"]) for e in self.backend_data["networks"][kind]]
        ports_section.add_field(MultiCheckbox, name="wan", args=checkboxes, multifield=True)
        ports_section.add_field(MultiCheckbox, name="lan", args=checkboxes, multifield=True)
        ports_section.add_field(MultiCheckbox, name="guest", args=checkboxes, multifield=True)
        ports_section.add_field(MultiCheckbox, name="none", args=checkboxes, multifield=True)

        ports_section.add_field(Checkbox, name="ssh_on_wan", default=False, required=False)
        ports_section.add_field(Checkbox, name="http_on_wan", default=False, required=False)
        ports_section.add_field(Checkbox, name="https_on_wan", default=False, required=False)

        def networks_form_cb(data):
            wan = data.get("wan", [])
            lan = data.get("lan", [])
            guest = data.get("guest", [])
            none = data.get("none", [])

            ssh_on_wan = bool(data.get("ssh_on_wan", "0"))
            http_on_wan = bool(data.get("http_on_wan", "0"))
            https_on_wan = bool(data.get("https_on_wan", "0"))

            result = current_state.backend.perform(
                "networks", "update_settings", {
                    "firewall": {
                        "ssh_on_wan": ssh_on_wan, "http_on_wan": http_on_wan,
                        "https_on_wan": https_on_wan
                    },
                    "networks": {"lan": lan, "wan": wan, "guest": guest, "none": none}
                }
            )
            return "save_result", result

        networks_form.add_callback(networks_form_cb)

        return networks_form
示例#15
0
文件: remote.py 项目: erdoukki/foris
 def get_generate_token_form(self, data=None):
     generate_token_form = fapi.ForisForm("generate_remote_token", data)
     token_section = generate_token_form.add_section("generate_token",
                                                     title=None)
     token_section.add_field(
         Textbox,
         name="name",
         label=_("Token name"),
         required=True,
         hint=
         _("The display name for the token. It must be shorter than 64 characters "
           "and must contain only alphanumeric characters, dots, dashes and "
           "underscores."),
         validators=[
             RegExp(_("Token name is invalid."), r'[a-zA-Z0-9_.-]+'),
             LenRange(1, 63)
         ])
     return generate_token_form
示例#16
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
示例#17
0
    def get_form(self):
        form = fapi.ForisForm("suboridinates", self.data)

        section = form.add_section(name="main_section", title=_(self.userfriendly_title))

        section.add_field(File, name="token_file", label=_("Token file"), required=True)

        def form_cb(data):
            res = current_state.backend.perform(
                "subordinates",
                "add_sub",
                {"token": base64.b64encode(data["token_file"].file.read()).decode("utf-8")},
            )

            return "save_result", res

        form.add_callback(form_cb)
        return form
示例#18
0
    def get_form(self):
        finished_form = fapi.ForisForm("guide_finished", {})
        finished_form.add_section(
            name="guide_finished",
            title=_(self.userfriendly_title),
            description=_(
                "Congratulations you've successfully reached the end of this guide. "
                "Once you leave this guide you'll be granted access to the "
                "full configuration interface of this device."))

        def guide_finished_cb(data):
            res = current_state.backend.perform("web", "update_guide", {
                "enabled": False,
            })
            return "save_result", res  # store {"result": ...} to be used later...

        finished_form.add_callback(guide_finished_cb)
        return finished_form
示例#19
0
    def make_form(self, data: typing.Optional[dict]):

        form_data = self.convert_data_from_backend_to_form(
            current_state.backend.perform("subordinates", "list")
        )

        if data:
            form_data.update(data)

        sub_form = fapi.ForisForm("update_subsub", form_data)
        sub_section = sub_form.add_section(
            "subsubordinate_section",
            title="",
            description=_(
                "You can edit managed devices here. These devices are not "
                "not directly connected to this device but "
                "they are connected through another managed device."
            ),
        )
        sub_section.add_field(Hidden, name="controller_id", required=True, title="")
        sub_section.add_field(
            Textbox,
            name="custom_name",
            label=_("Custom Name"),
            validators=[validators.LenRange(0, 30)],
            hint=_("Nicer name for your device with serial '%(controller_id)s'.")
            % dict(controller_id=self.subsubordinate_controller_id),
        )

        def form_cb(data):
            res = current_state.backend.perform(
                "subordinates",
                "update_subsub",
                {
                    "controller_id": data["controller_id"],
                    "options": {"custom_name": data["custom_name"]},
                },
            )
            return "save_result", res

        sub_form.add_callback(form_cb)

        return sub_form
示例#20
0
    def get_form(self):
        backend_data = current_state.backend.perform("wifi", "get_settings")
        form_data = self._backend_data_to_form_data(backend_data)
        if self.data:
            form_data.update(self.data)

        wifi_form = fapi.ForisForm("wifi", form_data)
        wifi_form.add_section(
            name="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 within the form."))

        # Add wifi section
        wifi_section = wifi_form.add_section(
            name="wifi_settings",
            title=_("Wi-Fi settings"),
        )

        for idx, device in enumerate(backend_data["devices"]):
            prefix = WifiHandler.prefixed(device["id"], "")
            device_form_data = {
                k[len(prefix):]: v
                for k, v in form_data.items() if k.startswith(prefix)
            }  # prefix removed
            self._prepare_device_fields(
                wifi_section, device, device_form_data,
                len(backend_data["devices"]) - 1 == idx)

        def form_cb(data):
            update_data = self._form_data_to_backend_data(
                data, [e["id"] for e in backend_data["devices"]])
            res = current_state.backend.perform("wifi", "update_settings",
                                                update_data)
            return "save_result", res  # store {"result": ...} to be used later...

        wifi_form.add_callback(form_cb)
        return wifi_form
示例#21
0
文件: profile.py 项目: erdoukki/foris
    def get_form(self):

        data = {"workflow": self.backend_data["current_workflow"]}
        if self.data:
            data.update(self.data)

        profile_form = fapi.ForisForm("profile", data)
        main = profile_form.add_section(name="set_profile", title=_(self.userfriendly_title))
        main.add_field(Hidden, name="workflow", value=self.backend_data["current_workflow"])

        def profile_form_cb(data):
            result = current_state.backend.perform(
                "web", "update_guide", {
                    "enabled": True,
                    "workflow": data["workflow"],
                }
            )
            return "save_result", result

        profile_form.add_callback(profile_form_cb)

        return profile_form
示例#22
0
文件: remote.py 项目: erdoukki/foris
 def get_token_id_form(self, data=None):
     token_id_form = fapi.ForisForm("token_id_form", data)
     token_section = token_id_form.add_section("token_id_section",
                                               title=None)
     token_section.add_field(Textbox,
                             name="token_id",
                             label="",
                             required=True,
                             validators=[
                                 RegExp(_("Token id is invalid."),
                                        r'([a-zA-Z0-9][a-zA-Z0-9])+')
                             ])
     token_section.add_field(
         Textbox,
         name="name",
         label=_("Token name"),
         required=False,
         validators=[
             RegExp(_("Token name is invalid."), r'[a-zA-Z0-9_.-]+'),
             LenRange(1, 63)
         ],
     )
     return token_id_form
示例#23
0
    def get_form(self):
        time_form = fapi.ForisForm("time", self.data, filter=filters.time)
        time_main = time_form.add_section(
            name="set_time",
            title=_(self.userfriendly_title),
            description=
            _("We could not synchronize the time with a timeserver, probably due to a "
              "loss of connection. It is necessary for the router to have correct time "
              "in order to function properly. Please, synchronize it with your "
              "computer's time, or set it manually."))

        time_main.add_field(Textbox,
                            name="time",
                            label=_("Time"),
                            nuci_path="time",
                            nuci_preproc=lambda v: v.local)

        def time_form_cb(data):
            client.set_time(data['time'])
            return "none", None

        time_form.add_callback(time_form_cb)

        return time_form
示例#24
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
示例#25
0
    def get_form(self):
        stats = client.get(filter=filters.stats).find_child("stats")
        cards = self._get_wireless_cards(stats)

        if not cards:
            return None

        wifi_form = fapi.ForisForm("wifi",
                                   self.data,
                                   filter=filters.wifi_filter())

        # Create mapping of radio_name -> iface_index
        radio_to_iface = self._get_radio_to_iface(wifi_form)

        # Add header section (used for page title)
        wifi_form.add_section(
            name="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."))

        # Add wifi section
        wifi_section = wifi_form.add_section(
            name="wifi_settings",
            title=_("Wi-Fi settings"),
        )

        # Get list of available radios
        radios = self._get_radios(cards, wifi_section, radio_to_iface,
                                  self.data or {}, wifi_form.nuci_config())

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

            guest_wifi_enabled = False
            for radio in radios:
                if self._prepare_radio_cb(data, wireless, radio):
                    guest_wifi_enabled = True

            guest_interfaces = ["guest_turris_%s" % e for e in sorted(radios)]

            # test whether it is required to pass update guest network
            current_data = client.get(filter=filters.wifi_filter())
            current_enabled = preprocessors.guest_network_enabled(current_data)
            if guest_wifi_enabled and not current_enabled:
                # Guest network handling
                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
                LanHandler.prepare_guest_configs(uci, True, network, prefix,
                                                 guest_interfaces)
            elif guest_wifi_enabled:
                # try to update guest interfaces if the differs
                stored = current_data.find_child(
                    "uci.network.guest_turris.ifname")
                if not stored or set(
                        stored.value.split(" ")) != set(guest_interfaces):
                    network_conf = uci.add(Config("network"))
                    interface_section = network_conf.add(
                        Section("guest_turris", "interface"))
                    interface_section.add(
                        Option("ifname", " ".join(guest_interfaces)))

            return "edit_config", uci

        wifi_form.add_callback(wifi_form_cb)

        return wifi_form
示例#26
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
示例#27
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
示例#28
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
示例#29
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
示例#30
0
    def get_form(self):
        # form definitions
        pw_form = fapi.ForisForm("password", self.data)
        pw_main = pw_form.add_section(
            name="set_password",
            title=_(self.userfriendly_title),
            description=_("Set your password for this administration "
                          "interface. The password must be at least 6 "
                          "characters long."))
        if self.change:
            pw_main.add_field(Password,
                              name="old_password",
                              label=_("Current password"))
            label_pass1 = _("New password")
            label_pass2 = _("New password (repeat)")
        else:
            label_pass1 = _("Password")
            label_pass2 = _("Password (repeat)")

        pw_main.add_field(Password,
                          name="password",
                          label=label_pass1,
                          required=True,
                          validators=validators.LenRange(6, 128))
        pw_main.add_field(Password,
                          name="password_validation",
                          label=label_pass2,
                          required=True,
                          validators=validators.EqualTo(
                              "password", "password_validation",
                              _("Passwords are not equal.")))
        pw_main.add_field(
            Checkbox,
            name="set_system_pw",
            label=_("Use the same password for advanced configuration"),
            hint=_(
                "Same password would be used for accessing this administration "
                "interface, for root user in LuCI web interface and for SSH "
                "login. Use a strong password! (If you choose not to set the "
                "password for advanced configuration here, you will have the "
                "option to do so later. Until then, the root account will be "
                "blocked.)"))

        def pw_form_cb(data):
            from beaker.crypto import pbkdf2
            if self.change:
                # if changing password, check the old pw is right first
                uci_data = client.get(filter=filters.foris_config)
                password_hash = uci_data.find_child("uci.foris.auth.password")
                # allow changing the password if password_hash is empty
                if password_hash:
                    password_hash = password_hash.value
                    # crypt automatically extracts salt and iterations from formatted pw hash
                    if password_hash != pbkdf2.crypt(data['old_password'],
                                                     salt=password_hash):
                        return "save_result", {'wrong_old_password': True}

            uci = Uci()
            foris = Config("foris")
            uci.add(foris)
            auth = Section("auth", "config")
            foris.add(auth)
            # use 48bit pseudo-random salt internally generated by pbkdf2
            new_password_hash = pbkdf2.crypt(data['password'], iterations=1000)
            auth.add(Option("password", new_password_hash))

            if data['set_system_pw'] is True:
                client.set_password("root", data['password'])

            return "edit_config", uci

        pw_form.add_callback(pw_form_cb)
        return pw_form