Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 82 additions & 108 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,82 @@
# Voting System

## Overview
The Voting System is a platform for secure and anonymous voting during meetings.
It uses a microservices architecture with the following main services:

- **Housing Association Service**:
- Retrieve housing association details
- Add and list residents
- Send meeting invitations to residents via RabbitMQ
- Generate resident/housing reports

- **Meeting Service**:
- Manage meetings and participants
- Create, start, and end meetings
- Add participants and manage meeting status
- Start question rounds
- Provide meeting details to frontend and other microservices

- **Invitation Service**:
- Handle invitation codes
- Validate participants
- Manage resident access to meetings by accepting invitations via API endpoints

- **Voting Service**:
- Create new voting sessions
- Retrieve voting details
- Update participant votes
- Track voting state
- Generate internal reports for meetings

- **Notification Service**:
- Manage and provide notifications for residents
- Expose endpoints to retrieve all notifications for a specific resident

- **Report Service**:
- Generate and provide reports for meetings after they end
- Fetch a specific report by its code (used by the Meeting microservice)
- Export reports in CSV/PDF format

The system uses RabbitMQ for communication between services.
Voters access the system via links, and admins can view and export results.

## System Design

This section covers the planned architecture, main features, and user stories for the Voting System.
It includes high-level decisions on microservices, communication patterns, and the main functionality of each service.

### Architectural Decisions
- Microservices architecture for modularity and scalability
- RabbitMQ for asynchronous communication between services
- Secure and anonymous voting flow
- Admin access for managing meetings and exporting reports

### Features
- Housing Association management
- Meeting management
- Invitations and participant validation
- Voting sessions with anonymous votes
- Notifications for residents
- Report generation and export

### User Stories
1. **Voter – Invite and Voting**
- Access voting page via link
- Cast votes for meeting questions
- One vote per question
- Confirmation of vote

2. **Admin – Voting Results**
- Secure login
- Register participants
- View and export results
- Votes remain anonymous

## Architecture Diagram

### Start Meeting Flow
![Start Meeting Flow](./docs/createmeeting.png)

### End Meeting Flow
*Diagram TBD*

## Build and Run Instructions
Option 1:
- `docker compose -f docker-compose.dev.yml up`

## Team Contributions
- **Architecture & Planning:** Mohemmed, Wisdan, Mustafa
- Discussed system design, microservices architecture, communication patterns, and feature planning

- **Backend development:**
- Mohemmed: Gateway, Meeting Service, Notification Service and Report Service
- Wisdan: Voting Service, Report Service, Notification Service
- Mustafa: Housing Association Service

- **Frontend development:** Mohemmed, Wisdan,
- Voting UI, Login UI, Meeting UI

- **Authentication:** Mohemmed

- **Docker setup & deployment:** Mohemmed, Wisdan

## Decisions and Simplifications
- MVP focuses on core voting and meeting results; proxy not included
- Added Report and Notification services beyond initial plan
- Security is implemented via Spring Boot Security
- Integrated RabbitMQ for asynchronous communication between services, exceeding initial scope
# Exam assigment - PG3402 Microservices

**Group Members:**
- Mohemmed Mossa Abdul-riza
- Wisdan Anes
- Mustafa Buga

**[See overview of the project ](docs/README.md)**

---
- [x] Instructions on how to build, start, and run the project. if you have more than one means of running the project (for example, docker
containers run locally, docker containers running on dockerhub, or running the individual
services locally), make sure you have clear instructions for each of these.


- [x] An overview of the project (you can use the one from the arbeidskrav as a basis). The
overview should accurately describe the project implementation.


- [x] A list of user stories that allow an examiner to assess the functionality developed in the
project (think of the most interesting and important scenarios that the examiner can run to see
what functionality you have implemented).


- [ ] A diagram showing the architecture of your system. This should show what services the
project contains and what type of communication they have between them (synchronous or
asynchronous).


- [x] if you collaborated with other students on a project, the README.md file should also
contain a discussion of the contributions and responsibilities of each team member.
During development, you may have to make a number of architecture decisions, assumptions
about the domain you are working with, or simplifications to how such a project would work
in reality. Document these decisions, assumptions, and simplifications in the README.md
file.

---
### Microservices specific requirements
#### Required (but not sufficient) for E

- [x] Use multiple services, that fulfill different functionality and communicate with each
other

- [x] At least two of the services communicate using synchronous communication (for
example, direct REST calls between two services).

- [x] At least two of the services communicate using asynchronous communication (for
example, using Message Queue). This will be done in accordance with event-driven
architecture, as discussed in class.

Required (but not sufficient) for D

- [x] Each service has a clear structure and functionality.

- [x] The architecture of the project is consistent with the documentation. (All services are
described in the architecture, they can be found in the project, their functionality, structure,
interactions are documented.

- [x] The project can be deployed as a group of Docker containers.

Required (but not sufficient) for C

- [x] The project uses a unique access point, that handled calls and routes them to appropriate
services – Gateway

- [x] The project uses a unique access point that, in addition to routing calls, also does load
balancing

Required (but not sufficient) for B
- [x] The project has a means of centrally controlling the health of running services – health
check

- [x] The project, and all services and necessary components, can be started via docker
compose (using the command ‘docker compose up’). The project is ready for integration into
a CI/CD pipeline.

Required (but not sufficient) for A
- [ ] The project has a means of centrally controlling configurations for the services – for
example, using Consul

- [x] The project can be deployed with multiple instances of relevant services of the
services.
110 changes: 110 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Voting System

## Overview
The Voting System is a platform for secure and anonymous voting during meetings.
It uses a microservices architecture with the following main services:

See the [Housing Service Documentation](../housing_association/README.md).

See the [Meeting Service Documentation](../meeting/README.md).

See the [Invitation Service Documentation](../invitation/README.md).

See the [Voting Service Documentation](../voting/README.md).

See the [Notification Service Documentation](../notification/README.md).

See the [Report Service Documentation](../report/README.md).

The system uses RabbitMQ for communication between services.
Voters access the system via links, and admins can view and export results.

---
## System Design

This section covers the planned architecture, main features, and user stories for the Voting System.
It includes high-level decisions on microservices, communication patterns, and the main functionality of each service.

---
### Architectural Decisions
- Microservices architecture for modularity and scalability
- RabbitMQ for asynchronous communication between services
- Secure and anonymous voting flow
- Admin access for managing meetings and exporting reports

---
### Features
- Housing Association management
- Meeting management
- Invitations and participant validation
- Voting sessions with anonymous votes
- Notifications for residents
- Report generation and export

---
### User Stories
1. **Voter – Invite and Voting**
- Access voting page via link
- Cast votes for meeting questions
- One vote per question
- Confirmation of vote

2. **Admin – Voting Results**
- Secure login
- Register participants
- View and export results
- Votes remain anonymous

---
## Architecture Diagram

### Create Meeting Flow
**Description:**
This flow illustrates how an admin creates a new meeting.

<img src="images/flow/createmeeting.png" alt="Create Meeting Flow" width="500"/>

---
### Start Meeting Flow
<img src="images/flow/startmeeting.png" alt="Start Meeting Flow" width="500"/>

---
### Start Voting Flow
<img src="images/flow/startvoting.png" alt="Start Voting Flow" width="500"/>

---
### End Meeting Flow
<img src="images/flow/endmeeting.png" alt="End Meeting Flow" width="500"/>

---
### Accept Invitation Flow
<img src="images/flow/acceptinvitation.png" alt="Accept Invitation Flow" width="500"/>

---
## Build and Run Instructions
Option 1:
- `docker compose -f docker-compose.prod.yml up`

---
## Team Contributions
- **Architecture & Planning:** Mohemmed, Wisdan, Mustafa
- Discussed system design, microservices architecture, communication patterns, and feature planning

- **Backend development:**
- Mohemmed: Gateway, Meeting Service, Notification Service and Report Service
- Wisdan: Voting Service, Report Service, Notification Service
- Mustafa: Housing Association Service

- **Frontend development:** Mohemmed, Wisdan,
- Voting UI, Login UI, Meeting UI

- **Authentication:** Mohemmed

- **Docker setup & deployment:** Mohemmed, Wisdan

---
## Decisions and Simplifications
- MVP focuses on core voting and meeting results; proxy not included
- Added Report and Notification services beyond initial plan
- Security is implemented via Spring Boot Security
- Integrated RabbitMQ for asynchronous communication between services, exceeding initial scope
Binary file removed docs/createmeeting.png
Binary file not shown.
Binary file added docs/images/database/housing_association.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/database/invitation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/database/meeting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/database/voting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/flow/acceptinvitation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/flow/createmeeting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/flow/endmeeting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/flow/startmeeting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/flow/startvoting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { BrowserRouter, Route, Routes } from "react-router-dom";
import { Login } from "./pages/Login.tsx";
import { Login } from "./login/Login.tsx";
import { Main } from "./pages/Main.tsx";
import {Phone} from "./pages/Phone.tsx";
import { Voting } from "./pages/Voting.tsx";
import {Phone} from "./phone/Phone.tsx";
import { Voting } from "./voting/Voting.tsx";
import {Error} from "./http/Error.tsx";
import {Invitation} from "./pages/Invitation.tsx";
import {Invitation} from "./invitation/Invitation.tsx";
import {useState} from "react";
import {PrivateRouter} from "./PrivateRouter.tsx";
import {Report} from "./pages/Report.tsx";
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion frontend/src/pages/Main.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Button } from "@mui/material";
import css from "./Main.module.css";
import { useState } from "react";
import { Resident } from "./Resident.tsx";
import { Resident } from "../resident/Resident.tsx";
import * as React from "react";
import {Meeting} from "../meeting/Meeting.tsx";
import type {HousingAssociationDTO} from "../App.tsx";
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import { Button } from "@mui/material";
import * as http from "../http/HttpRequest.ts";
import { ClearTokenInSession, GetTokenInSession } from "../http/TokenStorage.ts";
import css from "./Resident.module.css";
import css from "../resident/Resident.module.css";

export interface HousingAssociationDTO {
id: number;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/Report.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import css from "./Resident.module.css";
import css from "../resident/Resident.module.css";
import { useEffect, useState } from "react";
import { useSearchParams } from "react-router-dom";
import * as http from "../http/HttpRequest.ts";
Expand Down
File renamed without changes.
File renamed without changes.
10 changes: 5 additions & 5 deletions frontend/src/pages/Voting.tsx → frontend/src/voting/Voting.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {useEffect, useRef, useState} from "react";
import css from "./Voting.module.css";
import * as http from "../http/HttpRequest.ts";
import {VotingWaiting} from "../voting/VotingWaiting.tsx";
import {VotingAnswerQuestion} from "../voting/VotingAnswerQuestion.tsx";
import {VotingResult} from "../voting/VotingResult.tsx";
import {VotingWaiting} from "./VotingWaiting.tsx";
import {VotingAnswerQuestion} from "./VotingAnswerQuestion.tsx";
import {VotingResult} from "./VotingResult.tsx";

export type SelectedVote = "FOR" | "AGAINST"| "NOT_VOTED";
export type VotingState = "MEETING_NOT_STARTED" | "NOT_ONGOING" | "ONGOING_BUT_YOU_HAVE_VOTED" | "ONGOING_BUT_YOU_HAVE_NOT_VOTED" | "MEETING_ENDED";
Expand Down Expand Up @@ -53,11 +53,11 @@ export function Voting() {
<main className={css.main}>
{/* Single Card containing everything */}
<div className={css.card}>
{currentStatus === "MEETING_NOT_STARTED" && <VotingWaiting message="Meeting not started" />}
{currentStatus === "MEETING_NOT_STARTED" && <VotingWaiting displayLoading={false} message="Meeting not started" />}
{currentStatus === "NOT_ONGOING" && <VotingWaiting message="Waiting on question from admin" />}
{currentStatus === "ONGOING_BUT_YOU_HAVE_NOT_VOTED" && <VotingAnswerQuestion selectedVote={selectedVote} setSelectedVote={setSelectedVote}/>}
{currentStatus === "ONGOING_BUT_YOU_HAVE_VOTED" && <VotingWaiting message="Waiting on everyone to answer" />}
{currentStatus === "MEETING_ENDED" && <VotingWaiting message="Meeting is DONE" />}
{currentStatus === "MEETING_ENDED" && <VotingWaiting displayLoading={false} message="Meeting is done" />}
</div>
</main>
<VotingResult currentState={currentStatus}/>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/voting/VotingAnswerQuestion.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import css from "../pages/Voting.module.css";
import type {SelectedVote} from "../pages/Voting.tsx";
import css from "./Voting.module.css";
import type {SelectedVote} from "./Voting.tsx";
import {useEffect, useState} from "react";
import * as http from "../http/HttpRequest.ts";
import {VotingWaiting} from "./VotingWaiting.tsx";
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/voting/VotingResult.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as http from "../http/HttpRequest.ts";
import css from "./VotingResult.module.css"
import {useEffect, useState} from "react";
import type {SelectedVote, VotingState} from "../pages/Voting.tsx";
import type {SelectedVote, VotingState} from "./Voting.tsx";
import {Loading} from "../loading/Loading.tsx";

interface ApiVotingResult {
Expand Down
Loading