Skip to content

fortune-c/civicvote

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

27 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ—³ CivicVotes Documentation

Overview

CivicVotes is a production-ready Election & Voting Management System built with ASP.NET Core Web API. It provides comprehensive features for managing elections, candidates, and secure voting with role-based access control.

Live Demo (Frontend): civicvote-alpha.vercel.app Live Demo (Backend): https://fortune-c-p-api.onrender.com/


Table of Contents

  1. Authentication
  2. Voting Endpoints
  3. Admin Endpoints
  4. Error Handling
  5. Election State Machine
  6. Database Schema
  7. Security Features
  8. Built-in Frontend for Testing
  9. Learning Resources

πŸ–₯ Built-in Frontend for Testing

To provide a seamless experience for developers and testers, this project includes a basic, reactive frontend dashboard built with Vite, TypeScript, and Vanilla CSS.

Why use the built-in frontend?

  • No External Tools Required: Test the entire flow (Registration β†’ Login β†’ Election Creation β†’ Voting) directly in the browser without needing Postman or Swagger.
  • Role-Based Simulation: Easily switch between Voter, Candidate, and Electoral Administrator flows to verify access control logic.
  • Real-time API Interaction: Built on top of a custom api.ts service that handles JWT injection and refresh token rotation automatically.

How to Run

  1. Navigate to the frontend directory.
  2. Run npm install and then npm run dev.
  3. Open the provided local URL (typically http://localhost:5173).

πŸ” Authentication

All authenticated endpoints require a JWT Bearer token in the Authorization header:

Authorization: Bearer <your_jwt_token>

Roles

Role Description
Voter Can view elections, cast votes, view personal vote history
Electoral Administrator Can create/manage elections, candidates, view all votes
Candidate Reserved for future candidate-specific features

POST /api/auth/signup

Register a new user account.

Auth Required: No

Request Body:

Field Type Required Description
firstName string No User's first name
lastName string No User's last name
email string Yes Must be unique
password string Yes Min 10 chars, requires digit
roles string[] No Defaults to ["Voter"]

Response 201 Created:

{
  "message": "User registered successfully."
}

Error 400 Bad Request:

{
  "DuplicateUserName": ["Username 'john@example.com' is already taken."],
  "PasswordTooShort": ["Passwords must be at least 10 characters."]
}

POST /api/auth/signin

Authenticate and receive JWT + refresh token.

Auth Required: No

Request Body:

{
  "email": "john@example.com",
  "password": "SecurePass123"
}

Response 200 OK:

{
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "dGhpcyBpcyBhIHJlZnJl..."
}

Error 401 Unauthorized:

{
  "message": "Authentication failed. Invalid email or password, or account may be locked."
}

⚠️ Lockout Policy: After 5 failed login attempts, the account is locked for 15 minutes.


POST /api/auth/refresh

Refresh an expired access token.

Auth Required: No

Request Body:

{
  "accessToken": "expired.jwt.token",
  "refreshToken": "valid-refresh-token"
}

Response 200 OK:

{
  "accessToken": "new.jwt.token",
  "refreshToken": "new-refresh-token"
}

POST /api/auth/revoke

Revoke the current user's refresh token (effectively logging out).

Auth Required: Yes (any role)

Request Body: None

Response 200 OK:

{
  "message": "Refresh token revoked successfully."
}

πŸ—³ Voting Endpoints

GET /api/voting/elections

List all elections with pagination and search.

Auth Required: No

Query Parameters:

Parameter Type Default Description
PageNumber int 1 Page number
PageSize int 10 Items per page (max 50)
SearchTerm string null Search by election title
OrderBy string "title" Sort field (e.g., "title desc")

Response 200 OK:

[
  {
    "id": "c9d4c053-49b6-410c-bc78-2d54a9991870",
    "title": "Man of the Year",
    "description": "Pick your candidate for who should be the man of the year.",
    "startTime": "2024-01-01T09:00:00+00:00",
    "endTime": "2024-01-30T18:00:00+00:00",
    "status": "Ended",
    "createdBy": "80abbca8-664d-4b20-b5de-024705497d4a",
    "isCancelled": false,
    "createdAt": "2023-12-15T10:00:00+00:00"
  }
]

Response Headers:

X-Pagination: {"CurrentPage":1,"TotalPages":1,"PageSize":10,"TotalCount":2,"HasPrevious":false,"HasNext":false}

GET /api/voting/elections/{electionId}

Get a specific election by ID.

Auth Required: No


POST /api/voting/elections/{electionId}/vote ⭐

Cast a vote in an election.

Auth Required: Yes
Role Required: Voter

Request Body:

{
  "candidateId": "5f91845c-8975-470a-8994-06d997235221"
}

GET /api/voting/elections/{electionId}/results

Get detailed election results with candidate vote counts and percentages.

Auth Required: No


GET /api/voting/me/votes

Get all elections the current authenticated user has voted in.

Auth Required: Yes
Role Required: Voter


πŸ”§ Admin Endpoints

All admin endpoints require Authorization: Bearer <token> with the Electoral Administrator role.

Election Management

POST /api/admin/election/create

Create a new election (created as Draft by default).

POST /api/admin/elections/{electionId}/publish

Publish a Draft election. This makes it available for voting.

POST /api/admin/elections/{electionId}/cancel

Cancel an election.

PUT /api/admin/election/{electionId}

Update an election.

DELETE /api/admin/election/{electionId}

Soft-delete an election.


Candidate Management

POST /api/admin/elections/{electionId}/candidates

Add a candidate to an election.


⚠️ Error Handling

All errors follow the ProblemDetails (RFC 7807) format.

Status Code Meaning Common Causes
400 Bad Request Validation failure, invalid state transition
401 Unauthorized Missing/expired JWT token
403 Forbidden Insufficient role permissions
404 Not Found Election or candidate not found
409 Conflict Duplicate vote attempt
429 Too Many Requests Rate limit exceeded (60 req/min)
500 Internal Server Error Unexpected server error

πŸ“š Learning Resources & Development Experience

The development of CivicVotes has been an intensive journey of learning and applying modern web technologies. Key resources that significantly contributed to the success of this project include:

  • "Ultimate ASP.NET Core Web API" (Second Edition) by Marinko Spasojevic and Vladimir Pecanac. This comprehensive guide was instrumental in architecting the backend using modern best practices, including the Repository Pattern, Service Layer abstraction, and advanced security implementations like JWT Bearer authentication and Refresh Token rotation.
  • Official TypeScript Documentation: Leveraging TypeScript on the frontend ensured deep type safety and improved developer efficiency by catching architectural errors early in the development cycle.
  • Vite & Modern Frontend Tooling: Using Vite provided a premium development experience with blazing-fast HMR and an optimized build pipeline, which was crucial for maintaining high productivity throughout the project.

Developing this project provided invaluable experience in bridging complex architectural patterns with practical, production-ready implementation, focusing on security, performance, and user experience.


πŸ₯ Health Check

GET /health

Returns 200 OK with "Healthy" when the API is running.


About

Standard Secure Voting System - A secure and reliable voting system where eligible voters can cast votes, duplicate voting is prevented, and results are accurately tallied.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors