Skip to content

A modern, open-source .NET and Vue.JS Learning Management System (LMS), that enables organizations to deliver corporate training, track employee progress, and issue digitally-signed certificates

License

Notifications You must be signed in to change notification settings

lukasnymsa/training-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TrainingApp

License: MIT .NET Vue

A modern, open-source Learning Management System (LMS) built specifically for the .NET ecosystem. TrainingApp enables organizations to deliver corporate training, track employee progress, and issue digitally-signed certificates - all while maintaining full control over their data through self-hosted deployment.

📑 Table of Contents

📖 Overview

TrainingApp addresses the gap in open-source Learning Management Systems for organizations standardized on Microsoft technologies. Unlike popular LMS platforms built on PHP, Python, or Ruby, TrainingApp is native to the .NET ecosystem, reducing operational overhead and integration complexity for .NET-focused organizations.

The platform was developed as part of a diploma thesis analyzing corporate training requirements, digital signature integration, and data sovereignty concerns. It provides a complete solution for:

  • Corporate Training Management - Create courses, assign users, track completion
  • Knowledge Assessment - Build tests with multiple question types and automated grading
  • Compliance Certification - Generate PDF certificates with optional digital signatures via DigiSign
  • Data Sovereignty - Self-host on your infrastructure with full control over sensitive employee data

✨ Key Features

For Administrators

  • User and group management with role-based access control (Administrator, Instructor, Member)
  • Bulk enrollment of users and groups to courses
  • System-wide configuration and monitoring
  • OAuth authentication via Google and Microsoft

For Instructors

  • Rich text course content editor with multimedia support (images, YouTube/Vimeo videos)
  • Flexible test creation with 5 question types:
    • Single choice
    • Multiple choice
    • True/False
    • Number input
    • Open-ended text
  • Automated grading for objective questions
  • Manual grading interface for subjective questions
  • Course and test analytics

For Learners

  • Browse enrolled courses and learning materials
  • Take tests with attempt tracking
  • View progress and test history
  • Download verified certificates upon course completion

Technical Features

  • Modern Architecture - Clean Architecture + Vertical Slice Architecture hybrid
  • CQRS Pattern - Separation of command and query responsibilities
  • REPR Pattern - Request-Endpoint-Response API design
  • OAuth 2.0 - Passwordless authentication via external providers
  • JWT Security - Stateless token-based authorization
  • Digital Signatures - Integration with DigiSign for eIDAS-compliant certificates
  • Domain Events - Event-driven automation for certificate generation
  • Automated Audit - Built-in change tracking for all entities

📸 Screenshots

Rich Text Course Editor

Course Editor

Mobile View - Editor and Course Detail

Mobile View

Test Attempt Grading

Attempt Grading

🛠️ Technology Stack

Backend

  • .NET 9.0 - Primary framework
  • ASP.NET Core - Web API with Minimal APIs
  • Entity Framework Core - Data access with SQLite (PostgreSQL-ready)
  • ASP.NET Core Identity - User and role management
  • Wolverine - Mediator and message bus for CQRS
  • FluentValidation - Request validation
  • QuestPDF - PDF certificate generation
  • xUnit - Integration testing

Frontend

  • Vue 3 - Progressive JavaScript framework with Composition API
  • TypeScript - Type-safe development
  • Pinia - State management
  • Vue Router - Client-side routing
  • PrimeVue - UI component library
  • Axios - HTTP client
  • Vite - Build tool and dev server
  • Quill.js - Rich text editor

Infrastructure

  • Docker - Containerization
  • SQLite - Default database (development)
  • Nginx - Frontend static file serving
  • GitLab CI - Continuous integration

🚀 Getting Started

Prerequisites

For Docker deployment:

  • Docker Engine 20.10+
  • Docker Compose 2.0+

For development:

  • .NET SDK 9.0+
  • Node.js 22+ (or Node.js 20.19.0+)
  • Git

Quick Start with Docker

  1. Clone the repository
git clone https://gitlab.fit.cvut.cz/nymsaluk/trainingappdockerized.git
cd trainingappdockerized
  1. Start the application
docker-compose up -d
  1. Access the application
  1. First-time setup
    • Create an admin user through OAuth login (Google or Microsoft)
    • Configure OAuth providers in backend settings (see Configuration)

For detailed deployment instructions, see DEPLOYMENT.md.

Development Setup

Backend Setup

  1. Navigate to backend directory
cd be
  1. Restore dependencies
dotnet restore
  1. Update database
cd TrainingApp.Web
dotnet ef database update
  1. Run the backend
dotnet run --project TrainingApp.Web

Backend will be available at http://localhost:5000.

Frontend Setup

  1. Navigate to frontend directory
cd fe
  1. Install dependencies
npm install
  1. Configure environment Create a .env file:
VITE_API_BASE_URL=http://localhost:5000
  1. Run the development server
npm run dev

Frontend will be available at http://localhost:5173.

🏗️ Architecture

TrainingApp implements a hybrid architecture combining Clean Architecture principles with Vertical Slice Architecture:

Backend Structure

be/
├── TrainingApp.Core/                # Domain entities and application logic
│   ├── Domain/                      # Domain models organized by entity
│   │   ├── Users/
│   │   ├── Courses/
│   │   ├── Tests/
│   │   ├── Enrollments/
│   │   ├── Certificates/
│   │   └── ...
│   └── Application/                 # Application layer
│       ├── Features/                # Vertical slices (Commands, Queries, Events)
│       ├── Abstractions/            # Interfaces (IDataAccess, ICqrsDispatcher)
│       └── Common/                  # Shared application logic
├── TrainingApp.Infrastructure/      # External concerns
│   ├── Data/                        # EF Core DbContext
│   ├── Migrations/                  # Database migrations
│   ├── Services/                    # DigiSign, Certificate generation
│   ├── Cqrs/                        # Wolverine dispatcher adapter
│   ├── Identity/                    # ASP.NET Core Identity implementation
│   ├── OAuth/                       # OAuth provider integrations
│   └── Persistence/                 # Repository implementations
├── TrainingApp.Web/                 # API presentation layer
│   ├── Endpoints/                   # REPR pattern endpoints
│   ├── Middleware/                  # Request logging, error handling
│   └── Pages/                       # Razor pages (if any)
└── TrainingApp.Web.IntegrationTests/# Integration test suite

Frontend Structure

fe/
├── src/
│   ├── components/            # Reusable UI components
│   ├── views/                 # Page-level components
│   ├── stores/                # Pinia state management
│   ├── services/              # API client services
│   ├── router/                # Vue Router configuration
│   ├── types/                 # TypeScript interfaces
│   └── config/                # App configuration

Key Architectural Patterns

  • Clean Architecture - Dependency inversion with core domain independence
  • Vertical Slice Architecture - Feature-based organization within layers
  • CQRS - Command Query Responsibility Segregation via Wolverine
  • REPR - Request-Endpoint-Response for API design
  • Domain Events - Event-driven workflows for certificate automation
  • Repository Pattern - Data access abstraction via IDataAccess

⚙️ Configuration

OAuth Provider Setup

The application requires external authentication providers (Google and/or Microsoft) to be configured before first use.

Google OAuth Setup

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Enable the Google+ API
  4. Go to APIs & Services > Credentials and create OAuth 2.0 credentials
  5. Add authorized redirect URI: <backend-url>/signin-google (e.g., http://localhost:5000/signin-google)
  6. Save the Client ID and Client Secret
  7. Add them to appsettings.json under Authentication:Google

Microsoft OAuth Setup

  1. Go to Azure Portal
  2. Navigate to Azure Active Directory > App registrations
  3. Register a new application
  4. Under Authentication, add redirect URI: <backend-url>/signin-microsoft (e.g., http://localhost:5000/signin-microsoft)
  5. Go to Certificates & secrets and generate a client secret
  6. Save the Application (client) ID and the generated secret
  7. Add them to appsettings.json under Authentication:Microsoft

Note: Update redirect URIs if deploying to a different domain or port.

DigiSign Setup (Optional)

Required only if you want digitally-signed certificates (CertificateSettings:SigningProvider set to DigiSign).

  1. Go to DigiSign and create an account
  2. Navigate to Settings and create a new API key
  3. Configure these scopes:
    • Envelopes - read
    • Envelopes - edit
  4. Save the Access Key and Secret Key
  5. Register a webhook for Envelope completed event with URL: <backend-url>/api/webhooks/digisign-envelope-completed
  6. Add credentials to appsettings.json under DigiSign

If you don't need digital signatures, set CertificateSettings:SigningProvider to None and PDFs will be generated without signatures.

Backend Configuration

Edit be/TrainingApp.Web/appsettings.json and set the keys below. Each section shows a short JSON example followed by a concise explanation.

  "ConnectionStrings": {
    "DefaultConnection": "Data Source=data/sqlite.db"
  }
  • ConnectionStrings:DefaultConnection — EF Core connection string. Default local uses SQLite (data/sqlite.db). For SQL Server/LocalDB or PostgreSQL replace with the provider-specific connection string and ensure the provider packages are installed.
  "Jwt": {
    "Issuer": "<backend-url>",
    "Audience": "<backend-url>",
    "Key": "your-secure-key-min-32-characters"
  }
  • Jwt:Issuer — issuer claim for JWTs; typically your backend base URL (include scheme, https://...).
  • Jwt:Audience — expected audience claim; commonly the same as Issuer for this app.
  • Jwt:Key — symmetric signing key for JWTs. Use a cryptographically-secure random string (min 32 chars). Provide via environment variables or a secret manager in production — never commit to source control.
  "Authentication": {
    "AllowedProviders": ["Google", "Microsoft"],
    "Google": { "ClientId": "", "ClientSecret": "" },
    "Microsoft": { "ClientId": "", "ClientSecret": "" }
  }
  • Authentication:AllowedProviders — array of enabled external providers (Google, Microsoft).
  • Authentication:Google:ClientId / ClientSecret — Google OAuth credentials; set redirect URI to <backend-url>/signin-google in Google Cloud Console.
  • Authentication:Microsoft:ClientId / ClientSecret — Azure AD credentials; set redirect URI to <backend-url>/signin-microsoft in Azure App Registration.
  "Application": {
    "SystemUser": { "Email": "system@local" }
  },
  "DefaultAdmin": { "Email": "admin@local" }
  • Application:SystemUser:Email — optional system/service account email used for automated operations and audit entries.
  • DefaultAdmin:Email — email for the seeded administrator created on first run (idempotent seeding).
  "Storage": { "LocalPath": "data/certificates" }
  • Storage:LocalPath — filesystem path (relative to app root) for generated certificates and artifacts. Persist this path in Docker via a volume and ensure write permissions.
  "CertificateBranding": {
    "CompanyName": "Your Company",
    "HeaderText": "CERTIFICATE OF COMPLETION",
    "FooterText": "This certificate verifies successful completion of the training course",
    "SignatoryName": "",
    "SignatoryTitle": ""
  },
  "CertificateSettings": { "SigningProvider": "None" }
  • CertificateBranding.* — text fields applied to generated PDFs.
  • CertificateSettings:SigningProviderNone or DigiSign. If DigiSign is selected, configure DigiSign values below.
  "DigiSign": {
    "ApiBaseUrl": "https://api.digisign.org",
    "AccessKey": "",
    "SecretKey": "",
    "SignerName": "",
    "SignerEmail": "",
    "SenderName": "",
    "SenderEmail": ""
  }
  • DigiSign:* — DigiSign API credentials and signer/sender metadata. Keep AccessKey and SecretKey secret and provide via env vars.
  "Frontend": {
    "AllowedOrigins": ["<frontend-url>"],
    "DefaultRedirectUrl": "/auth-callback"
  }
  • Frontend:AllowedOrigins — CORS origins for the SPA; include local dev URL(s), production domain(s).
  • Frontend:DefaultRedirectUrl — SPA route that handles OAuth callback redirect.

Setting values via environment variables

  • Use environment variables to override appsettings.json. Replace : with __ for Docker/Compose. Examples:
    • ConnectionStrings__ApplicationDbContextConnection
    • Jwt__Key
    • Authentication__Google__ClientId

Docker and security notes

  • Mount a persistent Docker volume for Storage:LocalPath and the database file if using SQLite.
  • Provide secrets (Jwt:Key, OAuth client secrets, DigiSign keys) through environment variables or a secrets manager; do not commit them to the repo.
  • Enforce HTTPS and set Jwt:Issuer/Audience to the production https:// URL.

If you'd like I can generate a commented appsettings.Development.json with placeholders and a docker-compose environment snippet that shows exact env var names. Reply yes to create those files.

Frontend Configuration

Edit fe/.env:

VITE_API_BASE_URL=<backend-url> (e.g., http://localhost:5000)

For production deployment, update docker-compose.yml to set the correct API URL.

🚢 Deployment

Docker Deployment

See DEPLOYMENT.md for comprehensive deployment guide including:

  • Docker Compose setup
  • Environment configuration
  • Database initialization
  • Certificate signing setup
  • Production considerations
  • Troubleshooting

Production Checklist

  • Change JWT secret key
  • Configure OAuth providers
  • Set up HTTPS with reverse proxy
  • Configure DigiSign (if using digital signatures)
  • Set up automated backups
  • Configure logging and monitoring
  • Review CORS settings

📚 API Documentation

The backend automatically generates OpenAPI documentation accessible at /swagger/index.html when running in development mode.

Key API Endpoints

  • Authentication: /api/auth/* - OAuth and JWT token management
  • Users: /api/users/* - User CRUD operations
  • Courses: /api/courses/* - Course management
  • Tests: /api/tests/* - Test and question management
  • Enrollments: /api/enrollments/* - User enrollment
  • Attempts: /api/attempts/* - Test taking and grading
  • Certificates: /api/certificates/* - Certificate download
  • Groups: /api/groups/* - Group management

All endpoints require JWT authentication except OAuth callbacks and webhooks.

🧪 Testing

Backend Integration Tests

cd be
dotnet test
dotnet format

The test suite includes:

  • API endpoint testing
  • Authorization rule validation
  • Database operations
  • Domain event workflows

Tests use in-memory SQLite database for isolation.

Frontend Linting

cd fe
npm run lint          # ESLint
npm run type-check    # TypeScript
npm run format        # Prettier

🤝 Contributing

This is an open-source project. Contributions are welcome!

Development Workflow

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Run tests and linters
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Merge Request

Code Standards

  • Backend: Follow C# coding conventions, use Clean Architecture principles
  • Frontend: Use TypeScript, follow Vue 3 Composition API patterns
  • Write integration tests for new API endpoints

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🏷️ Version

Current Version: 1.0.0

Release Notes

1.0.0 (Initial Release)

  • Core LMS functionality
  • OAuth authentication (Google, Microsoft)
  • Rich text content editor
  • Multi-type question support
  • Automated and manual grading
  • PDF certificate generation
  • DigiSign integration for digital signatures
  • Docker deployment
  • Comprehensive integration tests

💬 Support

For issues, questions, or feature requests, please open an issue on the GitLab repository.

For deployment assistance, see DEPLOYMENT.md.

🙏 Acknowledgments

FIT CTU logo

This software was developed with the support of the Faculty of Information Technology, Czech Technical University in Prague. For more information, visit fit.cvut.cz.

About

A modern, open-source .NET and Vue.JS Learning Management System (LMS), that enables organizations to deliver corporate training, track employee progress, and issue digitally-signed certificates

Resources

License

Stars

Watchers

Forks