Exemple #1
0
    def get_form(self):
        tls_form = ForisForm("tls", self.data, filter=ca_filter)
        maintenance_main = tls_form.add_section(name="tls_client",
                                                title=_(
                                                    self.userfriendly_title))
        maintenance_main.add_field(
            Textbox,
            name="client_name",
            label=_("Client name"),
            required=True,
            hint=
            _("The display name for the client. It must be shorter than 64 characters "
              "and must contain only alphanumeric characters, dots, dashes and "
              "underscores."),
            validators=[
                RegExp(_("Client name is invalid."), client_name_regexp),
                LenRange(1, 63)
            ])

        def maintenance_form_cb(data):
            client_name = data['client_name']
            if new_client(client_name):
                messages.success(
                    _("Request for creating a new client \"%s\" was succesfully submitted. "
                      "Client token should be available for download in a minute."
                      ) % client_name)
            else:
                messages.error(
                    _("An error occurred when creating client \"%s\".") %
                    client_name)
            return "none", None

        tls_form.add_callback(maintenance_form_cb)
        return tls_form
Exemple #2
0
 def save(self, *args, **kwargs):
     result = super(ProfileConfigPage, self).save(no_messages=True, *args, **kwargs)
     if self.form.callback_results["result"]:
         messages.success(_("Guide workflow was sucessfully set."))
     else:
         messages.error(_("Failed to set guide workflow."))
     return result
Exemple #3
0
 def save(self, *args, **kwargs):
     result = super(NetworksConfigPage, self).save(no_messages=True, *args, **kwargs)
     if self.form.callback_results["result"]:
         messages.success(_("Network configuration was sucessfully updated."))
     else:
         messages.error(_("Unable to update your network configuration."))
     return result
 def _ajax_delete(self):
     controller_id = self._check_and_get_controller_id()
     res = current_state.backend.perform("subordinates", "del",
                                         {"controller_id": controller_id})
     if res["result"]:
         return bottle.template(
             "config/_message.html.j2",
             message={
                 "classes": ["success"],
                 "text":
                 _("Subordinate '%(controller_id)s' was successfully deleted."
                   ) % dict(controller_id=controller_id),
             },
             template_adapter=bottle.Jinja2Template,
         )
     else:
         return bottle.template(
             "config/_message.html.j2",
             message={
                 "classes": ["error"],
                 "text":
                 _("Failed to delete subordinate '%(controller_id)s'.") %
                 dict(controller_id=controller_id),
             },
             template_adapter=bottle.Jinja2Template,
         )
Exemple #5
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
Exemple #6
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
Exemple #7
0
 def save(self, *args, **kwargs):
     result = super(NetworksConfigPage, self).save(no_messages=True, *args, **kwargs)
     if self.form.callback_results["result"]:
         messages.success(_("Network configuration was sucessfully updated."))
     else:
         messages.error(_("Unable to update your network configuration."))
     return result
    def get_client_form(self, data=None):
        client_form = ForisForm("openvpn", data)
        main_section = client_form.add_section(
            name="name",
            title=None,
        )
        main_section.add_field(
            Textbox,
            name="client_name",
            label=_("Client name"),
            required=True,
            hint=
            _("The display name for the client. It must be shorter than 64 characters "
              "and must contain only alphanumeric characters, dots, dashes and "
              "underscores."),
            validators=[
                RegExp(_("Client name is invalid."), r'[a-zA-Z0-9_.-]+'),
                LenRange(1, 63)
            ])

        def form_callback(data):
            current_state.backend.perform("openvpn", "generate_client",
                                          {"name": self.data['client_name']})
            messages.success(
                _("Started to generate client '%(name)s' for the OpenVPN server."
                  ) % dict(name=data['client_name']))

            return bottle.redirect(reverse("config_page", page_name="openvpn"))

        client_form.add_callback(form_callback)
        return client_form
Exemple #9
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
Exemple #10
0
 def _action_delete_ca(self):
     self._check_post()
     data = current_state.backend.perform("remote", "delete_ca")
     if data["result"]:
         messages.success(_("CA for remote access was sucessfully deleted."))
     else:
         messages.error(_("Failed to delete CA for remote access."))
     bottle.redirect(reverse("config_page", page_name="remote"))
Exemple #11
0
class NuciTLS(YinElement):
    tag = "nuci-tls"
    NS_URI = "http://www.nic.cz/ns/router/nuci-tls"

    CLIENT_STATUS_ACTIVE = _("active")
    CLIENT_STATUS_REVOKED = _("revoked")
    CLIENT_STATUS_EXPIRED = _("expired")

    def __init__(self, clients, generating):
        super(NuciTLS, self).__init__()
        self.clients = clients
        self.generating = generating

    @staticmethod
    def from_element(element):
        generating = element.find(NuciTLS.qual_tag("generating")) is not None
        client_elements = element.findall(NuciTLS.qual_tag("client"))
        clients = {}
        for client_el in client_elements:
            name = client_el.find(NuciTLS.qual_tag("name")).text
            status = client_el.find(NuciTLS.qual_tag("status")).text
            clients[name] = {'name': name, 'status': status}
        return NuciTLS(clients, generating)

    @property
    def key(self):
        return "nuci-tls"

    @staticmethod
    def rpc_reset_ca(background=True):
        rpc_el = ET.Element(NuciTLS.qual_tag("reset-CA"))
        if background:
            ET.SubElement(rpc_el, NuciTLS.qual_tag("background"))
        return rpc_el

    @staticmethod
    def rpc_new_client(name, background=True):
        rpc_el = ET.Element(NuciTLS.qual_tag("new-client"))
        name_el = ET.SubElement(rpc_el, NuciTLS.qual_tag("name"))
        name_el.text = name
        if background:
            ET.SubElement(rpc_el, NuciTLS.qual_tag("background"))
        return rpc_el

    @staticmethod
    def rpc_revoke_client(name):
        rpc_el = ET.Element(NuciTLS.qual_tag("revoke-client"))
        name_el = ET.SubElement(rpc_el, NuciTLS.qual_tag("name"))
        name_el.text = name
        return rpc_el

    @staticmethod
    def rpc_get_token(name):
        rpc_el = ET.Element(NuciTLS.qual_tag("get-token"))
        name_el = ET.SubElement(rpc_el, NuciTLS.qual_tag("name"))
        name_el.text = name
        return rpc_el
Exemple #12
0
    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
Exemple #13
0
 def save(self, *args, **kwargs):
     no_messages = kwargs.pop("no_messages", False)
     result = super(ConfigPageMixin, self).save(*args, **kwargs)
     if no_messages:
         return result
     if result:
         messages.success(_("Configuration was successfully saved."))
     else:
         messages.warning(_("There were some errors in your input."))
     return result
Exemple #14
0
 def save(self, *args, **kwargs):
     super().save(no_messages=True, *args, **kwargs)
     result = self.form.callback_results.get('result', False)
     if result:
         messages.success(_("Configuration was successfully saved."))
     else:
         messages.error(
             _("Failed to update emulated services. Note that you might need to wait till "
               "ucollect is properly installed."))
     return result
Exemple #15
0
 def save(self, *args, **kwargs):
     super(MaintenanceConfigPage, self).save(no_messages=True, *args, **kwargs)
     result = self.form.callback_results.get('result')
     if result:
         messages.success(_("Configuration was successfully restored. "
                            "Note that a reboot will be required to apply restored "
                            "configuration."))
     else:
         messages.warning(_("Failed to restore the backup from the provided file."))
     return result
Exemple #16
0
 def _action_save_notifications(self):
     if bottle.request.method != 'POST':
         messages.error(_("Wrong HTTP method."))
         bottle.redirect(reverse("config_page", page_name="maintenance"))
     handler = notifications.NotificationsHandler(request.POST.decode())
     if handler.save():
         messages.success(_("Configuration was successfully saved."))
         bottle.redirect(reverse("config_page", page_name="maintenance"))
     messages.warning(_("There were some errors in your input."))
     return super(MaintenanceConfigPage, self).render(notifications_form=handler.form)
Exemple #17
0
 def _action_save_notifications(self):
     if bottle.request.method != "POST":
         messages.error(_("Wrong HTTP method."))
         bottle.redirect(reverse("config_page", page_name="maintenance"))
     handler = notifications.NotificationsHandler(bottle.request.POST.decode())
     if handler.save():
         messages.success(_("Configuration was successfully saved."))
         bottle.redirect(reverse("config_page", page_name="maintenance"))
     messages.warning(_("There were some errors in your input."))
     return super(MaintenanceConfigPage, self).render(notifications_form=handler.form)
Exemple #18
0
 def maintenance_form_cb(data):
     client_name = data['client_name']
     if new_client(client_name):
         messages.success(
             _("Request for creating a new client \"%s\" was succesfully submitted. "
               "Client token should be available for download in a minute."
               ) % client_name)
     else:
         messages.error(
             _("An error occurred when creating client \"%s\".") %
             client_name)
     return "none", None
Exemple #19
0
    def _action_toggle_collecting(self):
        if bottle.request.method != 'POST':
            messages.error(_("Wrong HTTP method."))
            bottle.redirect(reverse("config_page", page_name="data_collect"))

        handler = CollectionToggleHandler(bottle.request.POST.decode())
        if handler.save():
            messages.success(_("Configuration was successfully saved."))
            bottle.redirect(reverse("config_page", page_name="data_collect"))

        messages.warning(_("There were some errors in your input."))
        return super().render(collection_toggle_form=handler.form)
    def _action_delete_ca(self):
        """Call RPC to delete the CA of the openvpn server

        :return: redirect to plugin's main page
        """
        res = current_state.backend.perform("openvpn", "delete_ca")
        if res["result"]:
            messages.success(_("The OpenVPN CA was successfully deleted."))
        else:
            messages.success(_("Failed to delete the OpenVPN CA."))

        return bottle.redirect(reverse("config_page", page_name="openvpn"))
Exemple #21
0
    def _action_reset_ca(self):
        """Call RPC for resetting the CA and redirect back.

        :return: redirect to plugin's main page
        """
        if reset_ca():
            messages.success(
                _("Reset of the certification authority was successfully submitted."
                  ))
        else:
            messages.error(_("An error occurred when trying to reset the CA."))

        bottle.redirect(reverse("config_page", page_name="tls"))
    def _action_revoke(self):
        """Handle POST requesting revoking client certificate config

        :return: response with token with appropriate HTTP headers
        """
        res = current_state.backend.perform("openvpn", "revoke",
                                            {"id": self.data['revoke-client']})
        if res["result"]:
            messages.success(
                _("The client certificate was successfully revoked."))
        else:
            messages.error(_("Failed to revoke the client certificate."))
        return bottle.redirect(reverse("config_page", page_name="openvpn"))
            def prepare_message(results: dict) -> dict:
                if results["result"]:
                    message = {
                        "classes": ["success"],
                        "text": _("Wi-Fi settings were successfully updated."),
                    }

                else:
                    message = {
                        "classes": ["error"],
                        "text": _("Failed to update Wi-Fi settings.")
                    }
                return message
Exemple #24
0
    def _action_reset(self):

        if bottle.request.method != "POST":
            messages.error(_("Wrong HTTP method."))
            bottle.redirect(reverse("config_page", page_name="wifi"))

        data = current_state.backend.perform("wifi", "reset")
        if "result" in data and data["result"] is True:
            messages.success(_("Wi-Fi reset was successful."))
        else:
            messages.error(_("Failed to perform Wi-Fi reset."))

        bottle.redirect(reverse("config_page", page_name="wifi"))
Exemple #25
0
    def _action_reset(self):

        if bottle.request.method != "POST":
            messages.error(_("Wrong HTTP method."))
            bottle.redirect(reverse("config_page", page_name="wifi"))

        data = current_state.backend.perform("wifi", "reset")
        if "result" in data and data["result"] is True:
            messages.success(_("Wi-Fi reset was successful."))
        else:
            messages.error(_("Failed to perform Wi-Fi reset."))

        bottle.redirect(reverse("config_page", page_name="wifi"))
Exemple #26
0
 def save(self, *args, **kwargs):
     super(MaintenanceConfigPage, self).save(no_messages=True, *args, **kwargs)
     result = self.form.callback_results.get("result")
     if result:
         messages.success(
             _(
                 "Configuration was successfully restored. "
                 "Note that a reboot will be required to apply restored "
                 "configuration."
             )
         )
     else:
         messages.warning(_("Failed to restore the backup from the provided file."))
     return result
    def save(self, *args, **kwargs):
        super(SubordinatesSetupPage, self).save(no_messages=True,
                                                *args,
                                                **kwargs)
        data = self.form.callback_results
        if data["result"]:
            messages.success(
                _("Token was successfully added and client '%(controller_id)s' "
                  "should be visible in a moment.") %
                dict(controller_id=data["controller_id"]))
        else:
            messages.error(_("Failed to add token."))

        return data["result"]
    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
Exemple #29
0
class Workflow(object):
    TITLES = {
        WORKFLOW_OLD: _("Old"),
        WORKFLOW_MIN: _("Minimal"),
        WORKFLOW_ROUTER: _("Router"),
        WORKFLOW_BRIDGE: _("Local Server"),
        WORKFLOW_UNSET: _("Unset"),
    }
    DESCRIPTIONS = {
        WORKFLOW_UNSET:
        _("The workflow wasn't set yet."),
        WORKFLOW_OLD:
        _("Workflow for older devices and older turris OS versions (before 4.0)."
          ),
        WORKFLOW_MIN:
        _("Just set your password and you are ready to go. "
          "This workflow is aimed to more advanced users who intend not to use the web gui. "
          ),
        WORKFLOW_ROUTER:
        _("After you finish this workflow your device will be able to act as a fully "
          "functional router. It assumes that you want to have more or less standard "
          "network setup."),
        WORKFLOW_BRIDGE:
        _("This workflow will help you to setup your device to act as a local server. "
          "It means that the device will provide some kind of service to other devices "
          "within your local network (e.g. act as a network attached storage)."
          ),
    }

    def __init__(self, workflow, current, recommended):
        """ Create object which describes a guide workflow

        :type current: bool
        :type recommended: bool

        """
        if workflow not in WORKFLOWS:
            raise KeyError("Workflow '%s' was not found." % workflow)

        self.name = workflow
        self.title = Workflow.TITLES[workflow]
        self.description = Workflow.DESCRIPTIONS[workflow]
        self.current = current
        self.recommended = recommended

    @property
    def img(self):
        return "img/workflow-%s.svg" % self.name
Exemple #30
0
 def __init__(self, low, high):
     self.error_msg = _("This value should be between %(low)s and %(high)s."
                        ) % dict(low=low, high=high)
     self._low = low
     self._high = high
     super(FloatRange, self).__init__(self.error_msg)
     self.js_validator_params = "[%s,%s]" % (low, high)
Exemple #31
0
 def __init__(self):
     pattern = r"^([01][0-9]|2[0-3]):([0-5][0-9])$"
     super(Time,
           self).__init__(_("This is not valid time in HH:MM format."),
                          pattern)
     self.js_validator = ("pattern", pattern)
     self.extra_data["parsley-error-message"] = self.msg
Exemple #32
0
 def __init__(self, low, high):
     self._low = low
     self._high = high
     super(ByteLenRange, self).__init__(
         _("Length must be from %(low)s to %(high)s characters.") %
         dict(low=low, high=high))
     self.js_validator_params = "[%s,%s]" % (low, high)
Exemple #33
0
 def __init__(self, low, high):
     self._low = low
     self._high = high
     super(InRange, self).__init__(
         _("Not in a valid range %(low).1f - %(high).1f.") % dict(low=low, high=high)
     )
     self.js_validator_params = "[%.1f,%.1f]" % (low, high)
Exemple #34
0
def top_index():
    session = bottle.request.environ["foris.session"]
    if bottle.request.method == "POST":
        next = bottle.request.POST.get("next", None)
        login(next, session)
        # if login passes it will redirect to a proper page
        # otherwise it contains next parameter
        messages.error(_("The password you entered was not valid."))
        response.status = 403
    else:
        next = bottle.request.GET.get("next", None)
        if not current_state.password_set:  # auto login if no password is set
            if session.is_anonymous:
                session.recreate()
            session["user_authenticated"] = True
            session.save()

        if session.get("user_authenticated"):
            login_redirect()

    return dict(
        luci_path="//%(host)s/%(path)s" % {
            "host": bottle.request.get_header("host"),
            "path": "cgi-bin/luci"
        },
        next=next,
    )
Exemple #35
0
 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
Exemple #36
0
 def __init__(self, low, high):
     self._low = low
     self._high = high
     super(ByteLenRange, self).__init__(
         _("Length must be from %(low)s to %(high)s characters.") % dict(low=low, high=high)
     )
     self.js_validator_params = "[%s,%s]" % (low, high)
Exemple #37
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
Exemple #38
0
 def __init__(self, low, high):
     self._low = low
     self._high = high
     super(InRange, self).__init__(
         _("Not in a valid range %(low).1f - %(high).1f.") %
         dict(low=low, high=high))
     self.js_validator_params = "[%.1f,%.1f]" % (low, high)
Exemple #39
0
def top_index():
    session = bottle.request.environ["foris.session"]
    if bottle.request.method == "POST":
        next = bottle.request.POST.get("next", None)
        login(next, session)
        # if login passes it will redirect to a proper page
        # otherwise it contains next parameter
        messages.error(_("The password you entered was not valid."))
        response.status = 403
    else:
        next = bottle.request.GET.get("next", None)
        if not current_state.password_set:  # auto login if no password is set
            if session.is_anonymous:
                session.recreate()
            session["user_authenticated"] = True
            session.save()

        if session.get("user_authenticated"):
            login_redirect()

    return dict(
        luci_path="//%(host)s/%(path)s"
        % {"host": bottle.request.get_header("host"), "path": "cgi-bin/luci"},
        next=next,
    )
Exemple #40
0
def config_action_post(page_name, action):
    bottle.SimpleTemplate.defaults["active_config_page_key"] = page_name
    bottle.Jinja2Template.defaults["active_config_page_key"] = page_name
    ConfigPage = get_config_page(page_name)
    config_page = ConfigPage(request.POST.decode())
    if request.is_xhr:
        if request.POST.pop("_update", None):
            # if update was requested, just render the page - otherwise handle actions as usual
            return config_page.render(is_xhr=True)
    # check if the button click wasn't any sub-action
    subaction = request.POST.pop("action", None)
    if subaction:
        return config_action_post(page_name, subaction)
    try:
        result = config_page.call_action(action)
        try:
            if not result:
                bottle.redirect(reverse("config_page", page_name=page_name))
        except TypeError:
            # raised by Validator - could happen when the form is posted with wrong fields
            messages.error(_("Configuration could not be saved due to an internal error."))
            logger.exception("Error when saving form.")
        logger.warning("Form not saved.")
        return result
    except ValueError:
        raise bottle.HTTPError(404, "Unknown action.")
Exemple #41
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
Exemple #42
0
 def __init__(self, low, high):
     self.error_msg = _("This value should be between %(low)s and %(high)s.") % dict(
         low=low, high=high
     )
     self._low = low
     self._high = high
     super(FloatRange, self).__init__(self.error_msg)
     self.js_validator_params = "[%s,%s]" % (low, high)
Exemple #43
0
 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
Exemple #44
0
def make_notification_title(notification):
    """
    Helper function for creating of human-readable notification title.

    :param notification: notification to create title for
    :return: translated string with notification title
    """
    notification_titles = {"news": _("News"), "update": _("Update"), "error": _("Error")}

    # minor abuse of gettext follows...
    locale_date = translate_datetime(
        datetime.strptime(notification["created_at"], "%Y-%m-%dT%H:%M:%S")
    )

    return _("%(notification)s from %(created_at)s") % dict(
        notification=notification_titles.get(notification["severity"], _("Notification")),
        created_at=locale_date,
    )
Exemple #45
0
def prepare_approval_item_message(approval_item, show_operation=True):
    if approval_item["op"] == "install":
        return ((_("Install") + " ") if show_operation else "") + u"%s (%s)" % (
            approval_item["name"],
            approval_item["new_ver"],
        )
    elif approval_item["op"] == "remove":
        return ((_("Uninstall") + " ") if show_operation else "") + u"%s" % (approval_item["name"],)
    elif approval_item["op"] == "upgrade":
        return ((_("Upgrade") + " ") if show_operation else "") + "%s (%s)" % (
            approval_item["name"],
            approval_item["new_ver"],
        )
    elif approval_item["op"] == "downgrade":
        return ((_("Downgrade") + " ") if show_operation else "") + "%s (%s)" % (
            approval_item["name"],
            approval_item["new_ver"],
        )
Exemple #46
0
 def get_menu_tag(cls):
     if current_state.updater_is_running:
         return {
             "show": current_state.updater_is_running,
             "hint": _("Updater is running"),
             "text": u"<i class='fas fa-sync rotate'></i>",
         }
     else:
         return ConfigPageMixin.get_menu_tag_static(cls)
Exemple #47
0
    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)

        wifi_form = fapi.ForisForm("wifi", form_data)
        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
Exemple #48
0
    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
Exemple #49
0
    def _action_test_notifications(self):
        if bottle.request.method != "POST":
            messages.error(_("Wrong HTTP method."))
            bottle.redirect(reverse("config_page", page_name="maintenance"))
        data = current_state.backend.perform(
            "router_notifications",
            "create",
            {
                "msg": "_(This is a testing notification. Please ignore me.)",
                "severity": "news",
                "immediate": True,
            },
        )

        if data["result"]:
            messages.success(_("Testing message was sent, please check your inbox."))
        else:
            messages.error(
                _("Sending of the testing message failed, your configuration is possibly wrong.")
            )
        bottle.redirect(reverse("config_page", page_name="maintenance"))
Exemple #50
0
    def save(self, *args, **kwargs):
        result = super(UpdaterConfigPage, self).save(no_messages=True, *args, **kwargs)

        target = self.form.callback_results.get("target", None)
        if target in ["deny", "grant"]:
            result = self.form.callback_results["result"]
            if result:
                if target == "grant":
                    messages.success(_("Update was approved."))
                elif target == "deny":
                    messages.success(_("Update was postponed."))
            else:
                if target == "grant":
                    messages.error(_("Failed to approve the update."))
                elif target == "deny":
                    messages.error(_("Failed to postpone the update."))
            return result

        if result:
            messages.success(
                _(
                    "Configuration was successfully saved. Selected "
                    "packages should be installed or removed shortly."
                )
            )
        else:
            messages.warning(_("There were some errors in your input."))
        return result
Exemple #51
0
    def save(self, *args, **kwargs):
        result = super(PasswordConfigPage, self).save(no_messages=True, *args, **kwargs)
        wrong_old_password = self.form.callback_results.get("wrong_old_password", False)
        system_password_no_error = self.form.callback_results.get("system_password_no_error", None)
        foris_password_no_error = self.form.callback_results.get("foris_password_no_error", None)

        compromised = self.form.callback_results.get("compromised")
        if compromised:
            messages.error(
                _(
                    "The password you've entered has been compromised. "
                    "It appears %(count)d times in '%(list)s' list."
                )
                % dict(count=compromised["count"], list=compromised["list"])
            )
            return result

        if wrong_old_password:
            messages.error(_("Old password you entered was not valid."))
            return result

        if system_password_no_error is not None:
            if system_password_no_error:
                messages.success(_("System password was successfully saved."))
            else:
                messages.error(_("Failed to save system password."))
        if foris_password_no_error is not None:
            if foris_password_no_error:
                messages.success(_("Foris password was successfully saved."))
            else:
                messages.error(_("Failed to save Foris password."))

        return result
Exemple #52
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
Exemple #53
0
def config_page_post(page_name):
    bottle.SimpleTemplate.defaults["active_config_page_key"] = page_name
    bottle.Jinja2Template.defaults["active_config_page_key"] = page_name
    ConfigPage = get_config_page(page_name)
    config_page = ConfigPage(request.POST.decode())
    if request.is_xhr:
        if request.POST.pop("_update", None):
            # if update was requested, just render the page - otherwise handle actions as usual
            pass
        else:
            config_page.save()
        return config_page.render(is_xhr=True)
    try:
        if config_page.save():
            bottle.redirect(request.fullpath)
    except TypeError:
        # raised by Validator - could happen when the form is posted with wrong fields
        messages.error(_("Configuration could not be saved due to an internal error."))
        logger.exception("Error when saving form.")
    logger.warning("Form not saved.")
    return config_page.render(active_config_page_key=page_name)
Exemple #54
0
    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
Exemple #55
0
def translate_datetime(datetime_instance, default="%Y/%m/%d %H:%M:%S"):
    """ Tries to "translate" the datetime.

    This functions should handle e.g. conversions between US / EU date format
    according to localized translation. So these formats were added to be translated.
    Unfortunatelly some translators used non-asci characters to format the date.
    That would raise an exception and this function handles that by adding a fallback format.

    :param datetime_instance: date to be formatted
    :type datetime_instance: datetime.datetime
    :param default: default format
    :type default: str

    :returns: formatted date
    :rtype: str
    """

    try:
        return datetime_instance.strftime(_("%Y/%m/%d %H:%M:%S"))
    except UnicodeEncodeError:
        # Unicode characters in translated format -> fallback to default
        return datetime_instance.strftime(default)
Exemple #56
0
 def __init__(self):
     super(IPv4Netmask, self).__init__(_("Not a valid IPv4 netmask address."))
Exemple #57
0
 def __init__(self):
     super(IPv4, self).__init__(_("Not a valid IPv4 address."))
Exemple #58
0
 def __init__(self):
     super(NotEmpty, self).__init__(_("This field is required."))
Exemple #59
0
 def __init__(self):
     super(Duid, self).__init__(_("Duid is not valid."))
     self.reg_exp = re.compile(r"^([0-9a-fA-F][0-9a-fA-F]){4}([0-9a-fA-F][0-9a-fA-F])*$")