From 4b730ef724aa4bb00ab764769dea0083eec7f40e Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Thu, 2 Apr 2026 10:09:27 -0400 Subject: [PATCH] Check user's jurisdiction and prevent installation at certain regions --- archinstall/lib/args.py | 4 ++++ archinstall/lib/general/general_menu.py | 16 ++++++++++++++++ archinstall/lib/global_menu.py | 21 ++++++++++++++++++++- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/archinstall/lib/args.py b/archinstall/lib/args.py index c61bc5a15f..cb8441acf4 100644 --- a/archinstall/lib/args.py +++ b/archinstall/lib/args.py @@ -72,6 +72,7 @@ class ArchConfig: hostname: str = 'archlinux' kernels: list[str] = field(default_factory=lambda: ['linux']) ntp: bool = True + jurisdiction_restriction: bool = False packages: list[str] = field(default_factory=list) parallel_downloads: int = 0 timezone: str = 'UTC' @@ -112,6 +113,7 @@ def safe_config(self) -> dict[str, Any]: 'bootloader_config': self.bootloader_config.json() if self.bootloader_config else None, 'app_config': self.app_config.json() if self.app_config else None, 'auth_config': self.auth_config.json() if self.auth_config else None, + 'jurisdiction_restriction': self.jurisdiction_restriction, } if self.locale_config: @@ -140,6 +142,8 @@ def from_config(cls, args_config: dict[str, Any], args: Arguments) -> Self: if script := args_config.get('script', None): arch_config.script = script + arch_config.jurisdiction_restriction = args_config.get('jurisdiction_restriction', False) + if archinstall_lang := args_config.get('archinstall-language', None): arch_config.archinstall_language = translation_handler.get_language_by_name(archinstall_lang) diff --git a/archinstall/lib/general/general_menu.py b/archinstall/lib/general/general_menu.py index 5a95762ead..e85f6cfc25 100644 --- a/archinstall/lib/general/general_menu.py +++ b/archinstall/lib/general/general_menu.py @@ -15,6 +15,22 @@ class PostInstallationAction(Enum): CHROOT = tr('chroot into installation for post-installation configurations') +async def select_jurisdiction(preset: bool = False) -> bool: + header = tr('Are you located in California, Brazil, or any other region that mandates operating systems to verify or assist to verify the age, name, sex, or any other identifying information of the user?') + '\n' + + result = await Confirmation( + header=header, + allow_skip=False, + preset=preset, + ).show() + + match result.type_: + case ResultType.Selection: + return result.item() == MenuItem.yes() + case _: + raise ValueError('Unhandled return type') + + async def select_ntp(preset: bool = True) -> bool: header = tr('Would you like to use automatic time synchronization (NTP) with the default time servers?\n') + '\n' header += ( diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index cae51df2c2..a6d42062e1 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -7,7 +7,7 @@ from archinstall.lib.bootloader.bootloader_menu import BootloaderMenu from archinstall.lib.configuration import save_config from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu -from archinstall.lib.general.general_menu import add_number_of_parallel_downloads, select_hostname, select_ntp, select_timezone +from archinstall.lib.general.general_menu import add_number_of_parallel_downloads, select_hostname, select_ntp, select_timezone, select_jurisdiction from archinstall.lib.general.system_menu import select_kernel, select_swap from archinstall.lib.hardware import SysInfo from archinstall.lib.locale.locale_menu import LocaleMenu @@ -61,6 +61,13 @@ def _get_menu_options(self) -> list[MenuItem]: preview_action=self._prev_archinstall_language, key='archinstall_language', ), + MenuItem( + text=tr('Jurisdiction Restriction'), + action=select_jurisdiction, + value=False, + preview_action=self._prev_jurisdiction, + key='jurisdiction_restriction', + ), MenuItem( text=tr('Locales'), value=LocaleConfiguration.default(), @@ -198,6 +205,7 @@ async def _safe_config(self) -> None: def _missing_configs(self) -> list[str]: item: MenuItem = self._item_group.find_by_key('auth_config') auth_config: AuthenticationConfiguration | None = item.value + jurisdiction_restriction_item: MenuItem = self._item_group.find_by_key('jurisdiction_restriction') def check(s: str) -> bool: item = self._item_group.find_by_key(s) @@ -205,6 +213,10 @@ def check(s: str) -> bool: missing = set() + if jurisdiction_restriction_item.value: + missing.add( + tr('We do not provide Arch Linux to your jurisdiction. Please contact your local lawmakers if you have any question.'), + ) if (auth_config is None or auth_config.root_enc_password is None) and not (auth_config and auth_config.has_superuser()): missing.add( tr('Either root-password or at least 1 user with sudo privileges must be specified'), @@ -372,6 +384,13 @@ def _prev_ntp(self, item: MenuItem) -> str | None: return output return None + def _prev_jurisdiction(self, item: MenuItem) -> str | None: + if item.value is not None: + output = f'{tr("Jurisdiction Restriction")}: ' + output += tr('Yes') if item.value else tr('No') + return output + return None + def _prev_disk_config(self, item: MenuItem) -> str | None: disk_layout_conf: DiskLayoutConfiguration | None = item.value