feat(web): sign-in, first-run setup, app shell and user admin (M1)
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 50s
ci / ts / ts (packages + web) (push) Successful in 43s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 27s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m22s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 50s
ci / ts / ts (packages + web) (push) Successful in 43s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 27s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m22s
- core: AuthSession keeps the access token in memory, refreshes it once for all parallel requests (single-flight) and retries them; refresh races between tabs are retried, reuse signs out; ApiError carries problem+json codes and field errors - web: TanStack Router with guards — guests go to /login, the bootstrap admin to /setup/admin, temporary passwords to /setup/password, admin pages by role - login, setup screens, Classic shell (top bar, role-based sidebar, empty player), settings: name, theme, language, password, devices - users admin: search, role filter, create with a one-time temporary password, reset, block, role change, delete as the policy allows; audit log for admins - ru/en strings for auth, admin and error codes; language and theme are saved in the profile Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f075863f15
commit
ab092def54
44 files changed
+4070
-203
No files matched your search
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"users": {
|
||||
"title": "Users",
|
||||
"subtitle": "Create users and moderators, manage roles, reset passwords, block accounts",
|
||||
"create": "Create user",
|
||||
"search": "Name or username",
|
||||
"all": "All",
|
||||
"col_user": "User",
|
||||
"col_role": "Role",
|
||||
"col_status": "Status",
|
||||
"col_last_login": "Last seen",
|
||||
"status_active": "Active",
|
||||
"status_blocked": "Blocked",
|
||||
"status_must_change": "Must change password",
|
||||
"never": "Never signed in",
|
||||
"empty": "Nobody found",
|
||||
"more": "Show more",
|
||||
"actions": "Actions for {{username}}",
|
||||
"reset_password": "Reset password",
|
||||
"block": "Block",
|
||||
"unblock": "Unblock",
|
||||
"make_role": "Make {{role}}",
|
||||
"delete": "Delete",
|
||||
"delete_confirm": "Delete {{username}}? Their history and likes will be lost.",
|
||||
"block_confirm": "Block {{username}}? All their sessions will end.",
|
||||
"reset_confirm": "Reset {{username}}'s password? All their sessions will end.",
|
||||
"confirm": "Confirm",
|
||||
"you": "you"
|
||||
},
|
||||
"create": {
|
||||
"title": "New user",
|
||||
"username": "Username",
|
||||
"username_hint": "Latin letters, digits, \".\", \"_\", \"-\"",
|
||||
"display_name": "Name",
|
||||
"role": "Role",
|
||||
"password_note": "The server will generate a password and show it once.",
|
||||
"submit": "Create"
|
||||
},
|
||||
"temp_password": {
|
||||
"title": "Temporary password",
|
||||
"text": "Give this password to {{username}}. It is shown only now; they will be asked to change it on sign-in.",
|
||||
"done": "Done"
|
||||
},
|
||||
"audit": {
|
||||
"title": "Audit log",
|
||||
"subtitle": "Actions of administrators and moderators",
|
||||
"col_when": "When",
|
||||
"col_who": "Who",
|
||||
"col_action": "Action",
|
||||
"col_details": "Details",
|
||||
"system": "System",
|
||||
"empty": "No entries yet",
|
||||
"more": "Show more",
|
||||
"actions": {
|
||||
"user.bootstrap_create": "Initial administrator created",
|
||||
"user.bootstrap_credentials": "Administrator credentials set",
|
||||
"user.create": "User created",
|
||||
"user.rename": "Name changed",
|
||||
"user.role_change": "Role changed",
|
||||
"user.block": "User blocked",
|
||||
"user.unblock": "User unblocked",
|
||||
"user.password_reset": "Password reset",
|
||||
"user.delete": "User deleted"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"login": {
|
||||
"title": "Sign in",
|
||||
"subtitle": "Your music from your own server",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"submit": "Sign in",
|
||||
"bootstrap_hint": "First start: sign in as the administrator. The password is set in BOOTSTRAP_ADMIN_PASSWORD or printed in the api service log."
|
||||
},
|
||||
"setup": {
|
||||
"admin_badge": "First administrator sign-in",
|
||||
"admin_title": "Change the username and password",
|
||||
"admin_text": "The server stays locked until you do: the initial administrator credentials are visible in logs and settings.",
|
||||
"password_badge": "Password reset",
|
||||
"password_title": "Set a new password",
|
||||
"password_text": "You signed in with a temporary password. Choose your own — the temporary one will stop working.",
|
||||
"new_username": "New username",
|
||||
"new_password": "New password",
|
||||
"repeat_password": "Repeat the password",
|
||||
"min_length": "At least {{min}} characters",
|
||||
"submit": "Save and continue",
|
||||
"logout": "Sign out"
|
||||
}
|
||||
}
|
||||
@@ -17,5 +17,67 @@
|
||||
"label": "Language",
|
||||
"ru": "Русский",
|
||||
"en": "English"
|
||||
},
|
||||
"nav": {
|
||||
"main": "Navigation",
|
||||
"home": "Home",
|
||||
"admin": "Admin",
|
||||
"users": "Users",
|
||||
"audit": "Audit log"
|
||||
},
|
||||
"profile": {
|
||||
"menu": "Profile menu",
|
||||
"settings": "Settings",
|
||||
"logout": "Sign out"
|
||||
},
|
||||
"roles": {
|
||||
"admin": "Administrator",
|
||||
"moderator": "Moderator",
|
||||
"user": "User"
|
||||
},
|
||||
"home": {
|
||||
"greeting": "Hi, {{name}}!",
|
||||
"wave": "My Wave",
|
||||
"wave_soon": "An endless stream tuned to your taste will appear once the server has a library."
|
||||
},
|
||||
"player": {
|
||||
"empty": "Nothing is playing"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"account": "Account",
|
||||
"display_name": "Display name",
|
||||
"save": "Save",
|
||||
"saved": "Saved",
|
||||
"appearance": "Appearance",
|
||||
"theme": "Theme",
|
||||
"theme_dark": "Dark",
|
||||
"theme_light": "Light",
|
||||
"theme_system": "System",
|
||||
"password": "Password",
|
||||
"current_password": "Current password",
|
||||
"new_password": "New password",
|
||||
"repeat_password": "Repeat the password",
|
||||
"change_password": "Change password",
|
||||
"password_changed": "Password changed. Other devices have been signed out.",
|
||||
"sessions": "Devices",
|
||||
"session_current": "This device",
|
||||
"session_last_used": "Active: {{date}}",
|
||||
"session_end": "Sign out",
|
||||
"logout_all": "Sign out everywhere"
|
||||
},
|
||||
"form": {
|
||||
"show_password": "Show password",
|
||||
"hide_password": "Hide password",
|
||||
"passwords_mismatch": "Passwords don't match",
|
||||
"required": "Fill in this field",
|
||||
"cancel": "Cancel",
|
||||
"close": "Close",
|
||||
"copy": "Copy",
|
||||
"copied": "Copied"
|
||||
},
|
||||
"loading": "Loading…",
|
||||
"route_error": {
|
||||
"reload": "Reload the page"
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,8 @@
|
||||
"internal": "Something went wrong on the server. Please try again",
|
||||
"bad_request": "Invalid request",
|
||||
"not_found": "Not found",
|
||||
"method_not_allowed": "This action is not supported"
|
||||
"method_not_allowed": "This action is not supported",
|
||||
"network": "Cannot reach the server. Check your network"
|
||||
},
|
||||
"auth": {
|
||||
"invalid_credentials": "Wrong username or password",
|
||||
|
||||
Reference in new issue
Block a user