### Run Frontend Development Server Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Navigates to the frontend directory, installs dependencies using npm, and starts the frontend development server. This is typically used for frontend-specific development. ```bash cd frontend && npm && npm start ``` -------------------------------- ### Set Up Database Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Initializes the database according to the Diesel configuration, typically creating the database if it doesn't exist. ```bash diesel database setup ``` -------------------------------- ### Install Diesel CLI for PostgreSQL Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Installs the Diesel CLI with PostgreSQL support. This is a prerequisite for managing PostgreSQL databases with Diesel. ```bash cargo install diesel_cli --no-default-features --features postgres ``` -------------------------------- ### Build Production-Ready Application Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Compiles the project to create a production-ready executable. This command is used for deploying the application. ```bash cargo build ``` -------------------------------- ### Install create-rust-app CLI Source: https://github.com/wulf/create-rust-app/blob/main/README.md Installs the create-rust-app command-line interface using Cargo, Rust's package manager. This is the first step to using the tool. ```shell cargo install create-rust-app_cli ``` -------------------------------- ### Rust: Application Setup Function Source: https://context7.com/wulf/create-rust-app/llms.txt The `setup()` function initializes the application, configuring the database pool, mailer, and storage based on environment variables. It supports custom email templates. ```rust use create_rust_app::{setup, AppData, Database, Mailer}; fn main() { // Required environment variables: // - DATABASE_URL: postgres://user:pass@localhost/db or path/to/sqlite.db // - SECRET_KEY: secret key for JWT signing (when auth plugin enabled) // - SMTP_FROM_ADDRESS, SMTP_SERVER, SMTP_USERNAME, SMTP_PASSWORD, SEND_MAIL (for email) // - S3_HOST, S3_REGION, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY (for storage) let app_data: AppData = setup(); // AppData contains: // - app_data.database: Database connection pool // - app_data.mailer: Email sending service // - app_data.storage: S3 storage client (if plugin_storage enabled) // Use with custom email templates let app_data = setup().with_custom_email_templates(MyCustomTemplates::new()); } ``` -------------------------------- ### Database URL Setup and Plaintext Warning Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task involves guiding the user through database setup and automatically populating the .env file with the DATABASE_URL. It's crucial to warn the user about storing passwords in plaintext within the file. Docker can be used to show steps for booting up the database. ```bash # Example of a .env file structure DATABASE_URL="postgres://user:password@host:port/database" ``` -------------------------------- ### Install Diesel CLI for SQLite Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Installs the Diesel CLI with SQLite support. This is a prerequisite for managing SQLite databases with Diesel. ```bash cargo install diesel_cli --no-default-features --features sqlite-bundled ``` -------------------------------- ### Apply Database Migrations Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Runs all pending database migrations to update the database schema to the latest version. ```bash diesel migration run ``` -------------------------------- ### Application Setup Source: https://context7.com/wulf/create-rust-app/llms.txt Initializes the application by setting up the database pool, mailer, and storage client based on environment variables. Supports custom email templates. ```APIDOC ## Application Setup The `setup()` function initializes the application with database pool, mailer, and storage (if enabled). It loads environment variables and validates required configuration. ### Method ```rust use create_rust_app::{setup, AppData, Database, Mailer}; fn main() { // Required environment variables: // - DATABASE_URL: postgres://user:pass@localhost/db or path/to/sqlite.db // - SECRET_KEY: secret key for JWT signing (when auth plugin enabled) // - SMTP_FROM_ADDRESS, SMTP_SERVER, SMTP_USERNAME, SMTP_PASSWORD, SEND_MAIL (for email) // - S3_HOST, S3_REGION, S3_BUCKET, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY (for storage) let app_data: AppData = setup(); // AppData contains: // - app_data.database: Database connection pool // - app_data.mailer: Email sending service // - app_data.storage: S3 storage client (if plugin_storage enabled) // Use with custom email templates let app_data = setup().with_custom_email_templates(MyCustomTemplates::new()); } ``` ``` -------------------------------- ### Rust Backend Project Creation Command Source: https://github.com/wulf/create-rust-app/blob/main/README.md This is the core command for initiating a new Rust project. It takes the project name as an argument and sets up the basic structure for a full-stack application. ```rust create-rust-app create ``` -------------------------------- ### Running Background Tasks (Shell) Source: https://github.com/wulf/create-rust-app/blob/main/README.md Command to run the background task queue. This assumes the tasks are compiled into a binary named 'tasks'. ```shell cargo run --bin tasks ``` -------------------------------- ### Generate Project Resources Source: https://github.com/wulf/create-rust-app/blob/main/README.md After navigating into an existing project directory, this command generates code or resources based on your selections. This can include frontend and backend code, database migrations, or type definitions. ```shell cd ./my-todo-app create-rust-app # .. select resource type / properties ``` -------------------------------- ### Install cargo-watch for Continuous Compilation Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Installs the cargo-watch utility, which enables continuous compilation and execution of Rust applications as files change. It's used here to watch backend changes while ignoring frontend. ```bash cargo install cargo-watch ``` -------------------------------- ### Actix-Web Application Setup with Create Rust App Source: https://context7.com/wulf/create-rust-app/llms.txt This snippet demonstrates the complete setup of an Actix-Web application using the Create Rust App framework. It configures application data, authentication, and serves static files, integrating various plugins based on features. ```rust use actix_files::Files; use actix_web::{web, App, HttpServer, middleware}; use create_rust_app::{setup, AppConfig, AppData, Database, Mailer}; use create_rust_app::auth::{self, AuthConfig}; #[actix_web::main] async fn main() -> std::io::Result<()> { let app_data = setup(); let app_config = AppConfig { app_url: std::env::var("APP_URL") .unwrap_or_else(|_| "http://localhost:3000".to_string()), }; let auth_config = AuthConfig { #[cfg(feature = "plugin_auth-oidc")] oidc_providers: vec![], }; HttpServer::new(move || { let mut app = App::new() .app_data(web::Data::new(app_data.database.clone())) .app_data(web::Data::new(app_data.mailer.clone())) .app_data(web::Data::new(app_config.clone())) .app_data(web::Data::new(auth_config.clone())) .wrap(middleware::Logger::default()); #[cfg(feature = "plugin_storage")] { app = app.app_data(web::Data::new(app_data.storage.clone())); } // Mount auth endpoints at /api/auth app = app.service( web::scope("/api/auth") .configure(|cfg| { cfg.service(auth::endpoints(web::scope(""))); }) ); // Your custom API routes app = app.service( web::scope("/api") .route("/health", web::get().to(|| async { "OK" })) ); // Serve static files from frontend build app = app.service(Files::new("/", "./frontend/dist").index_file("index.html")); app }) .bind("127.0.0.1:3000")? .run() .await } ``` -------------------------------- ### Create a New Rust Project Source: https://github.com/wulf/create-rust-app/blob/main/README.md Initializes a new Rust web application project with the specified name. After creation, you can navigate into the project directory and run `create-rust-app` again to select backend frameworks, plugins, and other configurations. ```shell create-rust-app my-todo-app # .. select backend framework, plugins, etc. ``` -------------------------------- ### File Upload and Download with S3 (Rust) Source: https://github.com/wulf/create-rust-app/blob/main/README.md Demonstrates how to attach files to models and retrieve download URIs using an S3-compatible object store. It utilizes the `Storage` extractor and `Attachment` model. ```rust let s3_key = Attachment::attach("avatar", "users", user_id, AttachmentData { file_name: "image.png", data: bytes })?; ``` ```rust let storage: Storage // retreive this via the appropriate extractor in your frameowrk of choice let url = storage.download_uri(s3_key)?; ``` -------------------------------- ### Generate New Database Migration Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Creates a new SQL migration file for the database. The migration file will contain up and down SQL statements to manage schema changes. ```bash diesel migration generate ``` -------------------------------- ### Revert Last Database Migration Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Reverts the most recently applied database migration, rolling back schema changes. ```bash diesel migration revert ``` -------------------------------- ### Reset Database Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Resets the database to an empty state, usually by dropping and recreating the database. Use with caution as it deletes all data. ```bash diesel database reset ``` -------------------------------- ### Background Task Queueing (Rust) Source: https://github.com/wulf/create-rust-app/blob/main/README.md Shows how to add tasks to a background job queue using the `fang` crate. This functionality is currently supported for actix-web and postgresql. ```rust create_rust_app::tasks::queue() ``` -------------------------------- ### Updating Application Title and Manifest Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task focuses on changing the default application title from 'React App' to 'Create Rust App'. It also includes updating the manifest file to reflect this change, which is important for branding and mobile installations. ```html Create Rust App ``` ```json { "name": "Create Rust App", "short_name": "Create Rust App" } ``` -------------------------------- ### Run App in Development Mode with Watch Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Executes the application in development mode using `cargo-watch`. This command recompiles and restarts the backend automatically upon detecting changes, while the frontend updates instantly. ```bash cargo watch -x run -i frontend/ ``` -------------------------------- ### Generate TypeScript Types from Rust Code Source: https://github.com/wulf/create-rust-app/blob/main/crates/create-rust-app_cli/template/README.md Generates TypeScript definition files from Rust code that has been annotated with the `tsync` attribute. The output is saved to `frontend/src/types/rust.d.ts`. ```bash cargo tsync ``` -------------------------------- ### Social Authentication Configuration (Rust) Source: https://github.com/wulf/create-rust-app/blob/main/README.md Configures OIDC providers for social authentication, requiring the main auth plugin. It takes client IDs, secrets, and redirect paths as arguments. ```rust app.app_data(Data::new(AuthConfig { oidc_providers: vec![GOOGLE( "client_id", "client_secret", "/success/redirect", "/error/redirect", )], })) ``` -------------------------------- ### Queue Background Tasks with Fang in Rust Source: https://context7.com/wulf/create-rust-app/llms.txt Demonstrates defining and queuing synchronous and asynchronous tasks using the Fang library. It includes examples of implementing `Runnable` and `AsyncRunnable` traits for task structs and enqueuing them. Note that async queue connection should be handled at app startup. ```rust use create_rust_app::tasks::{queue, async_queue, create_async_queue}; use fang::{Runnable, AsyncRunnable, FangError, Queueable, AsyncQueueable}; use fang::serde::{Deserialize, Serialize}; use fang::async_trait; // Define a synchronous task #[derive(Serialize, Deserialize)] struct SendEmailTask { to: String, subject: String, body: String, } impl Runnable for SendEmailTask { fn run(&self, _queue: &dyn Queueable) -> Result<(), FangError> { println!("Sending email to: {}", self.to); // ... send email logic Ok(()) } } // Define an async task #[derive(Serialize, Deserialize)] struct ProcessImageTask { image_id: i32, } #[async_trait] impl AsyncRunnable for ProcessImageTask { async fn run(&self, _queue: &mut dyn AsyncQueueable) -> Result<(), FangError> { println!("Processing image: {}", self.image_id); // ... async image processing Ok(()) } } async fn queue_tasks() { // Queue a synchronous task let sync_queue = queue(); sync_queue.enqueue(SendEmailTask { to: "user@example.com".to_string(), subject: "Welcome!".to_string(), body: "Thanks for signing up.".to_string(), }).unwrap(); // Queue an async task (connect first at app startup) let async_q = async_queue(); { let mut q = async_q.lock().unwrap(); // Connect at app startup: // q.connect(fang::NoTls).await.unwrap(); q.enqueue(ProcessImageTask { image_id: 123 }).await.unwrap(); } } // Run task workers (separate binary: cargo run --bin tasks) // backend/main.rs creates the queue runner ``` -------------------------------- ### Integrating #[qsync] with Actix-web Endpoints Source: https://github.com/wulf/create-rust-app/blob/main/crates/qsync/README.md When using web frameworks like actix-web, the order of macro attributes is crucial. Ensure that the `#[qsync]` attribute is placed above framework-specific attributes like `#[get(...)]` or `#[post(...)]` because Rust evaluates macros from outermost to innermost. ```rust use actix_web::get; use wulf::qsync; struct MyActixService; impl MyActixService { #[qsync] #[get("/my-data")] async fn get_my_data() -> String { // ... implementation ... String::from("actix data") } } ``` -------------------------------- ### Configure OAuth2/OIDC Social Authentication in Rust Source: https://context7.com/wulf/create-rust-app/llms.txt Sets up social login providers like Google and GitHub using the auth-oidc plugin. It requires `actix_web`, `create_rust_app`, and configuration of `AuthConfig` with OIDC provider details. The example shows how to integrate this into an Actix web server. ```rust use actix_web::{web::Data, App, HttpServer}; use create_rust_app::{setup, AppConfig, auth::AuthConfig}; use create_rust_app::auth::oidc::OIDCProvider; #[actix_web::main] async fn main() -> std::io::Result<()> { let app_data = setup(); let app_config = AppConfig { app_url: "https://myapp.com".to_string(), }; let auth_config = AuthConfig { oidc_providers: vec![ // Google OAuth2 provider OIDCProvider::GOOGLE( "your-google-client-id".to_string(), "your-google-client-secret".to_string(), "/auth/success".to_string(), // Redirect on success "/auth/error".to_string(), // Redirect on error ), // Custom OIDC provider OIDCProvider { name: "github".to_string(), client_id: "github-client-id".to_string(), client_secret: "github-client-secret".to_string(), scope: vec!["user:email".to_string()], issuer_url: "https://github.com".to_string(), success_uri: "/auth/success".to_string(), error_uri: "/auth/error".to_string(), }, ], }; HttpServer::new(move || { App::new() .app_data(Data::new(app_data.clone())) .app_data(Data::new(app_config.clone())) .app_data(Data::new(auth_config.clone())) // ... configure routes }) .bind("127.0.0.1:3000")? .run() .await } ``` -------------------------------- ### Social Authentication Login Link (JSX) Source: https://github.com/wulf/create-rust-app/blob/main/README.md Provides a JSX link to initiate the social authentication flow, typically for services like Google. This is a frontend component. ```jsx Login with Google ``` -------------------------------- ### Frontend Links for OAuth2/OIDC Flow Source: https://context7.com/wulf/create-rust-app/llms.txt Provides HTML anchor tags for initiating OAuth2/OIDC login flows with different providers. Users click these links to start the authentication process. After successful authentication, the user is redirected to the specified `success_uri` with an `access_token` query parameter. ```html Login with Google Login with GitHub ``` -------------------------------- ### Validating Package Names in Cargo Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task addresses the need to prevent users from creating packages with names that conflict with Rust's built-in libraries or start with a digit. Cargo init fails in these scenarios, so validation is required before package creation. ```rust // Example validation logic (conceptual) fn is_valid_package_name(name: &str) -> bool { if name == "test" { return false; } if name.chars().next().map_or(false, |c| c.is_digit(10)) { return false; } true } ``` -------------------------------- ### CLI: Configure Existing Rust + React Project Source: https://context7.com/wulf/create-rust-app/llms.txt Adds resources and generates code for existing Create Rust App projects. Includes options for interactive configuration, generating react-query hooks (qsync), and adding new services (CRUD endpoints). ```bash cd my-project create-rust-app create-rust-app configure --qsync create-rust-app configure --new-service # Then enter resource name when prompted, e.g., "todo" ``` -------------------------------- ### Using web::block for Database Services in Actix Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task focuses on using `web::block` for services that access the database within an Actix web application. This is important for preventing blocking operations on the database from hindering the performance of the web server. Refer to the Actix documentation for detailed usage. ```rust use actix_web::web; async fn get_data_from_db() -> Result { // Simulate database access Ok("Data from database".to_string()) } async fn db_handler() -> web::Json { let data = web::block(|| get_data_from_db()) .await .unwrap(); // Proper error handling should be implemented here web::Json(data.unwrap()) } ``` -------------------------------- ### Project Root Detection using Cargo.toml Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task aims to locate the create-rust-app project root by searching for a specific key, `"[create-rust-app]"`, within the `Cargo.toml` file. This allows for consistent project structure regardless of where the user is running commands from. ```toml [package] name = "my_app" version = "0.1.0" edition = "2021" [create-rust-app] # This key helps identify the project root ``` -------------------------------- ### Annotating Rust Service Methods with #[qsync] Source: https://github.com/wulf/create-rust-app/blob/main/crates/qsync/README.md Use the `#[qsync]` attribute macro above your service methods to generate react-query hooks. This macro assumes your endpoints return JSON and relies on the directory structure to determine API paths. You can specify a return type or mark a method as a mutation. ```rust use wulf::qsync; struct MyService; impl MyService { #[qsync] async fn get_data() -> String { // ... implementation ... String::from("some data") } #[qsync(return_type = "string[]")] async fn get_list() -> Vec { // ... implementation ... vec!["item1".to_string(), "item2".to_string()] } #[qsync(mutate)] async fn update_data(id: u32, value: String) { // ... implementation ... } } ``` -------------------------------- ### Frontend Linting and Formatting with ESLint and Prettier Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task involves integrating ESLint and Prettier into the frontend development workflow. These tools help maintain code quality and consistency by enforcing coding standards and automatically formatting the code. ```json { "devDependencies": { "eslint": "^8.0.0", "prettier": "^2.0.0" } } ``` ```bash # Example commands yarn lint yarn format ``` -------------------------------- ### CLI: Create New Rust + React Project Source: https://context7.com/wulf/create-rust-app/llms.txt Scaffolds a new Rust + React project. Supports interactive mode or non-interactive CLI with specified backend framework, database, and plugins like auth, storage, and containerization. ```bash create-rust-app my-todo-app create-rust-app create my-app \ --cli \ --database postgres \ --backend actix-web \ --plugins auth,storage,container # Available plugins: # - auth: JWT-based email authentication with RBAC # - auth-oidc: OAuth2/OIDC social authentication # - container: Docker containerization # - storage: S3-compatible file storage # - graphql: GraphQL with playground # - utoipa: OpenAPI/Swagger documentation ``` -------------------------------- ### CLI - Create New Project Source: https://context7.com/wulf/create-rust-app/llms.txt Scaffolds a new Rust + React project with specified backend framework, database, and plugins. Supports interactive mode or non-interactive CLI arguments. ```APIDOC ## CLI - Create New Project Creates a new Rust + React project with the selected backend framework, database, and plugins. ### Method ```bash create-rust-app ``` ### Parameters #### CLI Arguments - `--cli` (boolean) - Use non-interactive CLI mode. - `--database` (string) - Specify database: `postgres` or `sqlite`. - `--backend` (string) - Specify backend framework: `actix-web` or `poem`. - `--plugins` (string) - Comma-separated list of plugins: `auth`, `auth-oidc`, `container`, `storage`, `graphql`, `utoipa`. ### Request Example ```bash # Interactive mode create-rust-app my-todo-app # Non-interactive mode create-rust-app create my-app \ --cli \ --database postgres \ --backend actix-web \ --plugins auth,storage,container ``` ``` -------------------------------- ### CLI - Configure Existing Project Source: https://context7.com/wulf/create-rust-app/llms.txt Adds resources and generates code for existing Create Rust App projects. Can be used interactively or for specific tasks like query synchronization or new service generation. ```APIDOC ## CLI - Configure Existing Project Adds resources and generates code for existing Create Rust App projects. ### Method ```bash cd create-rust-app [configure options] ``` ### Parameters #### CLI Arguments - `--qsync` (boolean) - Generate react-query hooks from backend services. - `--new-service` (boolean) - Add a new model and service (CRUD endpoints). Prompts for resource name. ### Request Example ```bash # Enter interactive configuration menu cd my-project create-rust-app # Generate react-query hooks create-rust-app configure --qsync # Add a new service create-rust-app configure --new-service ``` ``` -------------------------------- ### Manage Model Attachments in Rust Source: https://context7.com/wulf/create-rust-app/llms.txt Illustrates how to use the Attachment system to link files to database records. This includes attaching single or multiple files, finding attachments for records, and detaching single or all attachments. It requires `create_rust_app::Attachment`, `create_rust_app::AttachmentData`, `create_rust_app::Storage`, `create_rust_app::Database`, and `create_rust_app::Connection`. ```rust use create_rust_app::{Attachment, AttachmentData, Storage, Database, Connection}; async fn attachment_operations( db: &mut Connection, storage: &Storage, user_id: i32 ) { // Attach an avatar to a user record let image_bytes = std::fs::read("./avatar.png").unwrap(); let s3_key = Attachment::attach( db, storage, "avatar".to_string(), // Attachment name/type "users".to_string(), // Record type (table name) user_id, // Record ID AttachmentData { data: image_bytes, file_name: Some("avatar.png".to_string()), }, false, // allow_multiple: false = only one avatar per user true, // overwrite_existing: replace if exists ).await.unwrap(); println!("Uploaded with key: {}", s3_key); // Attach multiple images to a product (allow_multiple = true) for (i, image_path) in ["img1.jpg", "img2.jpg"].iter().enumerate() { let bytes = std::fs::read(image_path).unwrap(); Attachment::attach( db, storage, "images".to_string(), "products".to_string(), product_id, AttachmentData { data: bytes, file_name: Some(image_path.to_string()), }, true, // allow_multiple false, // don't overwrite ).await.unwrap(); } // Find attachment for a record let avatar = Attachment::find_for_record( db, "avatar".to_string(), "users".to_string(), user_id ).unwrap(); // Find all attachments for a record let product_images = Attachment::find_all_for_record( db, "images".to_string(), "products".to_string(), product_id ).unwrap(); // Detach (delete) a single attachment Attachment::detach(db, storage, avatar.id).await.unwrap(); // Detach all attachments of a type for a record Attachment::detach_all( db, storage, "images".to_string(), "products".to_string(), product_id ).await.unwrap(); } ``` -------------------------------- ### Splitting Frontend CRA Logic into a Separate Package Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task proposes extracting frontend Create React App (CRA) logic, such as the `useAuth` hook, into a separate npm package. This promotes reusability and modularity, although it might be less favorable if the project's focus shifts away from React. ```javascript // Example of a hook that could be extracted import { useState, useEffect } from 'react'; function useAuth(initialState) { const [isAuthenticated, setIsAuthenticated] = useState(initialState); useEffect(() => { // Authentication logic here }, []); return [isAuthenticated, setIsAuthenticated]; } export default useAuth; ``` -------------------------------- ### Perform S3-Compatible File Operations in Rust Source: https://context7.com/wulf/create-rust-app/llms.txt Demonstrates various file operations using the Storage plugin, including uploading, downloading, generating presigned URLs for download and upload, and deleting files. It requires the `create_rust_app::Storage` and `create_rust_app::AppData` types. ```rust use create_rust_app::{Storage, AppData}; use std::time::Duration; use std::path::PathBuf; async fn storage_operations(app_data: &AppData) { let storage: &Storage = &app_data.storage; // Upload a file directly let file_bytes = std::fs::read("./image.png").unwrap(); let key = "uploads/image.png".to_string(); storage.upload( key.clone(), file_bytes, "image/png".to_string(), "d41d8cd98f00b204e9800998ecf8427e".to_string(), // MD5 hash ).await.unwrap(); // Download a file to local path storage.download( "uploads/image.png".to_string(), PathBuf::from("./downloaded.png") ).await.unwrap(); // Get presigned download URL (expires in 1 hour) let download_url = storage.download_uri( "uploads/image.png".to_string(), Some(Duration::from_secs(3600)) ).await.unwrap(); println!("Download URL: {}", download_url); // Get public URL (when bucket allows public access) let public_url = storage.download_uri( "public/image.png".to_string(), None // None = public URL ).await.unwrap(); // Get presigned upload URL for client-side uploads let upload_uri = storage.upload_uri( "uploads/new-file.jpg".to_string(), Duration::from_secs(3600) ).await.unwrap(); println!("Upload to: {}", upload_uri.uri); // Headers to include: upload_uri.headers // Delete a file storage.delete("uploads/old-file.png".to_string()).await.unwrap(); // Delete multiple files storage.delete_many(vec![ "uploads/file1.png".to_string(), "uploads/file2.png".to_string(), ]).await.unwrap(); } ``` -------------------------------- ### User Authentication API Source: https://context7.com/wulf/create-rust-app/llms.txt Handles user login by verifying credentials and returning an access token and refresh token. ```APIDOC ## POST /api/auth/login ### Description Logs in a user by verifying their email and password. Returns an access token in the response body and a refresh token as an HttpOnly cookie. ### Method POST ### Endpoint /api/auth/login ### Parameters #### Query Parameters None #### Request Body - **email** (string) - Required - The user's email address. - **password** (string) - Required - The user's password. - **device** (string) - Optional - Information about the client device. ### Request Example ```json { "email": "user@example.com", "password": "securepass123", "device": "Chrome on macOS" } ``` ### Response #### Success Response (200) - **access_token** (string) - The JWT access token for authenticated requests. - **refresh_token** (cookie) - An HttpOnly cookie containing the refresh token. #### Response Example ```json { "access_token": "eyJ..." } ``` ```cookies refresh_token=eyJ...; HttpOnly; Secure; SameSite=Strict ``` ``` -------------------------------- ### Manage Roles and Permissions in Rust Source: https://context7.com/wulf/create-rust-app/llms.txt Demonstrates how to use the Role and Permission structs for RBAC functionality. It covers assigning/unassigning roles, granting/revoking permissions to users and roles, and fetching user permissions. Requires the `create_rust_app::auth` module and a `Database` connection. ```rust use create_rust_app::auth::{Role, Permission}; use create_rust_app::Database; async fn manage_roles_and_permissions(db: &Database) { let mut conn = db.get_connection().unwrap(); let user_id: i32 = 1; // Assign a single role to user Role::assign(&mut conn, user_id, "admin").unwrap(); // Assign multiple roles at once Role::assign_many(&mut conn, user_id, vec![ "editor".to_string(), "reviewer".to_string() ]).unwrap(); // Unassign role from user Role::unassign(&mut conn, user_id, "reviewer").unwrap(); // Get all roles for a user let user_roles: Vec = Role::fetch_all(&mut conn, user_id).unwrap(); println!("User roles: {:?}", user_roles); // Grant permission directly to user Permission::grant_to_user(&mut conn, user_id, "posts:create").unwrap(); // Grant permission to a role (all users with this role get the permission) Permission::grant_to_role(&mut conn, "editor", "posts:edit").unwrap(); // Grant multiple permissions to a role Permission::grant_many_to_role(&mut conn, "admin".to_string(), vec![ "users:read".to_string(), "users:write".to_string(), "users:delete".to_string(), ]).unwrap(); // Revoke permissions Permission::revoke_from_user(&mut conn, user_id, "posts:create").unwrap(); Permission::revoke_from_role(&mut conn, "editor".to_string(), "posts:edit".to_string()).unwrap(); Permission::revoke_all_from_role(&mut conn, "guest").unwrap(); // Fetch all permissions for a user (includes role-based permissions) let all_permissions: Vec = Permission::fetch_all(&mut conn, user_id).unwrap(); for perm in all_permissions { println!("Permission: {} (from role: {})", perm.permission, perm.from_role); } } ``` -------------------------------- ### Create Rust App Environment Variables Reference Source: https://context7.com/wulf/create-rust-app/llms.txt This section lists and explains the required and optional environment variables used to configure a Create Rust App application. It covers settings for database connection, JWT secrets, email services, S3 storage, and workspace paths. ```bash # .env file example # Required: Database connection DATABASE_URL=postgres://postgres:postgres@localhost/myapp # For SQLite: DATABASE_URL=./db.sqlite3 # Required for auth plugin: JWT signing key SECRET_KEY=your-super-secret-key-at-least-32-chars # Email configuration (required for auth plugin email features) SMTP_FROM_ADDRESS=noreply@myapp.com SMTP_SERVER=smtp.gmail.com SMTP_USERNAME=your-email@gmail.com SMTP_PASSWORD=your-app-password SEND_MAIL=true # Set to 'false' to disable actual email sending # S3 storage configuration (required for storage plugin) S3_HOST=https://s3.us-west-2.amazonaws.com S3_REGION=us-west-2 S3_BUCKET=my-app-bucket S3_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE S3_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY # Optional: Workspace configuration CRA_MANIFEST_PATH=./frontend/dist/manifest.json CRA_FRONTEND_DIR=./frontend CRA_VIEWS_GLOB=backend/views/**/*.html ``` -------------------------------- ### REST API: Authentication Endpoints (Auth Plugin) Source: https://context7.com/wulf/create-rust-app/llms.txt The auth plugin provides JWT-based authentication and session management, with endpoints mounted under `/api/auth`. Includes registration and account activation via email. ```bash # Register a new user (sends activation email) curl -X POST http://localhost:3000/api/auth/register \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "securepass123"}' # Response: {"message": "Registered! Check your email to activate your account."} # Activate account via token from email curl "http://localhost:3000/api/auth/activate?activation_token=eyJ..." ``` -------------------------------- ### User Sessions API Source: https://context7.com/wulf/create-rust-app/llms.txt Retrieves a list of user's active sessions, with pagination support. ```APIDOC ## GET /api/auth/sessions ### Description Retrieves a paginated list of the authenticated user's active sessions. ### Method GET ### Endpoint /api/auth/sessions ### Parameters #### Path Parameters None #### Query Parameters - **page** (integer) - Optional - The page number to retrieve (default is 1). - **page_size** (integer) - Optional - The number of sessions per page (default is 10). #### Request Body None ### Request Example ```bash curl http://localhost:3000/api/auth/sessions?page=1&page_size=10 \ -H "Authorization: Bearer eyJ..." ``` ### Response #### Success Response (200) - **sessions** (array) - A list of session objects. - **id** (integer) - The session ID. - **device** (string) - The device information for the session. - **created_at** (string) - The timestamp when the session was created. - **num_pages** (integer) - The total number of pages available. #### Response Example ```json { "sessions": [ { "id": 1, "device": "Chrome", "created_at": "..." } ], "num_pages": 1 } ``` ``` -------------------------------- ### Code Generation Commands Source: https://context7.com/wulf/create-rust-app/llms.txt Provides built-in cargo commands for generating Diesel models from the database schema and TypeScript types from Rust structs marked with `#[tsync::tsync]`. ```APIDOC ## Code Generation Commands Built-in cargo commands for generating Diesel models and TypeScript types. ### Commands - `cargo dsync`: Generate Diesel model structs from database schema. Output: `backend/models/*.rs`. - `cargo tsync`: Generate TypeScript types from Rust structs marked with `#[tsync::tsync]`. Output: `frontend/src/types/rust.d.ts`. - `cargo fullstack`: Run both frontend and backend with hot-reload. - `cargo backend`: Run only the backend development server. - `cargo frontend`: Run only the frontend development server. ``` -------------------------------- ### Diesel Migrations Directory Configuration Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This snippet shows the configuration for the Diesel migrations directory within `diesel.toml`. It specifies the location of migration files. Note that Diesel 2.x is expected to fully support this, while older versions like 1.4.8 might have limitations. ```toml [migrations_directory] file="backend/migrations" dir="backend/migrations" ``` -------------------------------- ### Authentication - REST API Endpoints Source: https://context7.com/wulf/create-rust-app/llms.txt The auth plugin provides REST API endpoints for JWT-based authentication and session management, all accessible under the `/api/auth` base path. ```APIDOC ## Authentication - REST API Endpoints The auth plugin provides complete JWT-based authentication with session management. All endpoints are mounted under `/api/auth`. ### Endpoints #### POST /api/auth/register Registers a new user. Sends an activation email upon successful registration. ##### Request Body - **email** (string) - Required - User's email address. - **password** (string) - Required - User's chosen password. ##### Response (200 OK) - **message** (string) - Confirmation message. ##### Request Example ```bash curl -X POST http://localhost:3000/api/auth/register \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "securepass123"}' ``` #### GET /api/auth/activate Activates a user account using a token received via email. ##### Query Parameters - **activation_token** (string) - Required - The token sent in the activation email. ##### Response Example ```bash curl "http://localhost:3000/api/auth/activate?activation_token=eyJ..." ``` ``` -------------------------------- ### Rust Auth Guard for Protected Endpoints Source: https://context7.com/wulf/create-rust-app/llms.txt Rust code demonstrating how to use the `Auth` extractor from `create-rust-app` to protect API endpoints. It shows how to access authenticated user IDs and check roles/permissions before allowing access to resources. ```rust use actix_web::{web, HttpResponse, get, post}; use create_rust_app::auth::{Auth, PaginationParams}; use create_rust_app::Database; // Simple protected endpoint - just requires valid JWT #[get("/api/profile")] async fn get_profile(auth: Auth, db: web::Data) -> HttpResponse { // auth.user_id contains the authenticated user's ID let user_id: i32 = auth.user_id; // Fetch user data from database let mut conn = db.get_connection().unwrap(); // ... query user HttpResponse::Ok().json(serde_json::json!({ "user_id": user_id })) } // Check roles and permissions #[post("/api/admin/users")] async fn admin_action(auth: Auth) -> HttpResponse { // Check if user has specific role if !auth.has_role("admin") { return HttpResponse::Forbidden().body("Admin role required"); } // Check for specific permission if !auth.has_permission("users:write".to_string()) { return HttpResponse::Forbidden().body("Permission denied"); } // Check multiple roles (any match) let is_privileged = auth.has_any_roles(["admin", "moderator"].map(String::from).to_vec()); // Check multiple permissions (all required) let can_manage = auth.has_all_permissions( ["users:read", "users:write"].map(String::from).to_vec() ); HttpResponse::Ok().finish() } ``` -------------------------------- ### Send Emails with Mailer and Custom Templates in Rust Source: https://context7.com/wulf/create-rust-app/llms.txt Illustrates using the Mailer struct for sending emails with both plain text and HTML content. It also shows how to implement custom email templates by creating a struct that derives `Clone` and implements the `EmailTemplates` trait. ```rust use create_rust_app::{Mailer, DefaultMailTemplates, EmailTemplates, AppData}; fn send_emails(mailer: &Mailer) { // Send a simple email mailer.send( "recipient@example.com", "Subject Line", "Plain text version of the email", "

HTML version

of the email

" ); } // Custom email templates for auth plugin #[derive(Clone)] struct CustomEmailTemplates { base_url: String, } impl EmailTemplates for CustomEmailTemplates { fn send_register(&self, mailer: &Mailer, to_email: &str, link: &str) { mailer.send( to_email, "Welcome to MyApp!", &format!("Click here to activate: {}{}", self.base_url, link), &format!("Activate your account", self.base_url, link), ); } fn send_activated(&self, mailer: &Mailer, to_email: &str) { mailer.send( to_email, "Account Activated", "Your account is now active!", "

Your account is now active!

", ); } fn send_password_changed(&self, mailer: &Mailer, to_email: &str) { mailer.send(to_email, "Password Changed", "Your password was changed.", "

Your password was changed.

"); } fn send_password_reset(&self, mailer: &Mailer, to_email: &str) { mailer.send(to_email, "Password Reset", "Your password was reset.", "

Your password was reset.

"); } fn send_recover_existent_account(&self, mailer: &Mailer, to_email: &str, link: &str) { mailer.send(to_email, "Reset Password", &format!("Reset: {}", link), &format!("Reset password", link)); } fn send_recover_nonexistent_account(&self, mailer: &Mailer, to_email: &str, link: &str) { mailer.send(to_email, "No Account Found", &format!("Register: {}", link), &format!("Create account", link)); } } // Use custom templates fn setup_with_custom_templates() -> AppData { use create_rust_app::setup; setup().with_custom_email_templates(CustomEmailTemplates { base_url: "https://myapp.com/".to_string(), }) } ``` -------------------------------- ### Protected Endpoints - Auth Guard Source: https://context7.com/wulf/create-rust-app/llms.txt Demonstrates how to protect API endpoints using the Auth Guard, which validates JWT tokens and checks roles/permissions. ```APIDOC ## GET /api/profile ### Description A simple protected endpoint that requires a valid JWT access token. It returns the authenticated user's ID. ### Method GET ### Endpoint /api/profile ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example (Requires Authorization header with a valid Bearer token) ### Response #### Success Response (200) - **user_id** (integer) - The ID of the authenticated user. #### Response Example ```json { "user_id": 123 } ``` ## POST /api/admin/users ### Description An example endpoint demonstrating role and permission checks for administrative actions. Requires specific roles or permissions to access. ### Method POST ### Endpoint /api/admin/users ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body (Assumed to contain data for user creation/modification, not detailed here) ### Request Example (Requires Authorization header with a valid Bearer token and appropriate roles/permissions) ### Response #### Success Response (200) (Returns success status if authorized) #### Response Example (No example provided) #### Error Response (403 Forbidden) Returned if the user does not have the required roles or permissions. ``` Admin role required ``` ``` Permission denied ``` ``` -------------------------------- ### Database Connection Source: https://context7.com/wulf/create-rust-app/llms.txt Provides a `Database` struct that wraps a connection pool using r2d2 and Diesel, supporting both PostgreSQL and SQLite. Connections can be obtained and used for Diesel queries. ```APIDOC ## Database Connection The `Database` struct provides a connection pool wrapper using r2d2 and Diesel, supporting both PostgreSQL and SQLite. ### Method ```rust use create_rust_app::{Database, Pool, Connection}; use diesel::prelude::*; fn example_query(db: &Database) -> Result, anyhow::Error> { // Get a connection from the pool let mut conn: Connection = db.get_connection()?; // Use with Diesel queries use crate::schema::users::dsl::*; let results = users .filter(activated.eq(true)) .limit(10) .load::(&mut conn)?; Ok(results) } // Database is also available via AppData fn with_app_data(app_data: &AppData) { let mut conn = app_data.database.get_connection().unwrap(); // ... use connection } ``` ``` -------------------------------- ### CSRF Mitigation Implementation Source: https://github.com/wulf/create-rust-app/blob/main/docs/TODO.md This task involves implementing a Cross-Site Request Forgery (CSRF) mitigation technique to protect web applications from malicious attacks. Various strategies can be employed, such as using synchronizer tokens. ```bash # Conceptual implementation steps: # 1. Generate a CSRF token on the server. # 2. Embed the token in a hidden form field. # 3. Validate the token on the server for incoming requests. ``` -------------------------------- ### API Authentication Endpoints (cURL) Source: https://context7.com/wulf/create-rust-app/llms.txt Collection of cURL commands to interact with API authentication endpoints. These include login, token refresh, session retrieval, logout, password change, forgot password, and password reset. They demonstrate request methods, headers, request bodies, and expected responses. ```bash curl -X POST http://localhost:3000/api/auth/login \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com", "password": "securepass123", "device": "Chrome on macOS"}' # Response: {"access_token": "eyJ..."} # Cookie: refresh_token=eyJ...; HttpOnly; Secure; SameSite=Strict curl -X POST http://localhost:3000/api/auth/refresh \ -b "refresh_token=eyJ..." # Response: {"access_token": "eyJ..."} curl http://localhost:3000/api/auth/sessions?page=1&page_size=10 \ -H "Authorization: Bearer eyJ..." # Response: {"sessions": [{"id": 1, "device": "Chrome", "created_at": "..."}], "num_pages": 1} curl -X POST http://localhost:3000/api/auth/logout \ -b "refresh_token=eyJ..." curl -X POST http://localhost:3000/api/auth/change \ -H "Authorization: Bearer eyJ..." \ -H "Content-Type: application/json" \ -d '{"old_password": "oldpass", "new_password": "newpass"}' curl -X POST http://localhost:3000/api/auth/forgot \ -H "Content-Type: application/json" \ -d '{"email": "user@example.com"}' curl -X POST http://localhost:3000/api/auth/reset \ -H "Content-Type: application/json" \ -d '{"reset_token": "eyJ...", "new_password": "newpass123"}' ```