usermod -G on each user. Primary-group members (users whose primary gid is {gid}) appear below but cannot be removed from here.",
+ "groups_members_title": "Members",
+ "groups_nav_description": "Unix groups from /etc/group on this machine.",
+ "groups_nav_title": "Groups",
+ "groups_no_results": "No groups found.",
+ "groups_no_supplementary_members": "No supplementary members.",
+ "groups_not_found": "Group not found: {name}",
+ "groups_primary_empty": "None.",
+ "groups_primary_label": "Primary ({count})",
+ "groups_search_placeholder": "Search name or gid…",
+ "groups_supplementary_label": "Supplementary ({count})",
"home": "Home",
"invalid_reset_link": "This link is invalid or has expired.",
+ "language": "Language",
"login": "Login",
"login_social_description": "You have to login to use this platform. Use your favorite social or your credentials",
"login_with": "Login with {social}",
"logout": "Logout",
+ "machine_actions": "Server actions",
+ "machine_add": "Add server",
+ "machine_add_description": "Connect a new server to manage from this dashboard.",
+ "machine_address": "Address",
+ "machine_address_placeholder": "http://127.0.0.1:9999",
+ "machine_delete_confirm": "This permanently removes \"{name}\" from the database. The connected server is not touched.",
+ "machine_delete_title": "Delete server?",
+ "machine_edit": "Edit server",
+ "machine_edit_description": "Update the connection details for this server.",
+ "machine_name": "Name",
+ "machine_name_placeholder": "Production server",
+ "machine_none": "No servers yet.",
+ "machine_offline_code": "Error 502",
+ "machine_offline_description": "Could not reach the nadir-agent at {address}. The host may be down, the agent stopped, or the address is wrong.",
+ "machine_offline_details": "Show error details",
+ "machine_offline_node_dest": "Agent",
+ "machine_offline_node_proxy": "Web UI",
+ "machine_offline_node_you": "You",
+ "machine_offline_status_connected": "CONNECTED",
+ "machine_offline_status_unreachable": "UNREACHABLE",
+ "machine_offline_title": "{name} is offline",
+ "machine_save": "Add server",
+ "machine_save_edit": "Save changes",
+ "machine_search_placeholder": "Search servers…",
+ "machine_token": "Token",
+ "machine_token_keep": "Leave blank to keep the current token.",
+ "machine_token_placeholder": "Agent bearer token",
"manual_entry_key": "Can't scan? Enter this key in your authenticator app manually:",
"name": "Name",
"name_placeholder": "Jane Doe",
@@ -152,40 +203,27 @@
"nav_admin_config_desc": "Application-wide configuration.",
"nav_admin_users": "Users",
"nav_admin_users_desc": "Manage user accounts, roles and access.",
- "cancel": "Cancel",
- "delete": "Delete",
- "edit": "Edit",
- "machine_actions": "Server actions",
- "machine_add": "Add server",
- "machine_add_description": "Connect a new server to manage from this dashboard.",
- "machine_delete_confirm": "This permanently removes \"{name}\" from the database. The connected server is not touched.",
- "machine_delete_title": "Delete server?",
- "machine_edit": "Edit server",
- "machine_edit_description": "Update the connection details for this server.",
- "machine_save_edit": "Save changes",
- "machine_token_keep": "Leave blank to keep the current token.",
- "machine_address": "Address",
- "machine_address_placeholder": "http://127.0.0.1:9999",
- "machine_name": "Name",
- "machine_name_placeholder": "Production server",
- "machine_none": "No servers yet.",
- "machine_save": "Add server",
- "machine_search_placeholder": "Search servers…",
- "machine_token": "Token",
- "machine_token_placeholder": "Agent bearer token",
"nav_dashboard_overview": "Overview",
"nav_dashboard_overview_desc": "System status at a glance.",
- "pagination_next": "Next",
- "pagination_page_of": "Page {page} of {pages}",
- "pagination_previous": "Previous",
"nav_system": "System",
"nav_system_datetime": "Date & Time",
"nav_system_datetime_desc": "Clock, timezone and time synchronisation.",
+ "nav_system_hostname": "Hostname",
+ "nav_system_hostname_desc": "Identify this machine on the network.",
"nav_system_localization": "Localization",
"nav_system_localization_desc": "Language, locale and region settings.",
+ "nav_system_power": "Power",
+ "nav_system_power_desc": "Reboot or power off the machine.",
+ "nav_users_groups": "Groups",
+ "nav_users_groups_desc": "Unix groups from /etc/group.",
+ "nav_users_system_users": "System users",
+ "nav_users_system_users_desc": "PAM/Unix accounts on this machine.",
"new_password": "New password",
"no_account": "No account yet?",
"or": "Or",
+ "pagination_next": "Next",
+ "pagination_page_of": "Page {page} of {pages}",
+ "pagination_previous": "Previous",
"password": "Password",
"password_hint": "At least 8 characters, mixing upper- and lower-case letters and a number.",
"privacy_policy": "Privacy Policy",
@@ -194,14 +232,56 @@
"reset_password_action": "Update password",
"reset_password_description": "Choose a strong password you don't use anywhere else.",
"reset_password_title": "Set a new password",
+ "save": "Save",
+ "saved": "Saved",
"scan_qr": "Add this key to your authenticator app, then enter the generated code below.",
"send_reset_link": "Send reset link",
+ "settings": "Settings",
"setup_2fa_description": "Add an extra layer of security to your account.",
"setup_2fa_title": "Set up two-factor authentication",
"sign_up": "Sign up",
"sign_up_description": "Sign up with your email and a username.",
"sign_up_title": "Create your account",
+ "system_hostname_current": "Current hostname",
+ "system_hostname_invalid": "Hostname is invalid",
+ "system_locale_generate": "Generate new locale",
+ "system_locale_generate_button": "Generate",
+ "system_locale_generate_desc": "Install a new locale on the host. On Debian/Ubuntu/Arch this uncomments the entry in /etc/locale.gen and runs locale-gen; on RHEL/Fedora it uses localedef.",
+ "system_locale_generate_invalid": "Use the form xx_XX.UTF-8 (e.g. fr_FR.UTF-8)",
+ "system_locale_generate_placeholder": "e.g. ja_JP.UTF-8",
+ "system_locale_keymap": "Console keymap",
+ "system_locale_lang": "System locale (LANG)",
+ "system_locale_language": "Fallback language (LANGUAGE)",
+ "system_locale_language_add": "Add language",
+ "system_locale_language_button": "Save",
+ "system_locale_language_desc": "Set the fallback language priority list for system messages and translations (optional).",
+ "system_locale_language_empty": "No fallback language set.",
+ "system_locale_language_placeholder": "e.g. en_US:en",
+ "system_locale_no_keymap_found": "No keymap found.",
+ "system_locale_no_locale_found": "No locale found.",
+ "system_locale_search_keymap_placeholder": "Search keymap…",
+ "system_locale_search_locale_placeholder": "Search locale…",
+ "system_locale_x11": "X11 layout",
+ "system_power_confirm_description": "The machine will be unreachable while it shuts down. This cannot be undone from here.",
+ "system_power_confirm_poweroff_title": "Power off this machine?",
+ "system_power_confirm_reboot_title": "Reboot this machine?",
+ "system_power_poweroff": "Power off",
+ "system_power_reboot": "Reboot",
+ "system_time_current": "Current time",
+ "system_time_manual": "Manual time",
+ "system_time_manual_hint": "Set the system clock to a specific RFC3339 time. Available only when NTP is off.",
+ "system_time_no_timezone_found": "No timezone found.",
+ "system_time_ntp": "Network time (NTP)",
+ "system_time_ntp_hint": "Automatically synchronize the clock with NTP servers.",
+ "system_time_ntp_not_synced": "Not synchronized",
+ "system_time_ntp_synced": "Synchronized",
+ "system_time_search_timezone_placeholder": "Search timezone…",
+ "system_time_timezone": "Timezone",
"terms_notice": "By clicking continue, you agree to our Terms of Service and Privacy Policy.",
+ "theme": "Theme",
+ "theme_dark": "Dark",
+ "theme_light": "Light",
+ "theme_system": "System",
"trust_device": "Trust this device for 30 days",
"two_factor_description": "Enter the 6-digit code from your authenticator app.",
"two_factor_title": "Two-factor authentication",
@@ -209,76 +289,100 @@
"use_backup_code": "Use a backup code",
"username": "Username",
"username_placeholder": "admin",
- "verification_sent": "We sent a verification link to {email}. Click it to activate your account.",
- "verify": "Verify",
- "verify_your_email": "You need to first verify your email address",
- "welcome_back": "Welcome back",
- "users_title": "Users",
- "users_description": "Manage application users.",
- "users_add": "Add User",
- "users_create": "Create",
- "users_edit": "Edit",
- "users_delete": "Delete",
- "users_ban": "Ban",
- "users_unban": "Unban",
- "users_search_placeholder": "Search by email…",
- "users_rows_per_page": "Rows per page",
- "users_role": "Role",
- "users_role_user": "User",
- "users_role_admin": "Admin",
- "users_created_at": "Joined",
- "users_status": "Status",
- "users_banned": "Banned",
- "users_active": "Active",
+ "users_action_set_password": "Set password",
"users_actions": "Actions",
- "users_create_title": "Create user",
- "users_create_description": "Add a new user to the system.",
- "users_edit_title": "Edit user",
- "users_edit_description": "Update user details.",
- "users_delete_confirm_title": "Delete user?",
- "users_delete_confirm_description": "This permanently removes the user. Optionally ban the email to prevent re-registration.",
- "users_delete_ban_email": "Also ban this email",
- "users_ban_reason": "Reason (optional)",
- "users_no_results": "No users found.",
- "users_page_of": "Page {page} of {total}",
- "users_prev": "Previous",
- "users_next": "Next",
- "users_saved": "User saved",
- "users_created": "User created",
- "users_deleted": "User deleted",
+ "users_active": "Active",
+ "users_add": "Add User",
+ "users_ban": "Ban",
"users_ban_action_title": "Ban user?",
- "cancel": "Cancel",
+ "users_ban_reason": "Reason (optional)",
+ "users_banned": "Banned",
+ "users_col_comment": "Comment",
+ "users_col_home": "Home",
+ "users_col_type": "Type",
+ "users_create": "Create",
+ "users_create_description": "Add a new user to the system.",
+ "users_create_field_comment": "Comment (GECOS)",
+ "users_create_field_create_home": "Create home directory",
+ "users_create_field_shell": "Shell",
+ "users_create_field_system": "System account",
+ "users_create_title": "Create user",
+ "users_created": "User created",
+ "users_created_at": "Joined",
+ "users_delete": "Delete",
+ "users_delete_ban_email": "Also ban this email",
+ "users_delete_confirm_description": "This permanently removes the user. Optionally ban the email to prevent re-registration.",
+ "users_delete_confirm_title": "Delete user?",
+ "users_delete_description": "Runs userdel on the host. This cannot be undone.",
+ "users_delete_field_remove_home": "Also remove home directory and mail spool",
+ "users_delete_title": "Delete {username}?",
+ "users_deleted": "User deleted",
+ "users_description": "Manage application users.",
+ "users_details": "Details",
+ "users_edit": "Edit",
+ "users_edit_description": "Update user details.",
+ "users_edit_title": "Edit user",
"users_filter": "Filter",
- "users_filter_title": "Filter Users",
+ "users_filter_24h": "Last 24h",
+ "users_filter_30d": "Last 30 days",
+ "users_filter_7d": "Last 7 days",
"users_filter_active": "Active",
"users_filter_active_hint": "Users with a recent session.",
- "users_filter_joined": "Joined",
"users_filter_any_time": "Any Time",
- "users_filter_24h": "Last 24h",
- "users_filter_7d": "Last 7 days",
- "users_filter_30d": "Last 30 days",
- "users_filter_date_range": "Date Range",
- "users_filter_date_from": "From",
- "users_filter_date_to": "To",
- "users_filter_email_verified": "Email verified only",
- "users_filter_online_only": "Online users only",
- "users_filter_online_hint": "Users with an active session.",
- "users_filter_show_banned": "Show banned users",
- "users_filter_display": "Display",
- "users_filter_reset": "Reset All",
"users_filter_count": "{n} filters active",
+ "users_filter_date_from": "From",
+ "users_filter_date_range": "Date Range",
+ "users_filter_date_to": "To",
+ "users_filter_display": "Display",
+ "users_filter_email_verified": "Email verified only",
+ "users_filter_joined": "Joined",
+ "users_filter_online_hint": "Users with an active session.",
+ "users_filter_online_only": "Online users only",
+ "users_filter_reset": "Reset All",
+ "users_filter_shell_only": "Login-capable shell only",
+ "users_filter_show_banned": "Show banned users",
+ "users_filter_show_system": "Show system users",
+ "users_filter_system_uid_hint": "(uid < 1000)",
+ "users_filter_title": "Filter Users",
+ "users_group_primary_badge": "(primary)",
+ "users_group_sys_badge": "sys",
+ "users_groups_title": "Groups",
+ "users_pam_groups_description": "Supplementary groups. Replaces the full set via usermod -G. Primary group is set at user creation and not editable here.",
+ "users_groups_updated": "Groups updated",
"users_invite": "Invite",
- "users_invite_title": "Invite user",
"users_invite_description": "Send an email invitation. The user sets their own password.",
+ "users_invite_title": "Invite user",
"users_invited": "Invitation sent",
+ "users_nav_description": "PAM/Unix accounts from /etc/passwd on this machine.",
+ "users_nav_title": "System users",
+ "users_next": "Next",
+ "users_no_gecos": "No GECOS comment",
+ "users_no_groups": "No groups.",
+ "users_no_results": "No users found.",
+ "users_page_of": "Page {page} of {total}",
+ "users_pam_create_description": "Adds a PAM account via useradd. Password stays locked until you set one.",
+ "users_pam_search_placeholder": "Search username, GECOS, uid…",
"users_pending": "Pending",
"users_pending_expires": "Invite expires {date}",
"users_pending_no_invite": "Email not verified",
+ "users_prev": "Previous",
+ "users_primary_gid": "Primary GID",
"users_resend_invite": "Resend invite",
- "settings": "Settings",
- "theme": "Theme",
- "theme_light": "Light",
- "theme_dark": "Dark",
- "theme_system": "System",
- "language": "Language"
+ "users_role": "Role",
+ "users_role_admin": "Admin",
+ "users_role_user": "User",
+ "users_rows_per_page": "Rows per page",
+ "users_saved": "User saved",
+ "users_search_placeholder": "Search by email…",
+ "users_set_password_description": "Piped to chpasswd over stdin; never appears in the process list.",
+ "users_set_password_title": "Set password — {username}",
+ "users_status": "Status",
+ "users_title": "Users",
+ "users_type_system": "system",
+ "users_type_user": "user",
+ "users_unban": "Unban",
+ "verification_sent": "We sent a verification link to {email}. Click it to activate your account.",
+ "verify": "Verify",
+ "verify_your_email": "You need to first verify your email address",
+ "welcome_back": "Welcome back"
}
diff --git a/package.json b/package.json
index 2c2b5ab..2cfcbca 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
+ "type:generate": "bunx openapi-typescript http://100.64.0.189:9999/openapi.json -o ./src/lib/server/nadir-agent/schema.d.ts",
"db:push": "drizzle-kit push",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
@@ -74,6 +75,7 @@
"ogl": "^1.0.11",
"openapi-fetch": "^0.17.0",
"runed": "^0.37.1",
+ "swapy": "^1.0.5",
"uqr": "^0.1.3",
"valibot": "^1.4.1"
}
diff --git a/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte b/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte
index bb4db41..4763e6d 100644
--- a/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte
+++ b/src/lib/components/blocks/breadcrumbs/breadcrumbs.svelte
@@ -5,16 +5,22 @@
import { page } from '$app/state';
import * as Breadcrumb from '$lib/components/ui/breadcrumb';
import { m } from '$lib/paraglide/messages';
+ import { getMachine } from '$lib/remotes/machines.remote';
+
+ const machine = $derived(page.params.machineId ? getMachine(page.params.machineId) : null);
const LABELS: Record{m.machine_none()}
+ {/each} +{m.users_description()}
++ {m.users_description()} +
- {sys.os.hostname} | {sys.os.pretty_name} | {sys.$db.address} + {sys.os.hostname} | {sys.os.pretty_name} | {sys.$agent_version} | {sys.$db.address}
{kms.reason}
+ {:else} ++ {m.users_nav_description()} +
+{u.comment || m.users_no_gecos()}
++ {m.groups_nav_description()} +
+gid {group.gid}
+