Beispiel #1
0
 def valuespec(self):
     return Checkbox(
         title=_("Rule based notifications"),
         label=_("Enable new rule based notifications"),
         help=
         _("If you enable the new rule based notifications then the current plain text email and "
           ""flexible notifications" will become inactive. Instead notificatios will "
           "be configured with the WATO module <i>Notifications</i> on a global base."),
     )
Beispiel #2
0
def _valuespec_inventory_mssql_counters_rules():
    return Dictionary(
        title=_("Include MSSQL Counters services"),
        elements=[
            ("add_zero_based_services",
             Checkbox(title=_("Include service with zero base."))),
        ],
        optional_keys=[],
    )
Beispiel #3
0
 def valuespec(self):
     return Checkbox(
         title=_("Visibility of Hosts/Services"),
         label=_("Only show hosts and services the user is a contact for"),
         help=_(
             "When this option is checked, then the status GUI will only "
             "display hosts and services that the user is a contact for - "
             "even if he has the permission for seeing all objects."),
     )
Beispiel #4
0
 def valuespec(self):
     choice = self._tag_group.get_tag_choices()[0]
     return Checkbox(
         title=self._tag_group.title,
         label=_u(choice[1]),
         true_label=self._tag_group.title,
         false_label="%s %s" % (_("Not"), self._tag_group.title),
         onclick="cmk.wato.fix_visibility();",
     )
Beispiel #5
0
 def valuespec(self):
     return Checkbox(
         title=_("Hosts/Service visibility (Webservice, Deprecated)"),
         label=_("Export only hosts and services the user is a contact for. "
                 "<b>Please don't use this option anymore, it is deprecated.</b>"),
         help=_("When this option is checked, then the Multisite webservice "
                "will only export hosts and services that the user is a contact for - "
                "even if he has the permission for seeing all objects."),
     )
Beispiel #6
0
 def valuespec(self):
     return Dictionary(
         title=_("Include MSSQL Counters services"),
         elements=[
             ("add_zero_based_services",
              Checkbox(title=_("Include service with zero base."))),
         ],
         optional_keys=[],
     )
Beispiel #7
0
def vs_bulk_discovery(render_form=False, include_subfolders=True):
    if render_form:
        render = "form"
    else:
        render = None

    if include_subfolders:
        selection_elements = [
            Checkbox(label=_("Include all subfolders"), default_value=True)
        ]
    else:
        selection_elements = []

    selection_elements += [
        Checkbox(
            label=_("Only include hosts that failed on previous discovery"),
            default_value=False),
        Checkbox(label=_("Only include hosts with a failed discovery check"),
                 default_value=False),
        Checkbox(label=_("Exclude hosts where the agent is unreachable"),
                 default_value=False),
    ]

    return Dictionary(
        title=_("Bulk discovery"),
        render=render,
        elements=[
            ("mode",
             RadioChoice(
                 title=_("Mode"),
                 orientation="vertical",
                 default_value="new",
                 choices=[
                     ("new", _("Add unmonitored services")),
                     ("remove", _("Remove vanished services")),
                     ("fixall",
                      _("Add unmonitored & remove vanished services")),
                     ("refresh", _("Refresh all services (tabula rasa)")),
                 ],
             )),
            ("selection",
             Tuple(title=_("Selection"), elements=selection_elements)),
            ("performance",
             Tuple(title=_("Performance options"),
                   elements=[
                       Checkbox(label=_("Use cached data if present"),
                                default_value=True),
                       Checkbox(label=_("Do full SNMP scan for SNMP devices"),
                                default_value=True),
                       Integer(label=_("Number of hosts to handle at once"),
                               default_value=10),
                   ])),
            ("error_handling",
             Checkbox(title=_("Error handling"),
                      label=_("Ignore errors in single check plugins"),
                      default_value=True)),
        ],
        optional_keys=[],
    )
Beispiel #8
0
def _parameter_valuespec_printer_supply():
    return Transform(
        Dictionary(elements=[
            (
                "levels",
                Tuple(
                    title=_("Levels for remaining supply"),
                    elements=[
                        Percentage(
                            title=_("Warning level for remaining"),
                            allow_int=True,
                            default_value=20.0,
                            help=
                            _("For consumable supplies, this is configured as the percentage of "
                              "remaining capacity. For supplies that fill up, this is configured "
                              "as remaining space."),
                        ),
                        Percentage(
                            title=_("Critical level for remaining"),
                            allow_int=True,
                            default_value=10.0,
                            help=
                            _("For consumable supplies, this is configured as the percentage of "
                              "remaining capacity. For supplies that fill up, this is configured "
                              "as remaining space."),
                        ),
                    ],
                ),
            ),
            (
                "some_remaining",
                MonitoringState(
                    title=_("State for <i>some remaining</i>"),
                    help=_(
                        "Some printers do not report a precise percentage but "
                        "just <i>some remaining</i> at a low fill state. Here you "
                        "can set the monitoring state for that situation"),
                    default_value=1,
                ),
            ),
            (
                "upturn_toner",
                Checkbox(
                    title=_("Upturn toner levels"),
                    label=
                    _("Printer sends <i>used</i> material instead of <i>remaining</i>"
                      ),
                    help=
                    _("Some Printers (eg. Konica for Drum Cartdiges) returning the available"
                      " fuel instead of what is left. In this case it's possible"
                      " to upturn the levels to handle this behavior"),
                ),
            ),
        ], ),
        forth=transform_printer_supply,
    )
Beispiel #9
0
def dashlet_vs_general_settings(dashlet: Dashlet, single_infos: List[str]):
    return Dictionary(
        title=_('General Settings'),
        render='form',
        optional_keys=['title', 'title_url'],
        elements=[
            ('type',
             FixedValue(
                 dashlet.type_name(),
                 totext=dashlet.title(),
                 title=_('Dashlet Type'),
             )),
            visuals.single_infos_spec(single_infos),
            ('background',
             Checkbox(
                 title=_('Colored Background'),
                 label=_('Render background'),
                 help=_(
                     'Render gray background color behind the dashlets content.'
                 ),
                 default_value=True,
             )),
            ('show_title',
             DropdownChoice(
                 title=_("Show title header"),
                 help=
                 _('Render the titlebar including title and link above the dashlet.'
                   ),
                 choices=[
                     (False, _("Don't show any header")),
                     (True, _("Show header with highlighted background")),
                     ("transparent", _("Show title without any background")),
                 ],
                 default_value=True,
             )),
            ('title',
             TextUnicode(
                 title=_('Custom Title') + '<sup>*</sup>',
                 help=
                 _('Most dashlets have a hard coded static title and some are aware of '
                   'its content and set the title dynamically, like the view snapin, which '
                   'displays the title of the view. If you like to use any other title, '
                   'set it here.'),
                 size=50,
             )),
            ("title_format", vs_title_infos()),
            ('title_url',
             TextUnicode(
                 title=_('Link of Title'),
                 help=
                 _('The URL of the target page the link of the dashlet should link to.'
                   ),
                 size=50,
             )),
        ],
    )
Beispiel #10
0
    def _vs_mandatory_elements(self):
        ident_attr: List = []
        if self._new:
            ident_attr = [
                ("ident",
                 ID(
                     title=_("Unique ID"),
                     help=_("The ID must be a unique text. It will be used as an internal key "
                            "when objects refer to this object."),
                     default_value=self._default_id,
                     allow_empty=False,
                     size=80,
                 )),
            ]
        else:
            ident_attr = [
                ("ident", FixedValue(
                    self._ident,
                    title=_("Unique ID"),
                )),
            ]

        if self._mode_type.is_site_specific():
            site_attr = [
                ("site", self._mode_type.site_valuespec()),
            ]
        else:
            site_attr = []

        if self._mode_type.can_be_disabled():
            disable_attr = [
                ("disabled",
                 Checkbox(
                     title=_("Activation"),
                     help=_("Disabled %s are kept in the configuration but are not active.") %
                     self._mode_type.name_singular(),
                     label=_("do not activate this %s") % self._mode_type.name_singular(),
                 )),
            ]
        else:
            disable_attr = []

        elements = ident_attr + [
            ("title",
             TextUnicode(
                 title=_("Title"),
                 help=_("The title of the %s. It will be used as display name.") %
                 (self._mode_type.name_singular()),
                 allow_empty=False,
                 size=80,
             )),
            ("comment", RuleComment()),
            ("docu_url", DocumentationURL()),
        ] + disable_attr + site_attr

        return elements
Beispiel #11
0
def _parameter_valuespec_netapp_luns():
    return Transform(
        Dictionary(
            title=_("Configure levels for used space"),
            elements=[
                (
                    "ignore_levels",
                    FixedValue(
                        title=_("Ignore used space (this option disables any other options)"),
                        help=_(
                            "Some luns, e.g. jfs formatted, tend to report incorrect used space values"
                        ),
                        totext=_("Ignore used space"),
                        value=True,
                    ),
                ),
                (
                    "levels",
                    Alternative(
                        title=_("Levels for LUN"),
                        show_alternative_title=True,
                        default_value=(80.0, 90.0),
                        match=match_dual_level_type,
                        elements=[
                            get_free_used_dynamic_valuespec("used", "LUN"),
                            Transform(
                                get_free_used_dynamic_valuespec(
                                    "free", "LUN", default_value=(20.0, 10.0)
                                ),
                                forth=transform_filesystem_free,
                                back=transform_filesystem_free,
                            ),
                        ],
                    ),
                ),
            ]
            + size_trend_elements
            + [
                (
                    "read_only",
                    Checkbox(
                        title=_("LUN is read-only"),
                        help=_(
                            "Display a warning if a LUN is not read-only. Without "
                            "this setting a warning will be displayed if a LUN is "
                            "read-only."
                        ),
                        label=_("Enable"),
                    ),
                ),
            ],
        ),
        forth=transform_trend_mb_to_trend_bytes,
    )
Beispiel #12
0
def dashlet_vs_general_settings(dashlet_type: Type[Dashlet], single_infos: List[str]):
    return Dictionary(
        title=_('General Settings'),
        render='form',
        optional_keys=['title', 'title_url'],
        elements=[
            ('type',
             FixedValue(
                 dashlet_type.type_name(),
                 totext=dashlet_type.title(),
                 title=_('Element type'),
             )),
            visuals.single_infos_spec(single_infos),
            ('background',
             Checkbox(
                 title=_('Colored background'),
                 label=_('Render background'),
                 help=_('Render gray background color behind the elements content.'),
                 default_value=True,
             )),
            ('show_title',
             DropdownChoice(
                 title=_("Show title header"),
                 help=_('Render the titlebar including title and link above the element.'),
                 choices=[
                     (False, _("Don't show any header")),
                     (True, _("Show header with highlighted background")),
                     ("transparent", _("Show title without any background")),
                 ],
                 default_value=True,
             )),
            ('title',
             TextInput(
                 title=_('Custom title') + '<sup>*</sup>',
                 placeholder=_(
                     "This option is macro-capable, please check the inline help for more "
                     "information."),
                 help=" ".join((
                     _('Most elements have a hard coded static title and some are aware of their '
                       'content and set the title dynamically, like the view snapin, which '
                       'displays the title of the view. If you like to use any other title, set it '
                       'here.'),
                     _title_help_text_for_macros(dashlet_type),
                 )),
                 size=75,
             )),
            ('title_url',
             TextInput(
                 title=_('Link of Title'),
                 help=_('The URL of the target page the link of the element should link to.'),
                 size=50,
             )),
        ],
    )
Beispiel #13
0
 def custom_job_attributes(self):
     return [
         ("no_history",
          Checkbox(
              title=_("Do not backup historical data"),
              help=_(
                  "You may use this option to create a much smaller partial backup of the site."
              ),
              label=_(
                  "Do not backup metric data (RRD files), the monitoring history and log files"),
          )),
     ]
Beispiel #14
0
def _valuespec_mssql_transactionlogs_discovery():
    return Dictionary(
        title=_("MSSQL datafile and transactionlog discovery"),
        elements=[
            (
                "summarize_datafiles",
                Checkbox(
                    title=_("Display only a summary of all Datafiles"),
                    label=_("Summarize Datafiles"),
                ),
            ),
            (
                "summarize_transactionlogs",
                Checkbox(
                    title=_("Display only a summary of all Transactionlogs"),
                    label=_("Summarize Transactionlogs"),
                ),
            ),
        ],
        optional_keys=[],
    )
Beispiel #15
0
def _parameter_valuespec_lnx_quota():
    return Dictionary(
        optional_keys=False,
        elements=[
            (
                "user",
                Checkbox(
                    title=_("Monitor user quotas"),
                    label=_("Enable"),
                    default_value=True,
                ),
            ),
            (
                "group",
                Checkbox(
                    title=_("Monitor group quotas"),
                    label=_("Enable"),
                ),
            ),
        ],
    )
Beispiel #16
0
def _parameter_valuespec_prism_alerts():
    return Dictionary(
        elements=[
            ("prism_central_only",
             Checkbox(
                 title=_("Consider alerts for Prism Central only"),
                 label=_("Activate (off: consider all alerts)"),
                 default_value=True,
             )),
        ],
        required_keys=[],
    )
Beispiel #17
0
def _valuespec_discovery_win_dhcp_pools():
    return Dictionary(
        title=_("Windows DHCP pool discovery"),
        elements=[
            ("empty_pools",
             Checkbox(
                 title=_("Discovery of empty DHCP pools"),
                 label=_("Include empty pools into the monitoring"),
                 help=_("You can activate the creation of services for "
                        "DHCP pools, which contain no IP addresses."),
             )),
        ],
    )
Beispiel #18
0
 def _vs_upload(self):
     return Dictionary(
         elements=[
             ("file", UploadOrPasteTextFile(
                 title=_("Import Hosts"),
                 file_title=_("CSV File"),
             )),
             ("do_service_detection", Checkbox(title=_("Perform automatic service discovery"),)),
         ],
         render="form",
         title=_("Import Hosts"),
         optional_keys=[],
     )
Beispiel #19
0
def _parameter_valuespec_brocade_optical():
    return Dictionary(
        elements=[
            ('temp', Checkbox(title=_("Temperature Alert"),
                              default_value=True)),
            ('tx_light',
             Checkbox(title=_("TX Light alert"),
                      label=_("TX Light alert"),
                      default_value=False)),
            ('rx_light',
             Checkbox(title=_("RX Light alert"),
                      label=_("TX Light alert"),
                      default_value=False)),
            ('lanes',
             Checkbox(
                 title=_("Lanes"),
                 label=_("Monitor & Graph Lanes"),
                 help=_("Monitor and graph the lanes, if the port has multiple"
                        ))),
        ],
        optional_keys=[],
    )
Beispiel #20
0
def vs_bulk_discovery(render_form=False, include_subfolders=True):
    selection_elements: List[ValueSpec] = []

    if include_subfolders:
        selection_elements.append(Checkbox(label=_("Include all subfolders"), default_value=True))

    selection_elements += [
        Checkbox(
            label=_("Only include hosts that failed on previous discovery"), default_value=False
        ),
        Checkbox(label=_("Only include hosts with a failed discovery check"), default_value=False),
        Checkbox(label=_("Exclude hosts where the agent is unreachable"), default_value=False),
    ]

    return Dictionary(
        title=_("Bulk discovery"),
        render="form" if render_form else "normal",
        elements=[
            (
                "mode",
                DropdownChoice(
                    title=_("Mode"),
                    default_value="new",
                    choices=[
                        ("new", _("Add unmonitored services and new host labels")),
                        ("remove", _("Remove vanished services")),
                        (
                            "fixall",
                            _(
                                "Add unmonitored services and new host labels, remove vanished services"
                            ),
                        ),
                        ("refresh", _("Refresh all services (tabula rasa), add new host labels")),
                        ("only-host-labels", _("Only discover new host labels")),
                    ],
                ),
            ),
            ("selection", Tuple(title=_("Selection"), elements=selection_elements)),
            (
                "performance",
                Tuple(
                    title=_("Performance options"),
                    elements=[
                        Checkbox(label=_("Do a full service scan"), default_value=True),
                        Integer(label=_("Number of hosts to handle at once"), default_value=10),
                    ],
                ),
            ),
            (
                "error_handling",
                Checkbox(
                    title=_("Error handling"),
                    label=_("Ignore errors in single check plugins"),
                    default_value=True,
                ),
            ),
        ],
        optional_keys=[],
    )
Beispiel #21
0
 def vs_parameters(cls):
     return [
         ("url", TextInput(
             title=_('URL'),
             size=50,
             allow_empty=False,
         )),
         ("show_in_iframe",
          Checkbox(
              title=_('Render in iframe'),
              label=_('Render URL contents in own frame'),
              default_value=True,
          )),
     ]
Beispiel #22
0
def _valuespec_inventory_heartbeat_crm_rules():
    return Dictionary(
        title=_("Heartbeat CRM Discovery"),
        elements=[
            ("naildown_dc",
             Checkbox(
                 title=_("Naildown the DC"),
                 label=_("Mark the currently distinguished controller as preferred one"),
                 help=_(
                     "Nails down the DC to the node which is the DC during discovery. The check "
                     "will report CRITICAL when another node becomes the DC during later checks."))
            ),
            ("naildown_resources",
             Checkbox(
                 title=_("Naildown the resources"),
                 label=_("Mark the nodes of the resources as preferred one"),
                 help=_(
                     "Nails down the resources to the node which is holding them during discovery. "
                     "The check will report CRITICAL when another holds the resource during later checks."
                 ))),
        ],
        help=_('This rule can be used to control the discovery for Heartbeat CRM checks.'),
        optional_keys=[],
    )
Beispiel #23
0
def _parameter_valuespec_windows_updates():
    return Tuple(
        title=_("Parameters for the Windows Update Check with WSUS"),
        help=_("Set the according numbers to 0 if you want to disable alerting."),
        elements=[
            Integer(title=_("Warning if at least this number of important updates are pending")),
            Integer(title=_("Critical if at least this number of important updates are pending")),
            Integer(title=_("Warning if at least this number of optional updates are pending")),
            Integer(title=_("Critical if at least this number of optional updates are pending")),
            Age(title=_("Warning if time until forced reboot is less then"), default_value=604800),
            Age(title=_("Critical if time time until forced reboot is less then"),
                default_value=172800),
            Checkbox(title=_("display all important updates verbosely"), default_value=True),
        ],
    )
Beispiel #24
0
def _valuespec_inventory_multipath_rules():
    return Dictionary(
        title=_("Linux Multipath Inventory"),
        elements=[
            ("use_alias",
             Checkbox(
                 title=_("Use the multipath alias as service name, if one is set"),
                 label=_("use alias"),
                 help=_(
                     "If a multipath device has an alias then you can use it for specifying "
                     "the device instead of the UUID. The alias will then be part of the service "
                     "description. The UUID will be displayed in the plugin output."))),
        ],
        help=_(
            "This rule controls whether the UUID or the alias is used in the service description during "
            "discovery of Multipath devices on Linux."),
    )
Beispiel #25
0
def cgroup_match_options():
    return Tuple(
        title=_("Operating system control group information"),
        elements=[
            Alternative(
                elements=[
                    TextInput(
                        title=
                        _("Exact content of the operating system control group info"
                          ),
                        label=_("Control group:"),
                        size=50,
                    ),
                    Transform(
                        RegExp(
                            size=50,
                            mode=RegExp.prefix,
                        ),
                        title=_(
                            "Regular expression matching control group info"),
                        help=_(
                            "This regex must match the <i>beginning</i> of the complete "
                            "control group information"),
                        forth=lambda x: x[1:],  # remove ~
                        back=lambda x: "~" + x,  # prefix ~
                    ),
                    FixedValue(
                        None,
                        totext="",
                        title=_("Match all control groups"),
                    ),
                ],
                match=match_alt,
                help=
                _("<p>The control group information is currently only specified by the linux agent"
                  " (cgroup). If it is present and this rule is set, the inventory will only trigger"
                  " if the control group of the corresponding process matches."
                  " For instance: you can use this rule to exclude all processes belonging to"
                  ' a docker container by specifying the expression "%s" (without the quotes),'
                  ' and selecting "%s".</p>') %
                (r".*/docker/", _("Invert matching")),
            ),
            Checkbox(label=_("Invert matching"), default_value=False),
        ],
    )
Beispiel #26
0
def _vs_annotation():
    extra_elements: List[Tuple[str, ValueSpec]] = []
    if not cmk_version.is_raw_edition():
        extra_elements.append(("hide_from_report", Checkbox(title=_("Hide annotation in report"))))

    return Dictionary(
        elements=[
            ("site", TextAscii(title=_("Site"))),
            ("host", TextUnicode(title=_("Hostname"))),
            ("host_state",
             Optional(
                 HostState(),
                 sameline=True,
                 title=_("Host state"),
                 label=_("Reclassify host state of this period"),
             )),
            ("service",
             Optional(TextUnicode(allow_empty=False),
                      sameline=True,
                      title=_("Service"),
                      label=_("Service description"))),
            ("service_state",
             Optional(
                 MonitoringState(),
                 sameline=True,
                 title=_("Service state"),
                 label=_("Reclassify service state of this period"),
             )),
            ("from", AbsoluteDate(title=_("Start-Time"), include_time=True)),
            ("until", AbsoluteDate(title=_("End-Time"), include_time=True)),
            ("downtime",
             Optional(
                 DropdownChoice(choices=[
                     (True, _("regard as scheduled downtime")),
                     (False, _("do not regard as scheduled downtime")),
                 ],),
                 title=_("Scheduled downtime"),
                 label=_("Reclassify downtime of this period"),
             )),
            ("text", TextAreaUnicode(title=_("Annotation"), allow_empty=False)),
        ] + extra_elements,
        title=_("Edit annotation"),
        optional_keys=[],
        validate=_validate_reclassify_of_states,
    )
Beispiel #27
0
    def parameters(cls, mode):
        parameters = super(PageRenderer, cls).parameters(mode)

        parameters += [(_("General Properties"), [
            (1.4, 'topic',
             TextUnicode(
                 title=_('Topic') + '<sup>*</sup>',
                 size=50,
                 allow_empty=False,
             )),
            (2.0, 'hidden',
             Checkbox(
                 title=_("Sidebar integration"),
                 label=_('Do not add a link to this page in sidebar'),
             )),
        ])]

        return parameters
Beispiel #28
0
 def _tls_valuespec(cls):
     return CascadingDropdown(
         title=_("Encryption"),
         choices=[
             (
                 "plain_text",
                 _("Plain text (Unencrypted)"),
                 FixedValue(
                     value={},
                     totext=_("Use plain text, unencrypted transport")),
             ),
             (
                 "encrypted",
                 _("Encrypt data using TLS"),
                 Dictionary(
                     elements=[
                         (
                             "verify",
                             Checkbox(
                                 title=_("Verify server certificate"),
                                 label=
                                 _("Verify the Livestatus server certificate using the local site CA"
                                   ),
                                 default_value=True,
                                 help=
                                 _("Either verify the server certificate using the site local CA or accept "
                                   "any certificate offered by the server. It is highly recommended to "
                                   "leave this enabled."),
                             ),
                         ),
                     ],
                     optional_keys=False,
                 ),
             ),
         ],
         help=
         _("When connecting to Check_MK versions older than 1.6 you can only use plain text "
           "transport. Starting with Check_MK 1.6 it is possible to use encrypted Livestatus "
           "communication. Sites created with 1.6 will automatically use encrypted communication "
           "by default. Sites created with previous versions need to be configured manually to "
           'enable the encryption. Have a look at <a href="werk.py?werk=7017">werk #7017</a> '
           "for further information."),
     )
Beispiel #29
0
def _discovery_valuespec_snapvault():
    return Dictionary(
        elements=[
            (
                "exclude_destination_vserver",
                Checkbox(
                    title=_("Exclude destination vserver"),
                    help=_("Only applicable to clustermode installations. "
                           "The service description of snapvault services is composed of the "
                           "destination vserver (SVM) and the destination volume by default. Check "
                           "this box if you would like to use the destination volume as the "
                           "service description on its own. "
                           "Please be advised that this may lead to a service description that is "
                           "not unique, resulting in some services, which are not shown!"),
                ),
            ),
        ],
        title=_('NetApp snapvault discovery'),
    )
Beispiel #30
0
def _vs_activation(title: str, has_foreign_changes: bool) -> Optional[Dictionary]:
    elements: List[DictionaryEntry] = []

    if active_config.wato_activate_changes_comment_mode != "disabled":
        is_optional = active_config.wato_activate_changes_comment_mode != "enforce"
        elements.append(
            (
                "comment",
                TextAreaUnicode(
                    title=_("Comment (optional)") if is_optional else _("Comment"),
                    cols=40,
                    try_max_width=True,
                    rows=1,
                    help=_(
                        "You can provide an optional comment for the current activation. "
                        "This can be useful to document the reason why the changes you "
                        "activate have been made."
                    ),
                    allow_empty=is_optional,
                ),
            )
        )

    if has_foreign_changes and user.may("wato.activateforeign"):
        elements.append(
            (
                "foreign",
                Checkbox(
                    title=_("Activate foreign changes"),
                    label=_("Activate changes of other users"),
                ),
            )
        )

    if not elements:
        return None

    return Dictionary(
        title=title,
        elements=elements,
        optional_keys=[],
        render="form_part",
    )