Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

School Management API

A RESTful API built with .NET 9.0 for managing students, teachers, courses, classes, attendance, assignments, and grading with role-based access control.

Features

Core Features

  • Complete JWT Authentication with token revocation and refresh token rotation
  • Database-Validated Refresh Tokens with automatic expiration and revocation
  • Redis Token Blacklist for immediate access token revocation
  • Role-Based Authorization (Admin, Teacher, Student) with middleware enforcement
  • Complete CRUD Operations for managing educational resources
  • Pagination & Filtering for large datasets (Classes, Students, Assignments)
  • Soft Delete for Users and Courses (preserves historical data)
  • File Upload support for assignment submissions
  • Redis Caching for improved performance
  • Attendance Tracking with multiple status types
  • Assignment Management with submission and grading capabilities
  • Notification System for broadcasting messages
  • Comprehensive Logging using Serilog
  • API Documentation with Swagger/OpenAPI
  • Data Validation using FluentValidation

Security Features

  • Access tokens with JTI claims (60-minute TTL)
  • Refresh tokens stored in database (7-day TTL)
  • Token blacklist with automatic cleanup (Redis TTL)
  • Token validation middleware
  • All tokens revoked on logout
  • Password hashing with BCrypt
  • SQL injection prevention

Tech Stack

  • .NET Core 9.0 - Backend framework
  • SQL Server 2022 - Database
  • Redis 7-Alpine - Caching & token blacklist
  • Entity Framework Core 9.0 - ORM
  • JWT Bearer - Authentication
  • StackExchange.Redis - Redis client
  • AutoMapper - Object mapping
  • FluentValidation - Input validation
  • Serilog - Logging
  • Swagger/OpenAPI - API documentation
  • BCrypt.NET - Password hashing
  • Docker - Containerization

Getting Started

Prerequisites

Setup Instructions

Option 1: Run with Docker (Recommended)

  1. Clone the repository:

    git clone <repository-url>
    cd SchoolManagementAPI
  2. Build and start the containers:

    docker-compose up --build
  3. The API will be available at:

    • HTTP: http://localhost:8080
    • Swagger UI: http://localhost:8080
  4. Run database migrations:

    dotnet ef database update

Option 2: Run Locally

  1. Clone the repository:

    git clone <repository-url>
    cd SchoolManagementAPI
  2. Update the connection string in appsettings.json:

    "ConnectionStrings": {
      "DefaultConnection": "Server=localhost;Database=SchoolManagementDb;User Id=sa;Password=YourPassword;TrustServerCertificate=True"
    }
  3. Run database migrations:

    dotnet ef database update
  4. Run the application:

    dotnet run
  5. The API will be available at:

    • HTTP: http://localhost:5000
    • HTTPS: https://localhost:5001
    • Swagger UI: http://localhost:5000

Database Migration Commands

# Create a new migration
dotnet ef migrations add MigrationName

# Apply migrations to database
dotnet ef database update

# Remove last migration
dotnet ef migrations remove

# View migration SQL script
dotnet ef migrations script

API Endpoints

Authentication

Method Endpoint Description Access
POST /api/auth/register Register new user Public
POST /api/auth/login Login and get JWT token Public
POST /api/auth/refresh-token Refresh access token (validates against DB) Public
POST /api/auth/logout Logout and revoke all tokens Authenticated

Authentication Flow:

  • Login returns access token (60min) + refresh token (7 days)
  • Access token added to requests: Authorization: Bearer {token}
  • When access token expires, use refresh token to get new tokens
  • Logout revokes all tokens (access token blacklisted in Redis, refresh tokens revoked in DB)
  • Tokens validated against database and Redis blacklist

Admin Endpoints

Method Endpoint Description Access
GET /api/admin/departments Get all departments Admin
GET /api/admin/departments/{id} Get department by ID Admin
POST /api/admin/departments Create department Admin
PUT /api/admin/departments/{id} Update department Admin
DELETE /api/admin/departments/{id} Delete department Admin
GET /api/admin/courses Get all courses Admin
GET /api/admin/courses/{id} Get course by ID Admin
POST /api/admin/courses Create course Admin
PUT /api/admin/courses/{id} Update course Admin
DELETE /api/admin/courses/{id} Delete course Admin

Teacher Endpoints

Method Endpoint Description Access
GET /api/teacher/classes Get teacher's classes Teacher
POST /api/teacher/classes Create new class Teacher
PUT /api/teacher/classes/{id} Update class Teacher
POST /api/teacher/classes/{classId}/enroll Enroll student in class Teacher
POST /api/teacher/attendance Mark attendance Teacher
GET /api/teacher/attendance/{classId} Get class attendance Teacher
POST /api/teacher/assignments Create assignment Teacher
GET /api/teacher/assignments/{classId} Get class assignments Teacher
POST /api/teacher/assignments/{id}/grade Grade submission Teacher

Student Endpoints

Method Endpoint Description Access
GET /api/student/classes Get enrolled classes Student
GET /api/student/attendance Get my attendance Student
GET /api/student/assignments Get my assignments Student
POST /api/student/assignments/{id}/submit Submit assignment Student
GET /api/student/grades Get my grades Student
GET /api/student/notifications Get notifications Student

Sample API Requests

1. Register a New User

POST /api/auth/register
Content-Type: application/json

{
  "name": "John Doe",
  "email": "john.doe@school.com",
  "password": "Password123",
  "role": "Teacher"
}

Response:

{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refreshToken": "base64encodedtoken...",
  "userId": 1,
  "name": "John Doe",
  "email": "john.doe@school.com",
  "role": "Teacher"
}

2. Login

POST /api/auth/login
Content-Type: application/json

{
  "email": "john.doe@school.com",
  "password": "Password123"
}

3. Create Department (Admin)

POST /api/admin/departments
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "name": "Computer Science",
  "description": "Department of Computer Science and Engineering",
  "headOfDepartmentId": 1
}

4. Create Course (Admin)

POST /api/admin/courses
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "name": "Introduction to Programming",
  "code": "CS101",
  "description": "Fundamentals of computer programming",
  "departmentId": 1,
  "credits": 3
}

5. Create Class (Teacher)

POST /api/teacher/classes
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "name": "CS101-Fall2024-Section1",
  "courseId": 1,
  "teacherId": 1,
  "semester": "Fall 2024",
  "startDate": "2024-09-01T00:00:00Z",
  "endDate": "2024-12-15T00:00:00Z"
}

6. Mark Attendance (Teacher)

POST /api/teacher/attendance
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "classId": 1,
  "studentId": 5,
  "date": "2024-11-14T00:00:00Z",
  "status": "Present"
}

7. Create Assignment (Teacher)

POST /api/teacher/assignments
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "classId": 1,
  "title": "Programming Assignment 1",
  "description": "Implement a basic calculator",
  "dueDate": "2024-11-30T23:59:59Z"
}

8. Submit Assignment (Student)

POST /api/student/assignments/1/submit
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "assignmentId": 1,
  "fileUrl": "https://storage.example.com/submissions/student5/assignment1.zip"
}

9. Grade Submission (Teacher)

POST /api/teacher/assignments/1/grade
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
  "grade": 95.5,
  "remarks": "Excellent work! Well-structured code."
}

Configuration

appsettings.json

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=sqlserver;Database=SchoolManagementDb;User Id=sa;Password=YourStrong@Passw0rd;TrustServerCertificate=True",
    "RedisConnection": "redis:6379"
  },
  "JwtSettings": {
    "SecretKey": "YourSecretKeyHere-MustBeLongEnough",
    "Issuer": "SchoolManagementAPI",
    "Audience": "SchoolManagementClient",
    "ExpiryMinutes": 60,
    "RefreshTokenExpiryDays": 7
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "Microsoft.AspNetCore": "Warning"
      }
    }
  }
}

Key Configuration:

  • ExpiryMinutes: Access token lifetime (default: 60 minutes)
  • RefreshTokenExpiryDays: Refresh token lifetime (default: 7 days)
  • RedisConnection: Redis server for caching and token blacklist
  • SecretKey: JWT signing key (must be at least 32 characters)

Business Rules & Validations

User Registration

  • Email must be unique and valid format
  • Password must be at least 6 characters with uppercase, lowercase, and number
  • Role must be Admin, Teacher, or Student

Departments

  • Department names must be unique
  • Head of Department must be a valid Teacher
  • Cannot delete department with associated courses

Courses

  • Course codes must be unique per department
  • Credits must be between 1 and 10
  • Cannot delete course with associated classes

Classes

  • Only teachers can create and manage classes
  • Students can only be enrolled by teachers
  • Cannot enroll same student twice in same class

Attendance

  • Only assigned teacher can mark attendance
  • Student must be enrolled in class
  • Status must be: Present, Absent, or Late
  • One attendance record per student per class per date

Assignments

  • Due date must be in the future
  • Only assigned teacher can create assignments
  • Only enrolled students can submit assignments
  • Only assigned teacher can grade submissions

Security Features

Authentication & Authorization

  • JWT Access Tokens: 60-minute lifetime with JTI claims for unique identification
  • Refresh Tokens: 7-day lifetime, stored and validated against database
  • Token Blacklist: Redis-based blacklist for immediate access token revocation
  • Token Validation Middleware: Automatic checking of blacklisted tokens on every request
  • Token Rotation: New refresh token issued on each refresh, old one revoked
  • Logout: All user tokens revoked (access token blacklisted, refresh tokens marked as revoked in DB)
  • Role-Based Authorization: Granular access control (Admin, Teacher, Student)
  • User Status Validation: Account deactivation prevents token usage

Data Security

  • Password Hashing: BCrypt with salt for secure password storage
  • Input Validation: FluentValidation for all DTOs
  • SQL Injection Prevention: Entity Framework parameterized queries
  • Soft Delete: Historical data preservation with IsActive flag
  • CORS Configuration: Configurable cross-origin resource sharing

Token Management

  • Access tokens include: userId, name, email, role, JTI (JWT ID)
  • Refresh tokens validated on every use: exists in DB, not expired, not revoked, user active
  • Automatic cleanup: Redis TTL ensures blacklisted tokens expire naturally
  • All old tokens revoked on new login for security

Logging

Logs are written to:

  • Console: All log levels in development
  • File: logs/schoolmanagement-{Date}.txt with daily rolling

Log levels:

  • Information: Application flow
  • Warning: Validation failures, business rule violations
  • Error: Exceptions and errors
  • Fatal: Application crashes

Testing

Access the Swagger UI at the root URL to test all endpoints interactively:

Authentication in Swagger

  1. Click the "Authorize" button
  2. Enter: Bearer <your-jwt-token>
  3. Click "Authorize"
  4. All subsequent requests will include the token

Testing Authentication Flow

Complete JWT Auth Test

1. Register/Login:

curl -X POST http://localhost:8080/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"test@example.com","password":"Password123"}'

Save both token and refreshToken from response.

2. Use Access Token:

TOKEN="your-access-token"
curl -X GET http://localhost:8080/api/student/classes \
  -H "Authorization: Bearer $TOKEN"

Expected: Success (200 OK)

3. Refresh Token:

REFRESH_TOKEN="your-refresh-token"
curl -X POST http://localhost:8080/api/auth/refresh-token \
  -H "Content-Type: application/json" \
  -d "{\"refreshToken\":\"$REFRESH_TOKEN\"}"

Expected: New tokens returned. Old refresh token is now revoked.

4. Logout:

curl -X POST http://localhost:8080/api/auth/logout \
  -H "Authorization: Bearer $TOKEN"

Expected: Success message

5. Verify Token Revoked:

curl -X GET http://localhost:8080/api/student/classes \
  -H "Authorization: Bearer $TOKEN"

Expected: 401 Unauthorized - "Token has been revoked"

6. Verify Refresh Token Revoked:

curl -X POST http://localhost:8080/api/auth/refresh-token \
  -H "Content-Type: application/json" \
  -d "{\"refreshToken\":\"$REFRESH_TOKEN\"}"

Expected: 401 Unauthorized

Monitor Token State

Check Redis blacklist:

docker exec -it schoolmanagement-redis redis-cli
> KEYS SchoolManagement_blacklist:token:*
> GET SchoolManagement_blacklist:token:{JTI}
> TTL SchoolManagement_blacklist:token:{JTI}

Check database refresh tokens:

-- Active tokens
SELECT * FROM RefreshTokens WHERE IsRevoked = 0;

-- Revoked tokens
SELECT * FROM RefreshTokens WHERE IsRevoked = 1;

-- User's tokens
SELECT * FROM RefreshTokens WHERE UserId = 1;

Docker Commands

# Build and start all containers (API, SQL Server, Redis)
docker-compose up --build

# Start containers (detached)
docker-compose up -d

# Stop containers
docker-compose down

# View logs
docker-compose logs -f

# View logs for specific service
docker-compose logs -f schoolmanagementapi
docker-compose logs -f redis

# Rebuild specific service
docker-compose up --build schoolmanagementapi

# Check container status
docker-compose ps

# Access SQL Server
docker exec -it schoolmanagement-sqlserver /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P YourStrong@Passw0rd -C

# Access Redis CLI
docker exec -it schoolmanagement-redis redis-cli

# Monitor Redis (check blacklisted tokens)
docker exec -it schoolmanagement-redis redis-cli
> KEYS SchoolManagement_blacklist:token:*
> GET SchoolManagement_blacklist:token:{JTI}
> TTL SchoolManagement_blacklist:token:{JTI}

Services Running:

Troubleshooting

Database Connection Issues

  • Ensure SQL Server container is healthy: docker-compose ps
  • Check connection string in appsettings.json
  • Verify SQL Server is accepting connections

Migration Issues

  • Ensure you're in the project directory: cd SchoolManagementAPI
  • Check EF Core tools are installed: dotnet tool install --global dotnet-ef
  • Delete Migrations folder and recreate if needed

JWT Authentication Issues

"Token has been revoked" error:

  • Token was blacklisted due to logout or security event
  • Solution: Request new tokens using refresh token or login again

Refresh token not working:

  • Check if token was revoked in database (SELECT * FROM RefreshTokens WHERE Token = 'your-token')
  • Verify token not expired (ExpiryDate > GETUTCDATE())
  • Verify user account active (SELECT IsActive FROM Users WHERE Id = userId)
  • Solution: Login again to get new tokens

Token validation failing:

  • Verify token not expired (60-minute lifetime for access tokens)
  • Check Authorization header format: Bearer <token>
  • Ensure SecretKey in appsettings.json is at least 32 characters
  • Check Redis is running for blacklist validation

Redis Connection Issues

Symptoms:

  • Blacklist not working
  • "RemoveByPrefix" errors in logs
  • Cache not functioning

Solutions:

  1. Check Redis is running: docker ps | grep redis
  2. Test Redis connection: docker exec -it schoolmanagement-redis redis-cli PING
  3. Verify RedisConnection in appsettings.json: "redis:6379"
  4. Check Redis logs: docker-compose logs redis

Token Blacklist Issues

Verify blacklist is working:

# Login and get token
# Logout
# Try to use the token - should get 401

# Check Redis for blacklisted token
docker exec -it schoolmanagement-redis redis-cli
> KEYS SchoolManagement_blacklist:token:*

Clear blacklist (testing only):

docker exec -it schoolmanagement-redis redis-cli
> KEYS SchoolManagement_blacklist:token:*
> DEL SchoolManagement_blacklist:token:{JTI}
# Or clear all:
> FLUSHDB

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add amazing feature'
  4. Push to the branch: git push origin feature/amazing-feature
  5. Open a Pull Request

License

This project is licensed under the MIT License.

About

A RESTful API built with .NET 9.0 for managing students, teachers, courses, classes, attendance, assignments, and grading with role-based access control.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages