Skip to content

Junaid-Ashraf-56/Submission_portal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

74 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“š Assignment Portal

A production-grade university assignment submission system

Spring Boot Java PostgreSQL Docker License

Live Demo Β· Report Bug Β· Request Feature

Assignment Portal Banner


πŸ“‹ Table of Contents


🌟 Overview

Assignment Portal is a full-stack web application built for university environments. It enables a structured workflow between Admins, Class Representatives (CRs), and Students β€” covering assignment creation, file submission, deadline management, and real-time class communication.

Built as a first production project, deployed at assignmentportal.live on DigitalOcean with Docker, Nginx, and Let's Encrypt SSL.


✨ Features

πŸ” Authentication & Security

  • Email-based OTP verification before account activation
  • Role-based access control (ROLE_ADMIN, ROLE_CR, ROLE_STUDENT)
  • PENDING β†’ ACTIVE account approval workflow
  • Forgot password via OTP with 1-minute expiry
  • Spring Security session management with CSRF protection
  • Async OTP email delivery for zero-latency redirects

πŸ‘¨β€πŸ’Ό Admin

  • Approve / reject / delete CR registration requests
  • View all CRs with expandable student lists per section
  • Dashboard stats β€” total CRs, students, pending requests
  • Email-based actions (no userId exposure)

πŸŽ“ Class Representative (CR)

  • Register with OTP verification β†’ admin approval flow
  • Create assignments with subject code, type (LAB/THEORY), and deadline
  • Track submission progress per assignment with progress bar
  • Download all student submissions as ZIP
  • Extend assignment deadlines
  • Edit profile β€” section/semester changes cascade to all linked students
  • Real-time class chat via WebSocket

πŸ§‘β€πŸŽ“ Student

  • View active assignments from their CR
  • Submit assignments (file upload to Supabase Storage)
  • Track submission status per assignment
  • Real-time class chat with classmates

πŸ’¬ Real-time Class Chat

  • WebSocket (STOMP over SockJS)
  • Auto-scoped chat rooms: {admission}-{program}-{section}-{semester}
  • Messages persisted to PostgreSQL
  • Loads last 50 messages on panel open
  • Unread message badge when panel is closed
  • Isolated β€” only classmates in the same room

πŸ›  Tech Stack

Layer Technology
Language Java 17
Framework Spring Boot 3.5.6
Security Spring Security 6
ORM Spring Data JPA + Hibernate 6
Database PostgreSQL 15
File Storage Supabase Storage
Real-time WebSocket (STOMP + SockJS)
Templating Thymeleaf
Email Spring Mail (Gmail SMTP, async)
Frontend Bootstrap 5.3, Bootstrap Icons
Containerization Docker + Docker Compose
Reverse Proxy Nginx
SSL Let's Encrypt (Certbot)
Hosting DigitalOcean Droplet
Build Maven

πŸ— Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Internet                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚ HTTPS :443
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               Nginx (Reverse Proxy)          β”‚
β”‚         SSL Termination + WS Proxy           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚ HTTP :8080
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Spring Boot Application              β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  MVC Layer  β”‚  β”‚  WebSocket (STOMP)   β”‚  β”‚
β”‚  β”‚  Thymeleaf  β”‚  β”‚  /topic/chat/{room}  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚         β”‚                    β”‚               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚         Service + Repository Layer     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                       β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                             β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  PostgreSQL 15  β”‚          β”‚   Supabase Storage  β”‚
β”‚  (Docker)       β”‚          β”‚   (File Uploads)    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸš€ Getting Started

Prerequisites

  • Java 17+
  • Maven 3.8+
  • Docker + Docker Compose
  • PostgreSQL 15 (or use Docker)

Local Development

1. Clone the repository

git clone https://github.com/Junaid-Ashraf-56/Submission_portal.git
cd Submission_portal

2. Create src/main/resources/application.properties

spring.application.name=submission_portal

spring.datasource.url=${SPRING_DATASOURCE_URL}
spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.open-in-view=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

supabase.url=${SUPABASE_URL}
supabase.key=${SUPABASE_KEY}
supabase.bucket.name=${SUPABASE_BUCKET_NAME}

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.http.client.HttpClientAutoConfiguration

spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=${MAIL_USERNAME}
spring.mail.password=${MAIL_PASSWORD}
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true

otp.expiry.minutes=1

3. Create docker-compose.yml with your environment variables (see Environment Variables)

4. Build and run

mvn clean package -DskipTests
docker compose up --build

5. Open http://localhost:8080


πŸ”‘ Environment Variables

Variable Description
SPRING_DATASOURCE_URL jdbc:postgresql://db:5432/submission_portal
SPRING_DATASOURCE_USERNAME PostgreSQL username
SPRING_DATASOURCE_PASSWORD PostgreSQL password
SUPABASE_URL Supabase project storage URL
SUPABASE_KEY Supabase service role key
SUPABASE_BUCKET_NAME Storage bucket name
MAIL_USERNAME Gmail address for OTP emails
MAIL_PASSWORD Gmail app password (not account password)

⚠️ Never commit application.properties or docker-compose.yml with real credentials. Both are in .gitignore.


🌐 Deployment

This project is deployed on DigitalOcean using Docker + Nginx + Let's Encrypt.

Stack

assignmentportal.live
      ↓ DNS (Namecheap A Record)
DigitalOcean Droplet (Ubuntu 22.04)
      ↓ Nginx (port 443 β†’ 8080, WebSocket proxy)
Docker Compose
      β”œβ”€β”€ submission_portal_app (Spring Boot)
      └── submission_portal_db  (PostgreSQL 15)

Update Production

# SSH into server
ssh root@YOUR_DROPLET_IP

# Pull latest code
cd /opt/Submission_portal
git pull origin main

# Rebuild and restart
mvn clean package -DskipTests
docker compose down
docker compose up --build -d

πŸ—Ί API Routes

Method Route Role Description
GET / Public Landing page
GET/POST /auth/login Public Login
GET/POST /auth/register Public CR registration
GET/POST /auth/verify-otp Public OTP verification
GET /cr/dashboard CR CR dashboard
GET /cr/manage-students CR Student management
POST /cr/create-assignment CR Create assignment
GET /cr/assignments/{id}/submissions CR View submissions
GET /cr/assignments/{id}/download-all CR Download ZIP
GET /student/dashboard Student Student dashboard
POST /student/assignments/{id}/submit Student Submit assignment
GET /admin/panel Admin Admin dashboard
POST /admin/cr/approve Admin Approve CR
POST /admin/cr/reject Admin Reject CR
GET /chat/{roomId}/history Authenticated Load chat history
WS /ws Authenticated WebSocket endpoint

πŸ—„ Database Schema

users
β”œβ”€β”€ id (PK)
β”œβ”€β”€ email (unique)
β”œβ”€β”€ password (BCrypt)
β”œβ”€β”€ role (ROLE_ADMIN / ROLE_CR / ROLE_STUDENT)
└── status (PENDING / ACTIVE)

students
β”œβ”€β”€ id (PK)
β”œβ”€β”€ user_id (FK β†’ users)
β”œβ”€β”€ name, roll_no, gender, phone_number
β”œβ”€β”€ section, program, semester, admission
└── university

assignments
β”œβ”€β”€ assignment_id (PK)
β”œβ”€β”€ created_by (FK β†’ students)
β”œβ”€β”€ subject_title, subject_code
β”œβ”€β”€ assignment_type (LAB / THEORY)
β”œβ”€β”€ description
└── end_time

submissions
β”œβ”€β”€ id (PK)
β”œβ”€β”€ assignment_id (FK β†’ assignments)
β”œβ”€β”€ student_id (FK β†’ students)
β”œβ”€β”€ file_url (Supabase)
└── submitted_at

chat_messages
β”œβ”€β”€ id (PK)
β”œβ”€β”€ room_id (admission-program-section-semester)
β”œβ”€β”€ sender_name
β”œβ”€β”€ content
└── sent_at

πŸ“ Project Structure

src/main/java/com/web/submission_portal/
β”œβ”€β”€ config/
β”‚   β”œβ”€β”€ SecurityConfig.java
β”‚   └── WebSocketConfig.java
β”œβ”€β”€ controller/
β”‚   β”œβ”€β”€ AdminController.java
β”‚   β”œβ”€β”€ AuthController.java
β”‚   β”œβ”€β”€ ChatController.java
β”‚   β”œβ”€β”€ CRController.java
β”‚   β”œβ”€β”€ RegistrationController.java
β”‚   └── StudentController.java
β”œβ”€β”€ entity/
β”‚   β”œβ”€β”€ Assignment.java
β”‚   β”œβ”€β”€ ChatMessage.java
β”‚   β”œβ”€β”€ Student.java
β”‚   β”œβ”€β”€ Submission.java
β”‚   └── User.java
β”œβ”€β”€ repository/
β”‚   β”œβ”€β”€ ChatMessageRepository.java
β”‚   β”œβ”€β”€ StudentRepository.java
β”‚   β”œβ”€β”€ SubmissionRepository.java
β”‚   └── UserRepository.java
└── service/
    β”œβ”€β”€ EmailService.java          ← @Async OTP delivery
    β”œβ”€β”€ OTPGeneratorService.java
    β”œβ”€β”€ PasswordResetService.java
    └── StudentService.java

src/main/resources/
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ admin/, auth/, cr/, student/
└── static/
    β”œβ”€β”€ css/  (theme.css, cr-dashboard.css, student-dashboard.css)
    └── js/   (cr-chat.js, student-chat.js)

🀝 Contributing

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

πŸ‘€ Author

Junaid Ashraf


⭐ Star this repo if you found it helpful!

Releases

No releases published

Packages

 
 
 

Contributors