From a98f86f31fd8ce9c7b55ed26b6f5068dfe33c8e1 Mon Sep 17 00:00:00 2001 From: Joseph Micheli Date: Mon, 29 Apr 2024 18:25:41 -0500 Subject: [PATCH 1/3] =?UTF-8?q?=E2=9C=85=20Fix=20stump=5Fconfig=20tests=20?= =?UTF-8?q?(#331)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 10 ++ core/Cargo.toml | 1 + core/src/config/stump_config.rs | 151 ++++++++++-------- .../src/notifier/discord_client.rs | 1 + .../src/notifier/telegram_client.rs | 2 + 5 files changed, 97 insertions(+), 68 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 381aade81..b694d7675 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6423,6 +6423,7 @@ dependencies = [ "serde-xml-rs", "serde_json", "specta", + "temp-env", "tempfile", "thiserror", "tokio", @@ -6835,6 +6836,15 @@ dependencies = [ "windows 0.39.0", ] +[[package]] +name = "temp-env" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96374855068f47402c3121c6eed88d29cb1de8f3ab27090e273e420bdabcf050" +dependencies = [ + "parking_lot 0.12.1", +] + [[package]] name = "tempdir" version = "0.3.7" diff --git a/core/Cargo.toml b/core/Cargo.toml index 53570015e..6e5532327 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -52,6 +52,7 @@ regex = "1.10.4" alphanumeric-sort = "1.5.3" [dev-dependencies] +temp-env = "0.3.6" tempfile = { workspace = true } criterion = { version = "0.5.1", features = ["html_reports", "async_tokio"] } diff --git a/core/src/config/stump_config.rs b/core/src/config/stump_config.rs index 26f084319..ce9607f89 100644 --- a/core/src/config/stump_config.rs +++ b/core/src/config/stump_config.rs @@ -525,42 +525,49 @@ mod tests { #[test] fn test_getting_config_from_environment() { - // Set environment variables - env::set_var(PROFILE_KEY, "release"); - env::set_var(PORT_KEY, "1337"); - env::set_var(VERBOSITY_KEY, "3"); - env::set_var(DB_PATH_KEY, "not_a_real_path"); - env::set_var(CLIENT_KEY, "not_a_real_dir"); - env::set_var(CONFIG_DIR_KEY, "also_not_a_real_dir"); - env::set_var(DISABLE_SWAGGER_KEY, "true"); - env::set_var(HASH_COST_KEY, "24"); - env::set_var(SESSION_TTL_KEY, (3600 * 24).to_string()); - env::set_var(SESSION_EXPIRY_INTERVAL_KEY, (60 * 60 * 8).to_string()); - - // Create a new StumpConfig and load values from the environment. - let config = StumpConfig::new("not_a_dir".to_string()) - .with_environment() - .unwrap(); - - // Confirm values are as expected - assert_eq!( - config, - StumpConfig { - profile: "release".to_string(), - port: 1337, - verbosity: 3, - pretty_logs: true, - db_path: Some("not_a_real_path".to_string()), - client_dir: "not_a_real_dir".to_string(), - config_dir: "also_not_a_real_dir".to_string(), - allowed_origins: vec![], - pdfium_path: None, - disable_swagger: true, - password_hash_cost: 24, - session_ttl: 3600 * 24, - expired_session_cleanup_interval: 60 * 60 * 8, - scanner_chunk_size: DEFAULT_SCANNER_CHUNK_SIZE, - } + temp_env::with_vars( + [ + (PROFILE_KEY, Some("release")), + (PORT_KEY, Some("1337")), + (VERBOSITY_KEY, Some("2")), + (DB_PATH_KEY, Some("not_a_real_path")), + (CLIENT_KEY, Some("not_a_real_dir")), + (CONFIG_DIR_KEY, Some("also_not_a_real_dir")), + (DISABLE_SWAGGER_KEY, Some("true")), + (HASH_COST_KEY, Some("24")), + (SESSION_TTL_KEY, Some(&(3600 * 24).to_string())), + ( + SESSION_EXPIRY_INTERVAL_KEY, + Some(&(60 * 60 * 8).to_string()), + ), + ], + || { + // Create a new StumpConfig and load values from the environment. + let config = StumpConfig::new("not_a_dir".to_string()) + .with_environment() + .unwrap(); + + // Confirm values are as expected + assert_eq!( + config, + StumpConfig { + profile: "release".to_string(), + port: 1337, + verbosity: 2, + pretty_logs: true, + db_path: Some("not_a_real_path".to_string()), + client_dir: "not_a_real_dir".to_string(), + config_dir: "also_not_a_real_dir".to_string(), + allowed_origins: vec![], + pdfium_path: None, + disable_swagger: true, + password_hash_cost: 24, + session_ttl: 3600 * 24, + expired_session_cleanup_interval: 60 * 60 * 8, + scanner_chunk_size: DEFAULT_SCANNER_CHUNK_SIZE, + } + ); + }, ); } @@ -670,38 +677,46 @@ mod tests { #[test] fn test_simulate_first_boot() { - env::set_var(PORT_KEY, "1337"); - env::set_var(VERBOSITY_KEY, "2"); - env::set_var(DISABLE_SWAGGER_KEY, "true"); - env::set_var(HASH_COST_KEY, "1"); - - let tempdir = tempfile::tempdir().expect("Failed to create temporary directory"); - // Now we can create a StumpConfig rooted at the temporary directory - let config_dir = tempdir.path().to_string_lossy().to_string(); - let generated = StumpConfig::new(config_dir.clone()) - .with_config_file() - .expect("Failed to generate StumpConfig from Stump.toml") - .with_environment() - .expect("Failed to generate StumpConfig from environment"); - - let expected = StumpConfig { - profile: "debug".to_string(), - port: 1337, - verbosity: 2, - pretty_logs: true, - db_path: None, - client_dir: "./dist".to_string(), - config_dir, - allowed_origins: vec![], - pdfium_path: None, - disable_swagger: true, - password_hash_cost: 1, - session_ttl: DEFAULT_SESSION_TTL, - expired_session_cleanup_interval: DEFAULT_SESSION_EXPIRY_CLEANUP_INTERVAL, - scanner_chunk_size: DEFAULT_SCANNER_CHUNK_SIZE, - }; - - assert_eq!(generated, expected); + temp_env::with_vars( + [ + (PORT_KEY, Some("1337")), + (VERBOSITY_KEY, Some("2")), + (DISABLE_SWAGGER_KEY, Some("true")), + (HASH_COST_KEY, Some("1")), + ], + || { + let tempdir = + tempfile::tempdir().expect("Failed to create temporary directory"); + // Now we can create a StumpConfig rooted at the temporary directory + let config_dir = tempdir.path().to_string_lossy().to_string(); + let generated = StumpConfig::new(config_dir.clone()) + .with_config_file() + .expect("Failed to generate StumpConfig from Stump.toml") + .with_environment() + .expect("Failed to generate StumpConfig from environment"); + + assert_eq!( + generated, + StumpConfig { + profile: "debug".to_string(), + port: 1337, + verbosity: 2, + pretty_logs: true, + db_path: None, + client_dir: "./dist".to_string(), + config_dir, + allowed_origins: vec![], + pdfium_path: None, + disable_swagger: true, + password_hash_cost: 1, + session_ttl: DEFAULT_SESSION_TTL, + expired_session_cleanup_interval: + DEFAULT_SESSION_EXPIRY_CLEANUP_INTERVAL, + scanner_chunk_size: DEFAULT_SCANNER_CHUNK_SIZE, + } + ); + }, + ); } fn get_mock_config_file() -> String { diff --git a/crates/integrations/src/notifier/discord_client.rs b/crates/integrations/src/notifier/discord_client.rs index 4bb5013e2..a98b9675a 100644 --- a/crates/integrations/src/notifier/discord_client.rs +++ b/crates/integrations/src/notifier/discord_client.rs @@ -76,6 +76,7 @@ mod tests { DiscordClient::new(webhook_url) } + #[ignore = "No token"] #[tokio::test] async fn test_send_message() { let client = get_debug_client(); diff --git a/crates/integrations/src/notifier/telegram_client.rs b/crates/integrations/src/notifier/telegram_client.rs index 363a6f205..8f67cc65d 100644 --- a/crates/integrations/src/notifier/telegram_client.rs +++ b/crates/integrations/src/notifier/telegram_client.rs @@ -61,6 +61,8 @@ mod tests { let chat_id = std::env::var("DUMMY_TG_CHAT_ID").expect("Failed to load chat ID"); TelegramClient::new(token, chat_id) } + + #[ignore = "No token"] #[tokio::test] async fn test_send_message() { let client = get_debug_client(); From bf82e01cc69b7749dd17152905f875c302d45ef9 Mon Sep 17 00:00:00 2001 From: Aaron Leopold <36278431+aaronleopold@users.noreply.github.com> Date: Wed, 1 May 2024 06:23:28 -0700 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20(#33?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/i18n/src/locales/fr.json | 180 +++++++++++++++--------------- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/packages/i18n/src/locales/fr.json b/packages/i18n/src/locales/fr.json index 236279972..de5b9193d 100644 --- a/packages/i18n/src/locales/fr.json +++ b/packages/i18n/src/locales/fr.json @@ -1,9 +1,9 @@ { "underConstruction": { - "heading": "This is awkward", - "message": "You've stumbled upon a page that's still being developed. I'd love to show it to you, but it isn't quite ready yet.", - "homeLink": "Go Home", - "githubLink": "View the GitHub issue" + "heading": "C'est embarrassant", + "message": "Vous êtes tombé sur une page qui est encore en cours de développement. J'aimerais vous la montrer, mais elle n'est pas encore tout à fait prête.", + "homeLink": "Aller à l'accueil", + "githubLink": "Voir le ticket GitHub" }, "authScene": { "claimHeading": "Initialisez votre serveur", @@ -53,63 +53,63 @@ }, "createBookClubScene": { "heading": "Créer un nouveau Club de Lecture", - "subtitle": "You can create a private book club a select few, or make it public for anyone on the server to join", + "subtitle": "Vous pouvez créer un club de lecture privé en sélectionnant des membres, ou le rendre public pour tous sur le serveur", "form": { "name": { - "label": "Name", - "placeholder": "My book club", - "description": "The name of your book club" + "label": "Nom", + "placeholder": "Mon club de lecture", + "description": "Le nom de votre club de lecture" }, "description": { "label": "Description", - "placeholder": "An 'Our Flag Means Death' fan club. We read pirate fiction to our hearts content", - "description": "An optional, short description of your book club" + "placeholder": "Un club de fans sur \"Notre Drapeau signifie la Mort\". Nous lisons des fictions sur la piraterie au gré de nos envies", + "description": "Une courte description facultative de votre club de lecture" }, "is_private": { - "label": "Private club", - "description": "If enabled, only users you invite will be able to join your book club" + "label": "Club privé", + "description": "Si activée, seuls les utilisateurs que vous invitez pourront rejoindre votre club de lecture" }, "member_role_spec": { - "heading": "Custom role mapping", + "heading": "Mappage des rôles personnalisé", "subtitle": [ "You can create custom names for the roles in your book club. For example, you could rename the 'Member' role to 'Crewmate', or 'Creator' to 'Captain'. If you don't want to use custom names, you can leave these fields blank and the default names will be used instead. For more information about roles, refer to the", "documentation" ], "member": { - "label": "Member", - "placeholder": "Member", - "description": "The name of the default role for your book club" + "label": "Membre", + "placeholder": "Membre", + "description": "Le nom du rôle par défaut pour votre club de lecture" }, "moderator": { - "label": "Moderator", - "placeholder": "Moderator", - "description": "The name of the moderator role for your book club" + "label": "Modérateur", + "placeholder": "Modérateur", + "description": "Le nom du rôle de modérateur pour votre club de lecture" }, "admin": { - "label": "Admin", - "placeholder": "Admin", - "description": "The name of the admin role for your book club" + "label": "Administrateur", + "placeholder": "Administrateur", + "description": "Le nom du rôle d'administrateur de votre club de lecture" }, "creator": { - "label": "Creator", - "placeholder": "Creator", - "description": "The name of the creator role for your book club. This is you!" + "label": "Créateur", + "placeholder": "Créateur", + "description": "Le nom du rôle de créateur de votre club de lecture. C'est vous !" } }, "creator_preferences": { "heading": "Your membership preferences", "subtitle": "Some preferences for your membership in the book club. These can be changed at any time from the book club settings page", "creator_display_name": { - "label": "Display Name", + "label": "Nom affiché", "placeholder": "oromei", - "description": "An optional display name for your membership in the book club. If set, this takes precedence over your username" + "description": "Un nom affiché facultatif pour votre adhésion au club de lecture. Si défini, celui-ci prend la priorité sur votre nom d'utilisateur" }, "creator_hide_progress": { - "label": "Hide Progress", - "description": "If enabled, your read progress will be hidden from other members of the book club" + "label": "Masquer la progression", + "description": "Si activée, votre progression de lecture sera cachée aux autres membres du club" } }, - "submit": "Create Book Club" + "submit": "Créer un Club de Lecture" } }, "createLibraryScene": { @@ -281,7 +281,7 @@ "settingsScene": { "navigation": { "general": "Général", - "logs": "Logs", + "logs": "Journaux", "server": "Serveur", "jobs": "Tâches et Configuration", "users": "Gestion des Utilisateurs", @@ -289,26 +289,26 @@ }, "sidebar": { "application": { - "account": "Account", + "account": "Compte", "appearance": "Apparence", - "reader": "Reader", + "reader": "Lecteur", "desktop": "Bureau", "label": "Application" }, "server": { - "general": "General", - "logs": "Logs", - "users": "Users", - "jobs": "Jobs", - "access": "Access", + "general": "Général", + "logs": "Journaux", + "users": "Utilisateurs", + "jobs": "Tâches", + "access": "Accéder", "notifications": "Notifications", - "label": "Server" + "label": "Serveur" } }, "app/account": { - "helmet": "Account settings", - "title": "Account settings", - "description": "Settings related to your account", + "helmet": "Paramètres du compte", + "title": "Paramètres du compte", + "description": "Paramètres liés à votre compte", "sections": { "account": { "validation": { @@ -375,50 +375,50 @@ } }, "navigationArrangement": { - "label": "Navigation arrangement", + "label": "Disposition de la navigation", "description": { - "sidebar": "Arrange and customize the navigation items in the sidebar", - "topbar": "Arrange and customize the navigation items in the topbar" + "sidebar": "Organiser et personnaliser les éléments de navigation dans la barre latérale", + "topbar": "Organiser et personnaliser les éléments de navigation dans la barre supérieure" }, - "isLocked": "Arrangement is locked", - "lock": "Lock arrangement", - "unlock": "Unlock arrangement", + "isLocked": "L'organisation est verrouillée", + "lock": "Verrouiller la disposition", + "unlock": "Déverrouiller la disposition", "options": { - "Home": "Home", - "Explore": "Explore", - "Libraries": "Libraries", - "BookClubs": "Book clubs", - "SmartLists": "Smart lists" + "Home": "Accueil", + "Explore": "Explorer", + "Libraries": "Bibliothèques", + "BookClubs": "Clubs de lecture", + "SmartLists": "Listes intelligentes" }, "entityOptions": { "createAction": { - "label": "Show create action", - "help": "Show the create action in the navigation" + "label": "Afficher l'action Créer", + "help": "Afficher l'action Créer dans la navigation" }, "linkToAll": { - "label": "See all link", - "help": "A link to a page dedicated to viewing all items of this type" + "label": "Voir tous les liens", + "help": "Un lien vers une page dédiée à la visualisation de tous les éléments de ce type" } } } } }, "app/reader": { - "helmet": "Reader settings", - "title": "Reader settings", - "description": "Default options for the Stump readers. These are bound to your current device only", + "helmet": "Paramètres du lecteur", + "title": "Paramètres du lecteur", + "description": "Options par défaut pour les lecteurs. Elles sont liées à votre appareil actuel uniquement", "sections": { "imageBasedBooks": { - "label": "Image-based books", - "description": "Comic books, manga, and other image-based books", + "label": "Livres à base d'images", + "description": "Bandes dessinées, mangas, et autres livres illustrés", "sections": { "preloadAheadCount": { - "label": "Preload ahead count", - "description": "The number of pages to preload ahead of the current page" + "label": "Nombre de préchargements avant la page actuelle", + "description": "Le nombre de pages à précharger avant la page actuelle" }, "preloadBehindCount": { - "label": "Preload behind count", - "description": "The number of pages to preload behind the current page" + "label": "Nombre de préchargements après la page actuelle", + "description": "Le nombre de pages à précharger après la page actuelle" } } } @@ -445,41 +445,41 @@ "message": "Votre serveur n'est pas à jour. Veuillez le mettre à jour vers la dernière version !" }, "serverInfo": { - "title": "Server information", - "description": "Basic details about your Stump server instance", + "title": "Informations du serveur", + "description": "Détails de base sur l'instance de votre serveur Stump", "build": { - "label": "Build", - "description": "Details about the version and build", + "label": "Version", + "description": "Détails à propos de la version", "version": { "semver": "Version", - "commitHash": "Exact commit", - "date": "Build date" + "commitHash": "Commit exact", + "date": "Date de compilation" } } } } }, "server/logs": { - "helmet": "Logs", - "title": "Logs", - "description": "The logs generated by your Stump server instance", + "helmet": "Journaux", + "title": "Journaux", + "description": "Les journaux générés par votre instance de serveur Stump", "sections": { "persistedLogs": { - "title": "Persisted logs", - "description": "These logs have been manually persisted to the database, typically associated with a specific job or event", + "title": "Journaux persistants", + "description": "Ces journaux ont été enregistrés manuellement dans la base de données et sont généralement associés à un travail ou à un événement spécifique", "table": { "columns": { - "level": "Level", + "level": "Niveau", "message": "Message", - "timestamp": "Timestamp" + "timestamp": "Horodatage" }, - "emptyHeading": "No logs to display", - "emptySubtitle": "Your server is either very healthy or very unhealthy" + "emptyHeading": "Aucun journal à afficher", + "emptySubtitle": "Votre serveur est soit très sain, soit en très mauvais état" } }, "liveLogs": { - "title": "Live logs feed", - "description": "Streamed directly from your Stump server instance in real-time" + "title": "Flux des journaux en direct", + "description": "Diffusion directe depuis votre instance de serveur Stump en temps réel" } } }, @@ -574,8 +574,8 @@ "description": "Permet à l'utilisateur d'accéder à l'explorateur de fichiers des bibliothèques.\nLa restriction de contenu n'est pas prise en charge lorsque cette fonctionnalité est accordée" }, "download": { - "label": "Download files", - "description": "Allows the user to download files from the server" + "label": "Télécharger les fichiers", + "description": "Permet à l'utilisateur de télécharger des fichiers à partir du serveur" }, "upload": { "label": "Envoyer des fichiers", @@ -615,8 +615,8 @@ "user": { "label": "Gestion des Utilisateurs", "read": { - "label": "Read users", - "description": "Allows the user to query other users on the server. This is required for some other features, e.g. excluding users from accessing a library" + "label": "Lire des utilisateurs", + "description": "Permet à l'utilisateur de rechercher d'autres utilisateurs sur le serveur. Cette fonction est nécessaire pour certaines fonctionnalités, par exemple pour réduire l'accès à une bibliothèque pour des utilisateurs" }, "manage": { "label": "Gérer les utilisateurs", @@ -685,7 +685,7 @@ "smartlists": "Listes intelligentes", "noSmartlists": "Aucune liste intelligente", "createSmartlist": "Créer une liste intelligente", - "seeAll": "See all" + "seeAll": "Afficher tout" }, "libraryOptions": { "scanLibrary": "Scanner", @@ -752,7 +752,7 @@ "saveChanges": "Enregistrer les modifications", "create": "Créer", "edit": "Éditer", - "unimplemented": "This functionality is not yet implemented! Check back later", - "limitedFunctionality": "This is not yet fully implemented and is lacking some features. Check back later" + "unimplemented": "Cette fonctionnalité n'est pas encore implémentée ! Revenez plus tard", + "limitedFunctionality": "Ceci n'est pas encore totalement implémenté et manque de certaines fonctionnalités. Revenez plus tard" } } \ No newline at end of file From 316cd091b8c829c4acf4df00af4e47f86f428db2 Mon Sep 17 00:00:00 2001 From: Aaron Leopold <36278431+aaronleopold@users.noreply.github.com> Date: Wed, 1 May 2024 16:52:27 -0700 Subject: [PATCH 3/3] :bug: Fix `check-for-update` false positive (#333) * :bug: Fix `check-for-update` false positive Fixes #320 * :bug: Fix shrinking sidebar buttons Just added `shrink-0` to ensure the buttons don't shrink on certain viewports --- apps/server/src/routers/api/v1/mod.rs | 6 +++++- .../src/components/navigation/sidebar/SideBarButtonLink.tsx | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/server/src/routers/api/v1/mod.rs b/apps/server/src/routers/api/v1/mod.rs index 8712b611e..46be6710a 100644 --- a/apps/server/src/routers/api/v1/mod.rs +++ b/apps/server/src/routers/api/v1/mod.rs @@ -137,11 +137,15 @@ async fn check_for_updates() -> APIResult> { if github_response.status().is_success() { let github_json: serde_json::Value = github_response.json().await?; - let latest_semver = github_json["tag_name"].as_str().ok_or_else(|| { + let mut latest_semver = github_json["tag_name"].as_str().ok_or_else(|| { APIError::InternalServerError( "Failed to parse latest release tag name".to_string(), ) })?; + if latest_semver.starts_with('v') && latest_semver.len() > 1 { + latest_semver = &latest_semver[1..]; + } + let has_update_available = latest_semver != current_semver; Ok(Json(UpdateCheck { diff --git a/packages/browser/src/components/navigation/sidebar/SideBarButtonLink.tsx b/packages/browser/src/components/navigation/sidebar/SideBarButtonLink.tsx index eb2e7aa88..115c9b75a 100644 --- a/packages/browser/src/components/navigation/sidebar/SideBarButtonLink.tsx +++ b/packages/browser/src/components/navigation/sidebar/SideBarButtonLink.tsx @@ -23,7 +23,7 @@ export default function SideBarButtonLink({ return (