4 Technical Handout
mixel edited this page 2025-06-23 11:12:01 +02:00

Technical Handout: PGG (Peer Group Grading) API

1. Why Do We Want to Implement APIs?

Based on our implementation, we chose to build APIs for the following reasons:

  • Separation of Frontend and Backend: Our API provides a clean interface between the Web UI and the Rust backend, allowing independent development and deployment
  • Security Layer: We implemented session-based authentication with Redis session storage and password hashing using Argon2
  • Modularity: Our controller-based architecture (auth.rs, user.rs, project.rs, group.rs) allows for clean code organization
  • Type Safety: Using Rust with Actix-web and Sea-ORM provides compile-time guarantees and prevents common runtime errors
  • Scalability: The stateless API design with external session storage (Redis) allows horizontal scaling

2. Who Is the User?

Primary Users:

  • Teachers: Educational professionals managing peer group evaluations
    • Need to create and manage projects
    • Assign students to groups
    • Track and evaluate peer assessments

System Users:

  • Administrators: Can create user accounts with secure passwords
  • Students (Future): Will be able to view their group assignments and submit peer evaluations

3. What User Problems Are We Solving and What Benefits Are We Creating?

Problems Solved:

  • Manual Group Management: Teachers currently track peer groups in spreadsheets or paper
  • Security Issues: No secure way to store sensitive grading data and user credentials
  • Data Integrity: Risk of data loss or corruption with manual systems
  • Access Control: No way to restrict access to sensitive grading information

Benefits Created:

  • Automated Workflows: CRUD operations for projects, groups, and users
  • Secure Authentication: Session-based auth with Redis and Argon2 password hashing
  • Data Persistence: PostgreSQL database with migrations using Sea-ORM
  • Audit Trail: All changes tracked through database transactions
  • RESTful Interface: Standard HTTP methods for easy integration

4. What Concrete Outcomes Do We Want to Achieve?

Implemented Features:

  • User Management: Create, read, update, delete users with secure password storage
  • Authentication: Login/logout with session management
  • Project Management: Full CRUD for projects
  • Database Migrations: Automated schema management
  • API Documentation: OpenAPI/Swagger UI integration
  • Testing Infrastructure: Unit and integration tests

Technical Achievements:

  • Response Times: Fast API responses using Actix-web
  • Security: Argon2 for password hashing, session-based authentication
  • Database Integrity: Foreign key constraints and transactions
  • Error Handling: Comprehensive error types with proper HTTP status codes

5. How Do We Plan to Execute the API Program?

Current Technology Stack:

# From Cargo.toml
- Language: Rust (Edition 2024)
- Web Framework: Actix-web 4
- ORM: Sea-ORM with PostgreSQL
- Session Storage: Redis with actix-session
- Authentication: Argon2 for password hashing
- API Documentation: utoipa with Swagger UI
- Testing: Built-in Rust testing with testcontainers

Deployment Strategy:

  • Static Binary: Compiled as a statically linked Rust binary
  • Docker Support: backend.Dockerfile for containerized deployment

Database Schema:

// Entities from our Sea-ORM models
- User (id, username, name)
- LocalAuth (id, hash, password_change_required)
- Project (id, name)
- Group (id, project_id, name)
- UserGroupProject (user_id, group_id, project_id) // Junction table

6. What Is the Architectural Style and Why Did We Choose It?

REST (Representational State Transfer)

We implemented a RESTful API as evidenced by our route structure:

// From controller.rs
cfg.service(web::scope("/project").configure(project::setup))
   .service(web::scope("/group").configure(group::setup))
   .service(web::scope("/user").configure(user::setup))
   .service(web::scope("/auth").configure(auth::setup))

Why REST?

  • Simplicity: Standard HTTP verbs (GET, POST, PUT, DELETE) as seen in our controllers
  • Statelessness: Sessions stored in Redis, not in application memory
  • Tool Support: Easy integration with Swagger UI for API documentation
  • Industry Standard: Familiar to developers, extensive ecosystem support

7. Implemented API Endpoints

Authentication (/api/v1/auth)

POST /api/v1/auth/login    // Login with username/password
POST /api/v1/auth/logout   // Logout and clear session

Users (/api/v1/user)

GET    /api/v1/user         // Get all users
GET    /api/v1/user/{id}    // Get specific user
POST   /api/v1/user         // Create user (with password)
DELETE /api/v1/user/{id}    // Delete user

Projects (/api/v1/project)

GET    /api/v1/project      // Get all projects
GET    /api/v1/project/{id} // Get specific project
POST   /api/v1/project      // Create project
PUT    /api/v1/project/{id} // Update project
DELETE /api/v1/project/{id} // Delete project

Groups (/api/v1/group) - Stubs implemented

GET    /api/v1/group              // Not implemented (returns 501)
GET    /api/v1/group/{project}    // Not implemented
POST   /api/v1/group              // Not implemented
PUT    /api/v1/group              // Not implemented
DELETE /api/v1/group/{id}         // Not implemented

8. Security Implementation

Password Security:

// From user.rs
- Argon2 hashing with salt generation
- Password validation (minimum 8 characters)
- Secure password verification on login

Session Management:

// From main.rs
- Redis-based sessions with actix-session
- Secure cookies (HTTPS in production)
- Session purging on logout

Error Handling:

// From error.rs
pub enum ApiError {
    Database(#[from] sea_orm::DbErr),
    Unauthorized,
    NotFound,
    BadRequest(String),
    ValidationError(#[from] validator::ValidationErrors),
    Argon2Error(String),
    SessionInsertError(#[from] actix_session::SessionInsertError),
    AlreadyLoggedIn,
}

9. Testing Strategy

Unit Tests

Located in individual modules, for example:

// From main.rs tests
#[test]
fn build_database_url_with_defaults() { ... }
#[test]
fn build_database_url_with_all_vars() { ... }

Integration Tests

Located in crates/backend/tests/:

// From integration_tests.rs
#[actix_web::test]
async fn test_ok() { ... }

// From endpoints/user.rs
#[actix_web::test]
async fn test_create_user() { ... }

Test Infrastructure:

  • Testcontainers: Automated PostgreSQL and Redis containers for testing
  • Test Helpers: Reusable test app setup with create_test_app! macro
  • Database Migrations: Automatic migration in test setup

10. Working Examples

Login Request:

// POST /api/v1/auth/login
{
  "username": "teacher1",
  "password": "securepassword"
}
// Response: 200 OK
{
  "message": "Login successful"
}

Create User:

// POST /api/v1/user
{
  "username": "newteacher",
  "name": "New Teacher",
  "password": "password123"
}
// Response: 200 OK
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "username": "newteacher",
  "name": "New Teacher"
}

Create Project:

// POST /api/v1/project
{
  "name": "Math Group Project 2024"
}
// Response: 200 OK
{
  "id": "660e8400-e29b-41d4-a716-446655440001",
  "name": "Math Group Project 2024"
}

11. Future Enhancements

Planned Features (from stubs):

  • Group management implementation
  • Class management system
  • Template system for reusable configurations
  • LDAP authentication integration (code exists in crates/ldap/)

Potential Improvements:

  • WebSocket support for real-time updates
  • Batch operations for bulk user/group creation
  • Export functionality for grades
  • Email notifications for group assignments

12. Conclusion

The PGG API successfully provides a secure, type-safe foundation for peer group grading management. Using Rust with Actix-web ensures high performance and reliability, while Sea-ORM provides a robust database abstraction layer. The modular architecture allows for easy extension, and the comprehensive test suite ensures reliability. With session-based authentication and proper error handling, the API is ready for production use in educational environments.