Demo flag
This commit is contained in:
parent
c52295fe21
commit
85224ef1f8
18
README.md
18
README.md
@ -26,7 +26,11 @@ This project is packaged with Nix flakes. To install and run it:
|
|||||||
|
|
||||||
Or run it directly:
|
Or run it directly:
|
||||||
```bash
|
```bash
|
||||||
|
# Run with a persistent database
|
||||||
nix run git+https://code.everydayimshuflin.com/greg/rss-reader -- -d /path/to/database.sqlite
|
nix run git+https://code.everydayimshuflin.com/greg/rss-reader -- -d /path/to/database.sqlite
|
||||||
|
|
||||||
|
# Or try it out in demo mode (uses in-memory database)
|
||||||
|
nix run git+https://code.everydayimshuflin.com/greg/rss-reader -- --demo
|
||||||
```
|
```
|
||||||
|
|
||||||
### Development
|
### Development
|
||||||
@ -46,7 +50,19 @@ To set up a development environment:
|
|||||||
|
|
||||||
3. Run the application:
|
3. Run the application:
|
||||||
```bash
|
```bash
|
||||||
|
# Run with a persistent database
|
||||||
cargo run -- -d rss-reader.db
|
cargo run -- -d rss-reader.db
|
||||||
|
|
||||||
|
# Or try it out in demo mode (uses in-memory database)
|
||||||
|
cargo run -- --demo
|
||||||
```
|
```
|
||||||
|
|
||||||
The application will be available at `http://localhost:8000`. On first run, you'll be prompted to create an admin user.
|
The application will be available at `http://localhost:8000`.
|
||||||
|
|
||||||
|
### Demo Mode
|
||||||
|
|
||||||
|
When running in demo mode (using the `--demo` flag), the application will:
|
||||||
|
- Use an in-memory SQLite database that is cleared when the application stops
|
||||||
|
- Create two pre-configured users:
|
||||||
|
- Admin user: username `admin`, password `admin`
|
||||||
|
- Regular user: username `demo`, password `demo`
|
46
src/demo.rs
Normal file
46
src/demo.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
use chrono;
|
||||||
|
use sqlx;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
pub async fn setup_demo_data(pool: &sqlx::SqlitePool) {
|
||||||
|
// Create admin user
|
||||||
|
let admin_id = Uuid::new_v4().to_string();
|
||||||
|
let admin_hash = bcrypt::hash("admin", bcrypt::DEFAULT_COST).unwrap();
|
||||||
|
let now = chrono::Utc::now().to_rfc3339();
|
||||||
|
|
||||||
|
sqlx::query(
|
||||||
|
"INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin)
|
||||||
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||||
|
)
|
||||||
|
.bind(&admin_id)
|
||||||
|
.bind("admin")
|
||||||
|
.bind(&admin_hash)
|
||||||
|
.bind(Option::<String>::None)
|
||||||
|
.bind(Option::<String>::None)
|
||||||
|
.bind(&now)
|
||||||
|
.bind(true)
|
||||||
|
.execute(pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to create admin user");
|
||||||
|
|
||||||
|
// Create demo user
|
||||||
|
let demo_id = Uuid::new_v4().to_string();
|
||||||
|
let demo_hash = bcrypt::hash("demo", bcrypt::DEFAULT_COST).unwrap();
|
||||||
|
|
||||||
|
sqlx::query(
|
||||||
|
"INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin)
|
||||||
|
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)",
|
||||||
|
)
|
||||||
|
.bind(&demo_id)
|
||||||
|
.bind("demo")
|
||||||
|
.bind(&demo_hash)
|
||||||
|
.bind(Option::<String>::None)
|
||||||
|
.bind(Option::<String>::None)
|
||||||
|
.bind(&now)
|
||||||
|
.bind(false)
|
||||||
|
.execute(pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to create demo user");
|
||||||
|
|
||||||
|
println!("Successfully set up demo data");
|
||||||
|
}
|
32
src/main.rs
32
src/main.rs
@ -3,6 +3,7 @@ extern crate rocket;
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
|
mod demo;
|
||||||
mod feed_utils;
|
mod feed_utils;
|
||||||
mod feeds;
|
mod feeds;
|
||||||
mod poll;
|
mod poll;
|
||||||
@ -20,7 +21,11 @@ use user::AuthenticatedUser;
|
|||||||
struct Args {
|
struct Args {
|
||||||
/// Path to the SQLite database file
|
/// Path to the SQLite database file
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
database: String,
|
database: Option<String>,
|
||||||
|
|
||||||
|
/// Run in demo mode with an in-memory database
|
||||||
|
#[arg(long)]
|
||||||
|
demo: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Database)]
|
#[derive(Database)]
|
||||||
@ -58,15 +63,21 @@ fn login() -> Template {
|
|||||||
fn rocket() -> _ {
|
fn rocket() -> _ {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
|
||||||
let db_url = format!("sqlite:{}", args.database);
|
let db_url = if args.demo {
|
||||||
|
"sqlite::memory:".to_string()
|
||||||
|
} else {
|
||||||
|
let database = args
|
||||||
|
.database
|
||||||
|
.expect("Database path is required when not in demo mode");
|
||||||
// Check if database file exists, create it if it doesn't
|
// Check if database file exists, create it if it doesn't
|
||||||
if !std::path::Path::new(&args.database).exists() {
|
if !std::path::Path::new(&database).exists() {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
File::create(&args.database).expect("Failed to create database file");
|
File::create(&database).expect("Failed to create database file");
|
||||||
}
|
}
|
||||||
|
format!("sqlite:{}", database)
|
||||||
|
};
|
||||||
|
|
||||||
// Run migrations before starting the server
|
// Run migrations and setup demo data if needed
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let pool = sqlx::SqlitePool::connect(&db_url).await.unwrap();
|
let pool = sqlx::SqlitePool::connect(&db_url).await.unwrap();
|
||||||
@ -74,12 +85,13 @@ fn rocket() -> _ {
|
|||||||
.run(&pool)
|
.run(&pool)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to run database migrations");
|
.expect("Failed to run database migrations");
|
||||||
|
|
||||||
|
if args.demo {
|
||||||
|
demo::setup_demo_data(&pool).await;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let figment = rocket::Config::figment().merge((
|
let figment = rocket::Config::figment().merge(("databases.rss_data.url", db_url));
|
||||||
"databases.rss_data.url",
|
|
||||||
format!("sqlite:{}", args.database),
|
|
||||||
));
|
|
||||||
|
|
||||||
rocket::custom(figment)
|
rocket::custom(figment)
|
||||||
.mount(
|
.mount(
|
||||||
|
Loading…
Reference in New Issue
Block a user