From 13c97cfcfcd2db4cb1fcb43d23a7e2b9e25525cb Mon Sep 17 00:00:00 2001 From: DecDuck Date: Fri, 6 Feb 2026 00:12:24 +1100 Subject: [PATCH] In-app store, torrential backend, locales (#332) * feat: add store nav and fixes * fix: reduce password requirement & new task error ui * fix: client webtoken fix * fix: delta versions and dockerfile * fix: use setup platforms for filter & display * fix: setup not accounted when returning valid options * feat: tighter delta version support * feat: dl/disk size * feat: offload manifest generation to torrential * fix: bump torrential * feat: remove droplet * feat: bump torrential * feat: convert locales --- server/.gitignore | 4 +- server/.prettierignore | 2 +- server/.vscode/settings.json | 2 +- server/Dockerfile | 3 +- server/buf.gen.yaml | 5 + server/components/Auth/Simple.vue | 23 +- server/components/GameEditor/Version.vue | 25 +- server/components/ImportVersionLaunchRow.vue | 35 +- server/components/Modal/CreateCollection.vue | 17 +- server/components/Modal/DeleteCollection.vue | 2 +- server/components/Modal/DeleteNews.vue | 2 +- server/components/Modal/DeleteUser.vue | 2 +- server/components/Modal/SelectLaunch.vue | 16 +- server/components/Selector/Combox.vue | 2 +- server/components/Selector/FileExtension.vue | 14 +- server/components/Selector/Game.vue | 4 +- server/components/SourceTable.vue | 2 +- server/components/UserHeader/StoreNav.vue | 39 ++ server/dev-tools/compose.yml | 6 +- server/drop.session.sql | 1 - server/i18n/locales/de.json | 4 +- server/i18n/locales/en_pirate.json | 4 +- server/i18n/locales/en_us.json | 132 ++++++- server/i18n/locales/fr.json | 4 +- server/i18n/locales/pl.json | 4 +- server/i18n/locales/ru.json | 2 +- server/layouts/default.vue | 3 +- server/package.json | 10 +- server/pages/account/notifications.vue | 2 +- server/pages/account/security.vue | 69 ++-- server/pages/admin/index.vue | 22 +- server/pages/admin/library/[id]/import.vue | 6 +- server/pages/admin/library/import.vue | 5 +- server/pages/admin/library/index.vue | 2 +- .../pages/admin/metadata/companies/index.vue | 2 +- server/pages/admin/task/[id]/index.vue | 52 ++- server/pages/auth/mfa.vue | 11 +- server/pages/auth/mfa/index.vue | 9 +- server/pages/auth/mfa/webauthn.vue | 4 +- server/pages/auth/register.vue | 2 +- server/pages/auth/signin.vue | 4 +- server/pages/mfa/setup/successful.vue | 17 +- server/pages/mfa/setup/totp.vue | 7 +- server/pages/mfa/setup/webauthn.vue | 13 +- server/pages/store/[id]/index.vue | 31 +- server/pnpm-lock.yaml | 339 ++++++++++------ .../v1/admin/depot/torrential/manifest.get.ts | 55 --- .../v1/admin/depot/torrential/versions.get.ts | 24 -- .../api/v1/admin/game/[id]/index.get.ts | 9 +- server/server/api/v1/admin/home/index.get.ts | 8 - .../api/v1/admin/import/version/index.post.ts | 7 +- .../server/api/v1/auth/signin/simple.post.ts | 16 +- .../server/api/v1/auth/signup/simple.post.ts | 8 +- .../[id]/version/[versionid]/index.get.ts | 6 +- .../v1/client/game/{ => [id]}/versions.get.ts | 28 +- .../api/v1/client/user/webtoken.post.ts | 12 +- server/server/api/v1/collection/index.post.ts | 19 +- server/server/api/v1/games/[id]/index.get.ts | 4 +- server/server/api/v1/store/index.get.ts | 23 +- .../api/v1/user/mfa/webauthn/index.delete.ts | 49 +++ server/server/internal/auth/index.ts | 6 +- server/server/internal/clients/ca.ts | 22 +- .../server/internal/clients/event-handler.ts | 52 +-- server/server/internal/gamesize/index.ts | 294 +++++--------- server/server/internal/library/index.ts | 77 +--- .../server/internal/library/manifest/index.ts | 52 ++- .../{manifest.ts => manifest/utils.ts} | 0 server/server/internal/library/provider.ts | 11 +- .../internal/library/providers/filesystem.ts | 55 +-- .../server/internal/library/providers/flat.ts | 53 +-- server/server/internal/services/index.ts | 6 +- .../internal/services/services/torrential.ts | 78 ---- .../internal/services/torrential/README.md | 27 ++ .../services/torrential/droplet-interface.ts | 361 ++++++++++++++++++ .../internal/services/torrential/index.ts | 189 +++++++++ .../services/torrential/manifest-fetch.ts | 89 +++++ .../services/torrential/server-games.ts | 38 ++ .../internal/services/torrential/utils.ts | 15 + server/server/internal/tasks/index.ts | 7 +- server/server/plugins/04.auth-init.ts | 34 ++ server/server/plugins/06.service-spinup.ts | 2 +- server/torrential | 2 +- 82 files changed, 1737 insertions(+), 967 deletions(-) create mode 100644 server/buf.gen.yaml create mode 100644 server/components/UserHeader/StoreNav.vue delete mode 100644 server/drop.session.sql delete mode 100644 server/server/api/v1/admin/depot/torrential/manifest.get.ts delete mode 100644 server/server/api/v1/admin/depot/torrential/versions.get.ts rename server/server/api/v1/client/game/{ => [id]}/versions.get.ts (83%) create mode 100644 server/server/api/v1/user/mfa/webauthn/index.delete.ts rename server/server/internal/library/{manifest.ts => manifest/utils.ts} (100%) delete mode 100644 server/server/internal/services/services/torrential.ts create mode 100644 server/server/internal/services/torrential/README.md create mode 100644 server/server/internal/services/torrential/droplet-interface.ts create mode 100644 server/server/internal/services/torrential/index.ts create mode 100644 server/server/internal/services/torrential/manifest-fetch.ts create mode 100644 server/server/internal/services/torrential/server-games.ts create mode 100644 server/server/internal/services/torrential/utils.ts diff --git a/server/.gitignore b/server/.gitignore index 7188be16..9cbcd222 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -34,4 +34,6 @@ deploy-template/* # generated prisma client /prisma/client -/prisma/validate \ No newline at end of file +/prisma/validate + +/server/internal/proto diff --git a/server/.prettierignore b/server/.prettierignore index 51b5f44b..ed27b4da 100644 --- a/server/.prettierignore +++ b/server/.prettierignore @@ -2,6 +2,6 @@ drop-base/ # file is fully managed by pnpm, no reason to break it pnpm-lock.yaml -torrential/ +/torrential/ .data/** **/.data/** diff --git a/server/.vscode/settings.json b/server/.vscode/settings.json index 0d0624ee..0570fe39 100644 --- a/server/.vscode/settings.json +++ b/server/.vscode/settings.json @@ -33,7 +33,7 @@ "username": "drop" } ], - "typescript.experimental.useTsgo": true, + "typescript.experimental.useTsgo": false, // prioritize ArkType's "type" for autoimports "typescript.preferences.autoImportSpecifierExcludeRegexes": ["^(node:)?os$"] } diff --git a/server/Dockerfile b/server/Dockerfile index 92506f15..7b84a110 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -68,6 +68,7 @@ COPY --from=torrential-build /build/target/release/torrential /usr/bin/ ENV LIBRARY="/library" ENV DATA="/data" ENV NGINX_CONFIG="/nginx.conf" -ENV NUXT_PORT=4000 +# NGINX's port +ENV PORT=4000 CMD ["sh", "/app/startup/launch.sh"] diff --git a/server/buf.gen.yaml b/server/buf.gen.yaml new file mode 100644 index 00000000..fb9d2f35 --- /dev/null +++ b/server/buf.gen.yaml @@ -0,0 +1,5 @@ +version: v1 +plugins: + - plugin: es + out: server/internal/proto + opt: target=ts diff --git a/server/components/Auth/Simple.vue b/server/components/Auth/Simple.vue index 565aae88..5454e88d 100644 --- a/server/components/Auth/Simple.vue +++ b/server/components/Auth/Simple.vue @@ -90,7 +90,7 @@ import { startAuthentication, browserSupportsWebAuthn, } from "@simplewebauthn/browser"; -import type { FetchError } from "ofetch"; +import { FetchError } from "ofetch"; const username = ref(""); const password = ref(""); @@ -141,16 +141,19 @@ const router = useRouter(); const route = useRoute(); const { t } = useI18n(); -function signin_wrapper() { +async function signin_wrapper() { loading.value = true; - signin() - .catch((response) => { - const message = response.message || t("errors.unknown"); - error.value = message; - }) - .finally(() => { - loading.value = false; - }); + try { + await signin(); + } catch (e) { + if (e instanceof FetchError) { + error.value = e.data.message || t("errors.unknown"); + } else { + error.value = e as string; + } + } finally { + loading.value = false; + } } async function signin() { diff --git a/server/components/GameEditor/Version.vue b/server/components/GameEditor/Version.vue index cf8f36a8..28165fad 100644 --- a/server/components/GameEditor/Version.vue +++ b/server/components/GameEditor/Version.vue @@ -3,9 +3,11 @@
-

Versions

+

+ {{ $t("library.admin.version.title") }} +

- Versions versions version, versions versions. Versions. + {{ $t("library.admin.version.description") }}

@@ -36,28 +38,28 @@ scope="col" class="py-3 pr-3 pl-4 text-left text-xs font-medium tracking-wide text-gray-400 uppercase sm:pl-0" > - Name (ID) + {{ $t("library.admin.version.table.name") }} - Path + {{ $t("library.admin.version.table.path") }} - Setup Configurations + {{ $t("library.admin.version.table.setup") }} - Launch Configurations + {{ $t("library.admin.version.table.launch") }} - Edit + {{ $t("common.edit") }} @@ -100,13 +102,13 @@ v-if="version.setups.length == 0" class="text-xs uppercase font-display text-zinc-700 font-semibold" > - No setups configured. + {{ $t("library.admin.version.noSetups") }}
- Version configured as in setup-only mode. + {{ $t("library.admin.version.setupOnly") }}
    - Delete, - {{ version.displayName ?? version.versionPath }} + {{ $t("common.delete") }} - The installation directory is set as the current directory when - launching. It is not prepended to your command. + {{ $t("library.admin.launchRow.currentDirHint") }}
{{ $t("library.admin.import.version.installDir") }} @@ -124,7 +123,7 @@ - '{{ launchProcessQuery }}' + {{ launchProcessQuery }}

- {executor} - is replaced with the game's launch command for executors. + +

@@ -174,7 +183,7 @@

- Executor + {{ $t("library.admin.launchRow.executorTitle") }}

@@ -182,12 +191,12 @@ v-else class="font-bold uppercase font-display text-zinc-500 text-sm" > - No executor selected + {{ $t("library.admin.launchRow.noExecutorSelected") }}
- Select new executor + {{ + $t("library.admin.launchRow.executorSelect") + }}
- Remove + {{ $t("common.remove") }} - No extensions selected. + {{ + $t("library.admin.fileExtSelector.noSelected") + }}
- Add "{{ normalize(query) }}" + + {{ + $t("library.admin.fileExtSelector.add", [normalize(query)]) + }} - Type at least 4 characters to get results + {{ $t("library.admin.gameSelector.hint") }}
- No results + {{ $t("common.noResults") }}
- {{ $t("delete") }} + {{ $t("common.delete") }} {{ $t("chars.srComma", [source.name]) }} diff --git a/server/components/UserHeader/StoreNav.vue b/server/components/UserHeader/StoreNav.vue new file mode 100644 index 00000000..e93e3b82 --- /dev/null +++ b/server/components/UserHeader/StoreNav.vue @@ -0,0 +1,39 @@ + + diff --git a/server/dev-tools/compose.yml b/server/dev-tools/compose.yml index c2d81883..0dbe5ea4 100644 --- a/server/dev-tools/compose.yml +++ b/server/dev-tools/compose.yml @@ -1,12 +1,14 @@ services: postgres: image: postgres:14-alpine - user: "1000:1000" ports: - 5432:5432 volumes: - - ../.data/db:/var/lib/postgresql/data + - postgres-data:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=drop - POSTGRES_USER=drop - POSTGRES_DB=drop + +volumes: + postgres-data: diff --git a/server/drop.session.sql b/server/drop.session.sql deleted file mode 100644 index b12df243..00000000 --- a/server/drop.session.sql +++ /dev/null @@ -1 +0,0 @@ -DELETE FROM "Session" WHERE 1=1; diff --git a/server/i18n/locales/de.json b/server/i18n/locales/de.json index fc42fe9d..19c867af 100644 --- a/server/i18n/locales/de.json +++ b/server/i18n/locales/de.json @@ -70,7 +70,7 @@ "register": { "confirmPasswordFormat": "Muss mit oben genanntem übereinstimmen", "emailFormat": "Muss im Format nutzer{'@'}beispiel.de sein", - "passwordFormat": "Muss mindestens 14 Zeichen enthalten", + "passwordFormat": "Muss mindestens 8 Zeichen enthalten", "subheader": "Gebe unten deine Daten ein, um dein Konto zu erstellen.", "title": "Erstelle dein Drop Konto", "usernameFormat": "Muss mindestens 5 Zeichen enthalten und aus Kleinbuchstaben bestehen" @@ -101,6 +101,7 @@ "close": "Schließen", "create": "Erstellen", "date": "Datum", + "delete": "Löschen", "deleteConfirm": "Möchtest du \"{0}\" wirklich löschen?", "divider": "{'|'}", "edit": "Bearbeiten", @@ -120,7 +121,6 @@ "tags": "Tags", "today": "Heute" }, - "delete": "Löschen", "drop": { "desc": "Eine Open-Source-Plattform für die Verteilung von Spielen, die auf Geschwindigkeit, Flexibilität und Ästhetik ausgelegt ist.", "drop": "Drop" diff --git a/server/i18n/locales/en_pirate.json b/server/i18n/locales/en_pirate.json index 01f5c3e3..6b1554bd 100644 --- a/server/i18n/locales/en_pirate.json +++ b/server/i18n/locales/en_pirate.json @@ -56,7 +56,7 @@ "register": { "confirmPasswordFormat": "Must be the same as above, savvy?", "emailFormat": "Must be in the fashion of a true scallywag {'@'} example.com", - "passwordFormat": "Must be 14 or more marks, ye landlubber!", + "passwordFormat": "Must be 8 or more marks, ye landlubber!", "subheader": "Fill in yer details below to make yer mark.", "title": "Forge yer Drop Mark", "usernameFormat": "Must be 5 or more marks, and all lowercase, argh!" @@ -87,6 +87,7 @@ "close": "Shut yer trap!", "create": "Forge!", "date": "Date", + "delete": "Scuttle!", "deleteConfirm": "Are ye sure ye want to scuttle \"{0}\", ye rogue?", "divider": "{'|'}", "edit": "Amend", @@ -104,7 +105,6 @@ "tags": "Marks", "today": "Today" }, - "delete": "Scuttle!", "drop": { "desc": "An open-source game distribution platform built for speed, flexibility and beauty, like a swift brigantine!", "drop": "Drop" diff --git a/server/i18n/locales/en_us.json b/server/i18n/locales/en_us.json index ed7a803f..8163a380 100644 --- a/server/i18n/locales/en_us.json +++ b/server/i18n/locales/en_us.json @@ -9,7 +9,9 @@ "subheader": "Manage the devices authorized to access your Drop account.", "title": "Devices" }, - "home": { "title": "Home" }, + "home": { + "title": "Home" + }, "notifications": { "all": "View all {arrow}", "clear": "Clear notifications", @@ -21,7 +23,35 @@ "title": "Notifications", "unread": "Unread Notifications" }, - "security": { "title": "Security" }, + "security": { + "2fa": { + "superlevelHint": { + "signin": "Sign in {arrow}", + "success": "You have access to these protected actions.", + "title": "Sign in again to access these settings." + }, + "title": "Two-factor authentication", + "totp": { + "description": "TOTP generates one-time codes, completely offline. You can use any TOTP authenticator you like.", + "disableButton": "Disable", + "title": "TOTP" + }, + "webauthn": { + "bypassHint": "Also lets you bypass signing in with compatible devices.", + "description": "Otherwise known as passkeys. Authenticate using biometrics, a device, YubiKeys, or any compatible FIDO2 device.", + "manage": "Manage", + "modal": { + "description": "Create new keys or remove existing keys from your account.", + "new": "New key", + "tableCreated": "Created", + "tableName": "Name", + "title": "WebAuthn Keys" + }, + "title": "WebAuthn" + } + }, + "title": "Security" + }, "settings": "Settings", "title": "Account Settings", "token": { @@ -50,6 +80,31 @@ "adminTitle": "Admin Dashboard - Drop", "adminTitleTemplate": "{0} - Admin - Drop", "auth": { + "2fa": { + "backToOptions": "{arrow} Back to options", + "description": "Two-factor authentication is enabled on your account. Choose one of the options below to continue.", + "passkey": { + "createDescription": "WebAuthn, or passkeys, allow you to sign in or complete 2FA with biometrics or hardware security devices.", + "createTitle": "Create a passkey", + "description": "Use a passkey, like biometrics, a hardware security device, or other compatible device to sign in to your Drop account.", + "passkeyNameTag": "Name", + "signinButton": "Sign in with WebAuthn", + "title": "WebAuthn" + }, + "success": { + "back": "{arrow} Back to account security", + "description": "Drop has successfully created and added your 2FA method. If this is your first time configuring 2FA, your account now requires it to sign in.", + "title": "Added your 2FA method!" + }, + "title": "Two-factor authentication", + "totp": { + "createDescription": "Use your TOTP authenticator, like Google Authenticator, Aegis, or Bitwarden, to add 2FA to your Drop account.", + "createHint": "Enter the generated code to enable TOTP", + "createTitle": "Set up your authenticator", + "description": "Use a one-time code to sign in to your Drop account.", + "title": "TOTP" + } + }, "callback": { "authClient": "Authorize client?", "authorize": "Authorize", @@ -72,7 +127,7 @@ "register": { "confirmPasswordFormat": "Must be the same as above", "emailFormat": "Must be in the format user{'@'}example.com", - "passwordFormat": "Must be 14 or more characters", + "passwordFormat": "Must be 8 or more characters", "subheader": "Fill in your details below to create your account.", "title": "Create your Drop account", "usernameFormat": "Must be 5 or more characters, and lowercase" @@ -81,12 +136,14 @@ "externalProvider": "external provider", "forgot": "Forgot password?", "noAccount": "Don't have an account? Ask an admin to create one for you.", + "noAccountProtected": "We need you to sign in again for security reasons while attempting to access more sensitive actions.", "or": "OR", "pageTitle": "Sign in to Drop", "rememberMe": "Remember me", "signin": "Sign in", "signinWithExternalProvider": "Sign in with {externalProvider} {arrow}", - "title": "Sign in to your account" + "title": "Sign in to your account", + "titleProtected": "Sign in to access protected action" }, "signout": "Signout", "username": "Username" @@ -105,6 +162,7 @@ "close": "Close", "create": "Create", "date": "Date", + "delete": "Delete", "deleteConfirm": "Are you sure you want to delete \"{0}\"?", "divider": "{'|'}", "edit": "Edit", @@ -119,12 +177,12 @@ "remove": "Remove", "save": "Save", "saved": "Saved", + "select": "Select", "servers": "Servers", "srLoading": "Loading…", "tags": "Tags", "today": "Today" }, - "delete": "Delete", "drop": { "desc": "An open-source game distribution platform built for speed, flexibility and beauty.", "drop": "Drop" @@ -158,7 +216,9 @@ "invalidPassState": "Invalid password state. Please contact the server administrator.", "invalidUserOrPass": "Invalid username or password.", "inviteIdRequired": "id required in fetching invitation", - "method": { "signinDisabled": "Sign in method not enabled" }, + "method": { + "signinDisabled": "Sign in method not enabled" + }, "usernameTaken": "Username already taken." }, "backHome": "{arrow} Back to home", @@ -248,12 +308,18 @@ "aboutDrop": "About Drop", "api": "API documentation", "comparison": "Comparison", - "docs": { "client": "Client Docs", "server": "Server Docs" }, + "docs": { + "client": "Client Docs", + "server": "Server Docs" + }, "documentation": "Documentation", "findGame": "Find a Game", "footer": "Footer", "games": "Games", - "social": { "discord": "Discord", "github": "GitHub" }, + "social": { + "discord": "Discord", + "github": "GitHub" + }, "topSellers": "Top Sellers", "version": "Drop {version} {gitRef}" }, @@ -303,6 +369,10 @@ "admin": { "detectedGame": "Drop has detected you have new games to import.", "detectedVersion": "Drop has detected you have new versions of this game to import.", + "fileExtSelector": { + "add": "Add \"{0}\"", + "noSelected": "No extensions selected." + }, "game": { "addCarouselNoImages": "No images to add.", "addDescriptionNoImages": "No images to add.", @@ -323,10 +393,14 @@ "setCover": "Set as cover" }, "gameLibrary": "Game Library", + "gameSelector": { + "hint": "Type at least 4 characters to get results" + }, "import": { "bulkImportDescription": "When on this page, you won't be redirect to the import task, so you can import multiple games in succession.", "bulkImportTitle": "Bulk import mode", "import": "Import", + "importAs": "Import as", "link": "Import {arrow}", "loading": "Loading game results…", "search": "Search", @@ -344,6 +418,7 @@ "launchPlaceholder": "game.exe --args", "loadingVersion": "Loading version metadata…", "noLaunches": "No launch configurations added.", + "noNameProvided": "No name provided.", "noSetups": "No setup configurations added.", "noVersions": "No versions to import", "platform": "Version platform", @@ -357,6 +432,23 @@ }, "withoutMetadata": "Import without metadata" }, + "launchRow": { + "autosuggestHint": "Auto-suggest extensions", + "currentDirHint": "The installation directory is set as the current directory when launching. It is not prepended to your command.", + "executorHint": "{executor} is replaced with the game's launch command for emulators.", + "executorSelect": "Select new executor", + "executorTitle": "Executor", + "noExecutorSelected": "No executor selected" + }, + "launchSelector": { + "description": "Select a launch option as an executor for your new launch option.", + "noVersions": "No versions imported.", + "platformFilterHint": "Only showing launches for:", + "search": "Search for an executor", + "selectCommand": "Select a launch command", + "selectVersions": "Select a version", + "title": "Select a launch option" + }, "libraryHint": "No libraries configured.", "libraryHintDocsLink": "What does this mean? {arrow}", "metadata": { @@ -446,7 +538,17 @@ "subheader": "As you add folders to your library sources, Drop will detect it and prompt you to import it. Each game needs to be imported before you can import a version.", "title": "Libraries", "version": { - "noVersions": "You have no versions of this game available." + "description": "All versions imported for your game.", + "noSetups": "No setups configured.", + "noVersions": "You have no versions of this game available.", + "setupOnly": "Version configured as in setup-only mode.", + "table": { + "launch": "Launch Configurations", + "name": "Name (ID)", + "path": "Path", + "setup": "Setup Configurations" + }, + "title": "Versions" } }, "back": "Back to Library", @@ -595,6 +697,7 @@ "completedTasksTitle": "Completed tasks", "dailyScheduledTitle": "Daily scheduled tasks", "execute": "{arrow} Execute", + "noActions": "No actions", "noTasksRunning": "No tasks currently running", "progress": "{0}%", "runningTasksTitle": "Running tasks", @@ -628,8 +731,15 @@ }, "userHeader": { "closeSidebar": "Close sidebar", - "links": { "community": "Community", "library": "Library", "news": "News" }, - "profile": { "admin": "Admin Dashboard", "settings": "Account settings" } + "links": { + "community": "Community", + "library": "Library", + "news": "News" + }, + "profile": { + "admin": "Admin Dashboard", + "settings": "Account settings" + } }, "users": { "admin": { diff --git a/server/i18n/locales/fr.json b/server/i18n/locales/fr.json index f3d19e26..1764f52d 100644 --- a/server/i18n/locales/fr.json +++ b/server/i18n/locales/fr.json @@ -70,7 +70,7 @@ "register": { "confirmPasswordFormat": "Doit être pareil qu'au dessus", "emailFormat": "Doit être au format utilisateur{'@'}exemple.com", - "passwordFormat": "Doit être au moins 14 caractères ou plus", + "passwordFormat": "Doit être au moins 8 caractères ou plus", "subheader": "Remplissez vos coordonnées pour créer votre compte.", "title": "Créer votre compte Drop", "usernameFormat": "Doit être au moins 5 caractères et en minuscules" @@ -101,6 +101,7 @@ "close": "Fermer", "create": "Créer", "date": "Date", + "delete": "Supprimer", "deleteConfirm": "Êtes vous sûr de vouloir supprimer \"{0}\" ?", "divider": "{'|'}", "edit": "Éditer", @@ -120,7 +121,6 @@ "tags": "Étiquettes", "today": "Aujourd'hui" }, - "delete": "Supprimer", "drop": { "desc": "Une plateforme de distribution libre conçue pour être rapide, flexible et belle.", "drop": "Drop" diff --git a/server/i18n/locales/pl.json b/server/i18n/locales/pl.json index b7215ca5..b20de9bc 100644 --- a/server/i18n/locales/pl.json +++ b/server/i18n/locales/pl.json @@ -70,7 +70,7 @@ "register": { "confirmPasswordFormat": "Musi być takie samo jak powyżej", "emailFormat": "Musi być w formacie uzytkownik{'@'}example.com", - "passwordFormat": "Musi mieć conajmniej 14 znaków", + "passwordFormat": "Musi mieć conajmniej 8 znaków", "subheader": "Wpisz poniżej swoje dane, aby utworzyć swoje konto.", "title": "Stwórz swoje konto Drop", "usernameFormat": "Musi mieć co najmniej 5 znaków i małe litery" @@ -101,6 +101,7 @@ "close": "Zamknij", "create": "Utwórz", "date": "Data", + "delete": "Usuń", "deleteConfirm": "Czy jesteś pewny że chcesz usunąć \"{0}\"?", "divider": "{'|'}", "edit": "Edytuj", @@ -120,7 +121,6 @@ "tags": "Tagi", "today": "Dzisiaj" }, - "delete": "Usuń", "drop": { "desc": "Platforma typu open source do dystrybucji gier, stworzona z myślą o szybkości, elastyczności i estetyce.", "drop": "Drop" diff --git a/server/i18n/locales/ru.json b/server/i18n/locales/ru.json index c3f58151..dc1e4d2e 100644 --- a/server/i18n/locales/ru.json +++ b/server/i18n/locales/ru.json @@ -79,6 +79,7 @@ "close": "Закрыть", "create": "Создать", "date": "Дата", + "delete": "Удалить", "deleteConfirm": "Вы точно хотите удалить \"{0}\"?", "edit": "Редактировать", "friends": "Друзья", @@ -94,7 +95,6 @@ "tags": "Теги", "today": "Сегодня" }, - "delete": "Удалить", "drop": { "drop": "Уронить" }, diff --git a/server/layouts/default.vue b/server/layouts/default.vue index 5b453632..f344fd47 100644 --- a/server/layouts/default.vue +++ b/server/layouts/default.vue @@ -9,8 +9,9 @@ -
+
+
diff --git a/server/package.json b/server/package.json index eef05ecf..570331a8 100644 --- a/server/package.json +++ b/server/package.json @@ -12,7 +12,7 @@ "dev": "nuxt dev", "generate": "nuxt generate", "preview": "nuxt preview", - "postinstall": "nuxt prepare && prisma generate", + "postinstall": "nuxt prepare && prisma generate && buf generate", "typecheck": "nuxt typecheck", "lint": "pnpm run lint:eslint && pnpm run lint:prettier", "lint:eslint": "eslint .", @@ -20,8 +20,8 @@ "lint:fix": "eslint . --fix && prettier --write --list-different ." }, "dependencies": { + "@bufbuild/protobuf": "^2.11.0", "@discordapp/twemoji": "^16.0.1", - "@drop-oss/droplet": "5.3.1", "@headlessui/vue": "^1.7.23", "@heroicons/vue": "^2.1.5", "@lobomfz/prismark": "0.0.3", @@ -44,8 +44,9 @@ "fast-fuzzy": "^1.12.0", "file-type-mime": "^0.4.3", "jdenticon": "^3.3.0", - "kjua": "^0.10.0", "jose": "^6.1.3", + "jsonwebtoken": "^9.0.3", + "kjua": "^0.10.0", "luxon": "^3.6.1", "micromark": "^4.0.1", "normalize-url": "^8.0.2", @@ -68,10 +69,13 @@ "vuedraggable": "^4.1.0" }, "devDependencies": { + "@bufbuild/buf": "^1.65.0", + "@bufbuild/protoc-gen-es": "^2.11.0", "@intlify/eslint-plugin-vue-i18n": "^4.0.1", "@nuxt/eslint": "^1.3.0", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", + "@types/jsonwebtoken": "^9.0.10", "@types/luxon": "^3.6.2", "@types/node": "^22.13.16", "@types/semver": "^7.7.0", diff --git a/server/pages/account/notifications.vue b/server/pages/account/notifications.vue index 04b83f13..3c25592a 100644 --- a/server/pages/account/notifications.vue +++ b/server/pages/account/notifications.vue @@ -85,7 +85,7 @@ @click="deleteNotification(notification.id)" > - {{ $t("delete") }} + {{ $t("common.delete") }}
diff --git a/server/pages/account/security.vue b/server/pages/account/security.vue index 8d358c4a..83b64ece 100644 --- a/server/pages/account/security.vue +++ b/server/pages/account/security.vue @@ -13,13 +13,21 @@

- Sign in again to access these settings. - {{ " " }} + {{ $t("account.security.2fa.superlevelHint.title") }} Sign in → + + + +

@@ -31,7 +39,7 @@

- You have access to these protected actions. + {{ $t("account.security.2fa.superlevelHint.success") }}

@@ -40,7 +48,7 @@

- Two-factor authentication + {{ $t("account.security.2fa.title") }}

@@ -67,15 +75,16 @@ class="absolute inset-0" aria-hidden="true" > - TOTP + {{ $t("account.security.2fa.totp.title") }}

- TOTP generates one-time codes, completely offline. You can use any - TOTP authenticator you like. + {{ $t("account.security.2fa.totp.description") }}

- Disable + {{ + $t("account.security.2fa.totp.disableButton") + }}
-

WebAuthn

+

+ {{ $t("account.security.2fa.webauthn.title") }} +

- Otherwise known as passkeys. Authenticate using biometrics, a - device, YubiKeys, or any compatible FIDO2 device. + {{ $t("account.security.2fa.webauthn.description") }}

- Also lets you bypass signing in with compatible devices. + {{ $t("account.security.2fa.webauthn.bypassHint") }}

Manage{{ $t("account.security.2fa.webauthn.manage") }} @@ -130,9 +140,11 @@