implement secrets read from env vars
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
# will have compiled files and executables
|
||||
debug/
|
||||
target/
|
||||
.env
|
||||
successful_submissions.tsv
|
||||
|
||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||
|
||||
@@ -11,6 +11,7 @@ leptos = { version = "0.8.0" }
|
||||
leptos_router = { version = "0.8.0" }
|
||||
axum = { version = "0.8.0", optional = true }
|
||||
console_error_panic_hook = { version = "0.1", optional = true }
|
||||
dotenvy = { version = "0.15", optional = true }
|
||||
leptos_axum = { version = "0.8.0", optional = true }
|
||||
leptos_meta = { version = "0.8.0" }
|
||||
tokio = { version = "1", features = ["rt-multi-thread"], optional = true }
|
||||
@@ -24,6 +25,7 @@ hydrate = [
|
||||
]
|
||||
ssr = [
|
||||
"dep:axum",
|
||||
"dep:dotenvy",
|
||||
"dep:tokio",
|
||||
"dep:leptos_axum",
|
||||
"leptos/ssr",
|
||||
|
||||
@@ -36,6 +36,18 @@ Additionally, Cargo.toml may need updating as new versions of the dependencies a
|
||||
cargo leptos watch
|
||||
```
|
||||
|
||||
Copy `dev.env` to `.env`, then replace the placeholder with a unique secret
|
||||
before starting the server. The `.env` file is loaded automatically at startup
|
||||
and is ignored by Git. `DEV_SECRET_KEY` authorizes server status changes and
|
||||
submission-history access:
|
||||
|
||||
```powershell
|
||||
Copy-Item dev.env .env
|
||||
```
|
||||
|
||||
You can also provide `DEV_SECRET_KEY` through the process environment. Do not
|
||||
commit secrets or expose them in client-side code.
|
||||
|
||||
## Installing Additional Tools
|
||||
|
||||
By default, `cargo-leptos` uses `nightly` Rust, `cargo-generate`, and `sass`. If you run into any trouble, you may need to install one or more of these tools.
|
||||
|
||||
@@ -87,7 +87,7 @@ type HistoryViewEntry = (String, String, bool, String, String);
|
||||
async fn get_submission_history(
|
||||
secret_key: String,
|
||||
) -> Result<Vec<HistoryViewEntry>, ServerFnError> {
|
||||
if !crate::manage::valid_status_secret_key(&secret_key) {
|
||||
if !crate::secrets::validate_dev_secret_key(&secret_key)? {
|
||||
return Err(ServerFnError::new("Invalid secret key"));
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ fn persist_submission(submission: &SuccessfulSubmission) -> Result<(), ServerFnE
|
||||
|
||||
#[server]
|
||||
async fn clear_submission_history(secret_key: String) -> Result<(), ServerFnError> {
|
||||
if !crate::manage::valid_status_secret_key(&secret_key) {
|
||||
if !crate::secrets::validate_dev_secret_key(&secret_key)? {
|
||||
return Err(ServerFnError::new("Invalid secret key"));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
pub mod app;
|
||||
pub mod codes;
|
||||
pub mod manage;
|
||||
#[cfg(feature = "ssr")]
|
||||
pub mod secrets;
|
||||
|
||||
#[cfg(feature = "hydrate")]
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
|
||||
+5
-4
@@ -1,12 +1,13 @@
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
use axum::Router;
|
||||
use code_submission::app::*;
|
||||
use leptos::logging::log;
|
||||
use leptos::prelude::*;
|
||||
use leptos_axum::{generate_route_list, LeptosRoutes};
|
||||
use code_submission::app::*;
|
||||
|
||||
code_submission::secrets::load_dotenv().expect("Unable to load .env configuration");
|
||||
|
||||
let conf = get_configuration(None).unwrap();
|
||||
let addr = conf.leptos_options.site_addr;
|
||||
@@ -30,8 +31,8 @@ async fn main() {
|
||||
listener,
|
||||
app.into_make_service_with_connect_info::<std::net::SocketAddr>(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "ssr"))]
|
||||
|
||||
+1
-9
@@ -12,14 +12,6 @@ pub(crate) fn server_live_state() -> bool {
|
||||
SERVER_LIVE.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
const STATUS_SECRET_KEY: &str = "password";
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub(crate) fn valid_status_secret_key(secret_key: &str) -> bool {
|
||||
secret_key == STATUS_SECRET_KEY
|
||||
}
|
||||
|
||||
#[server]
|
||||
async fn get_live_state() -> Result<bool, ServerFnError> {
|
||||
Ok(server_live_state())
|
||||
@@ -27,7 +19,7 @@ async fn get_live_state() -> Result<bool, ServerFnError> {
|
||||
|
||||
#[server]
|
||||
async fn set_live_state(live: bool, secret_key: String) -> Result<(), ServerFnError> {
|
||||
if !valid_status_secret_key(&secret_key) {
|
||||
if !crate::secrets::validate_dev_secret_key(&secret_key)? {
|
||||
return Err(ServerFnError::ServerError("Invalid secret key".to_string()));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
use leptos::prelude::ServerFnError;
|
||||
use std::io::ErrorKind;
|
||||
|
||||
pub(crate) const DEV_SECRET_KEY: &str = "DEV_SECRET_KEY";
|
||||
|
||||
pub fn load_dotenv() -> Result<(), String> {
|
||||
match dotenvy::dotenv() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(dotenvy::Error::Io(error)) if error.kind() == ErrorKind::NotFound => Ok(()),
|
||||
Err(error) => Err(format!("Unable to load .env file: {error}")),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn validate_dev_secret_key(provided_key: &str) -> Result<bool, ServerFnError> {
|
||||
let expected_key = std::env::var(DEV_SECRET_KEY).map_err(|_| {
|
||||
ServerFnError::new(format!(
|
||||
"Required server secret {DEV_SECRET_KEY} is not configured"
|
||||
))
|
||||
})?;
|
||||
|
||||
Ok(provided_key == expected_key)
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
1791318883 152713800 127.0.0.1 false code1
|
||||
1791318908 161513000 127.0.0.1 true code1
|
||||
|
Reference in New Issue
Block a user