# 💰 Budgeteer [![Build and Test](https://github.com/edgeofsanity76/Budgeteer/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/edgeofsanity76/Budgeteer/actions/workflows/build-and-test.yml) [![Docker Publish](https://github.com/edgeofsanity76/Budgeteer/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/edgeofsanity76/Budgeteer/actions/workflows/docker-publish.yml) A personal finance dashboard built with Blazor Server (.NET 10). > **Status:** beta — see the in-app badge. ## Features - **Multi-account support** — current accounts, savings, credit cards, each with its own currency and colour - **Transaction tracking** — income & expenses with date, category, and account assignment - **Recurring transactions** — daily, weekly, monthly, or yearly recurrence with automatic materialisation up to one year ahead - **Dashboard** — balance trend chart (Chart.js), recent & upcoming transaction lists, account filter toggles, inline balance editing, and configurable time window - **Reports** — doughnut charts for expenses and income by category, monthly income vs expenses bar chart, and a category summary table with filterable date range and account selection - **Categories** — emoji-icon categories with sensible defaults and full CRUD - **Transactions table** — sortable columns, search, pagination, per-account filtering, time-window presets, bulk selection & delete, and responsive column hiding on mobile - **Authentication** — ASP.NET Identity with registration, login, password change, account deletion, and 5-attempt lockout - **SSO providers** — optional Google, Microsoft, and GitHub sign-in (configured via `appsettings.json`) - **Settings** — change password, reset all data (with confirmation), delete account - **Toast notifications** — inline validation feedback via a toast system - **Help & About pages** — in-app guides, tips, and project info - **Responsive UI** — Bootstrap 5, mobile-friendly layout with collapsible sidebar, responsive table columns, and scoped CSS - **CI/CD** — GitHub Actions for build/test and Docker Hub publishing - **Docker** — multi-stage Dockerfile with volume-mounted SQLite, OCI image labels, and automatic security patching ## Tech Stack | Layer | Technology | |---|---| | Framework | .NET 10 / Blazor Server (InteractiveServer) | | Database | SQLite via EF Core | | Auth | ASP.NET Core Identity + optional Google / Microsoft / GitHub SSO | | Charts | Chart.js (CDN) with JS interop | | CSS | Bootstrap 5, scoped CSS | | Tests | xUnit | | CI/CD | GitHub Actions | | Container | Docker (multi-stage build) | ## Getting Started ### Prerequisites - [.NET 10 SDK](https://dotnet.microsoft.com/download/dotnet/10.0) ### Run Locally ```bash cd BudgetApp dotnet run ``` The app will be available at `https://localhost:5001` (or the port shown in the console). A `budgetapp.db` SQLite file is created automatically on first run. ### Run Tests ```bash dotnet test ``` ### Run with Docker ```bash # Build docker build -t budgeteer . # Run (persists database in a named volume) docker run -d -p 8080:8080 -v budgeteer-data:/app/data --name budgeteer budgeteer ``` > **Note:** The SQLite database is stored at `/app/data/budgetapp.db` inside the container. > Always mount a volume to `/app/data` so your data survives image updates and container replacements. The app will be available at `http://localhost:8080`. ## Project Structure ``` BudgetApp/ ├── Components/ │ ├── Layout/ # MainLayout, AuthLayout, NavMenu │ ├── Pages/ # Home, Accounts, Transactions, Categories, │ │ # Reports, Settings, Help, About, Login, Register │ ├── ToastContainer.razor │ └── ToastValidator.razor ├── Data/ # EF Core entities, DbContext, Identity user ├── Migrations/ # EF Core migrations (SQLite) ├── Services/ # AccountService, TransactionService, CategoryService, │ # DashboardService, ToastService, AppState └── wwwroot/ ├── app.css # Global styles └── js/ └── chart-interop.js # Chart.js interop (line, doughnut, bar charts) BudgetApp.Tests/ ├── Helpers/ # TestDbContextFactory ├── Models/ # AccountModelTests └── Services/ # AccountService, TransactionService, CategoryService, # DashboardService tests ``` ## Configuration Default connection string in `appsettings.json`: ```json { "ConnectionStrings": { "DefaultConnection": "Data Source=budgetapp.db" } } ``` Override at runtime via environment variable: ```bash export ConnectionStrings__DefaultConnection="Data Source=/path/to/budgeteer.db" ``` ### SSO Providers (optional) Add client credentials to `appsettings.json` (or via environment / user-secrets). Each provider is only registered when both `ClientId` and `ClientSecret` are non-empty. ```json { "Authentication": { "Google": { "ClientId": "", "ClientSecret": "" }, "Microsoft": { "ClientId": "", "ClientSecret": "" }, "GitHub": { "ClientId": "", "ClientSecret": "" } } } ``` ## Licence This project is provided as-is for personal use. ## Using Custom SSL Certificates To enable HTTPS with custom SSL certificates in your Blazor application, follow these steps: 1. **Prepare PEM Files** Place your certificate and private key files in PEM format in a directory accessible by your app. Example paths: - `/app/data/certs/cert.pem` - `/app/data/certs/key.pem` 2. **Configure Certificate Paths** The application will look for certificate files in the following order: - Environment variables: `PEM_CERT_FILE` and `PEM_KEY_FILE` - Configuration values: `PemCertFile` and `PemKeyFile` in `appsettings.json` - Default: `/app/data/certs/cert.pem` and `/app/data/certs/key.pem` You can set environment variables before running the app: ```bash export PEM_CERT_FILE=/path/to/cert.pem export PEM_KEY_FILE=/path/to/key.pem ``` Or add to your `appsettings.json`: ```json { "PemCertFile": "/path/to/cert.pem", "PemKeyFile": "/path/to/key.pem" } ``` 3. **Fallback Behavior** If the certificate files are not found, the app will use the default development certificate. 4. **No Code Changes Needed** The certificate loading logic is already implemented in `Program.cs`. Simply provide the files and configuration as described above. --- **Note:** - Certificates must be in PEM format (`.pem`). - Ensure file permissions allow the app to read the certificate and key files. - For production, use certificates issued by a trusted Certificate Authority.