Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
chore: solve conflict with develop
Browse files Browse the repository at this point in the history
  • Loading branch information
tassiluca committed Feb 1, 2024
2 parents 04d5455 + ceddedc commit b942c7d
Show file tree
Hide file tree
Showing 337 changed files with 138,926 additions and 3,585 deletions.
74 changes: 54 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
<div align="center">

**Distributed Systems Final Project**
**Distributed Systems + Applications and Web Services Final Project @ UniBo**

```
██████╗██╗ ██╗ █████╗ ██╗███╗ ██╗██╗ ██╗ ██████╗ ████████╗███████╗
██╔════╝██║ ██║██╔══██╗██║████╗ ██║██║ ██║██╔═══██╗╚══██╔══╝██╔════╝
██║ ███████║███████║██║██╔██╗ ██║██║ ██║██║ ██║ ██║ █████╗
██║ ██╔══██║██╔══██║██║██║╚██╗██║╚██╗ ██╔╝██║ ██║ ██║ ██╔══╝
╚██████╗██║ ██║██║ ██║██║██║ ╚████║ ╚████╔╝ ╚██████╔╝ ██║ ███████╗
╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═══╝ ╚═════╝ ╚═╝ ╚══════╝
```
<img src="./frontend/src/assets/logo.svg" width="180px" />

[Requirements](#requirements) | [Startup](#startup) | [Documentation](#documentation) | [Troubleshooting](#troubleshooting) | [Authors](#authors)
[Abstract](#abstract) | [Requirements](#requirements) | [Startup](#startup) | [Docs](#documentation) | [Develop](#develop) | [Troubleshooting](#troubleshooting) | [Authors](#authors)

</div>

## Abstract

> Electronic voting systems based on blockchain technology have emerged
as a potential solution to enhance the security and transparency of traditional voting methods. In this system, voters cast their votes electronically,
and the results are stored on a decentralized blockchain ledger, which ensures the integrity of the vote by preventing any tampering or manipulation.
This system provides a transparent and immutable record of votes, which
can be accessed by anyone in the network, thus increasing trust in the electoral process. Nevertheless, the use of blockchain technology in electronic
voting systems holds promise for creating a more secure, transparent, and
democratic electoral process.
>
> The project consists of the implementation of a small-scale distributed electronic voting system based on blockchain technology. Specifically, the goal is to create a **distributed architecture** that exposes a **uniform API** allowing users to interact with the system using a web application.
**Warning:** This repository is part of an academic project developed for the course in Distributed Systems and Application and Web Services @ UniBo. It is intended for educational purposes and may not be suitable for production use.

## Requirements

- Unix system (either Linux or MacOS)
Expand All @@ -24,21 +31,30 @@
- Node.js 18 or higher
- `npm`

## Develop
## Startup

To clone the project:
---

```bash
git clone --recurse-submodules <URL> <DESTINATION>
**Important**

For security reasons the password for using the mailer is not stored in the repository, but it is passed to the container using a docker secret. Before starting up the system, it’s necessary to create a password file, at the position defined in the secrets section of the `docker-compose.yaml` file:

```yaml
secrets:
google_api_secret:
file: ~/secrets/api-pass.txt
```
If the repository has been cloned plainly, then submodules can be initialized manually:
It is also possible to specify the mail address that will be used to send the emails by changing the `MAIL ADDRESS` environment variable on the `api-server` service:

```bash
git submodule update --init --recursive
```yaml
environment:
...
- MAIL_USER=chainvote.01@gmail.com
...
```

## Startup
---

To bring up the blockchain network, deploy the smart contracts on top of the peers, start the API services and the frontend web app you can use the `services.sh` script on the root of the project.

Expand All @@ -50,15 +66,19 @@ To bring up all the system's services:

Since the first time it will pull Hyperledger Fabric binaries and docker images to create blockchain artifacts and start API services, it will take a while to bring up the entire system.

---

While it reaches the API server creation phase, the script will execute the `npm login` command.
We've preconfigured some default credentials for this purpose; these should be used when login request is prompted:

- username: `user`
- password: `password`

:warning: During the startup phase of the API layer, the script will require the sudo privileges in order to ensure that the `verdaccio`, `cache` and `dbdata` folders have write and read permissions, which are needed on Linux environment.
During the startup phase of the API layer, the script will require the sudo privileges in order to ensure that the `verdaccio`, `cache` and `dbdata` folders have write and read permissions, which are needed on Linux environment.

---

The full working system consists of 33 containers (Figure 19): one for each peer and chaincode deployed on it, five containers for the API services and one for the frontend web app.
The full working system consists of 33 containers: one for each peer and chaincode deployed on it, five containers for the API services and one for the frontend web app.

To bring them down without cleaning the blockchain artifacts (it will speed up the creation of the network next times):

Expand Down Expand Up @@ -87,6 +107,20 @@ For more details have a look at the project documentation.
- [`api-server`](https://tassiluca.github.io/ChainVote/swagger-ui-api/)
- [`auth-server`](https://tassiluca.github.io/ChainVote/swagger-ui-auth/)

## Develop

To clone the project:

```bash
git clone --recurse-submodules <URL> <DESTINATION>
```

If the repository has been cloned plainly, then submodules can be initialized manually:

```bash
git submodule update --init --recursive
```

## Troubleshooting

If you are encountering issues or observing unexpected behavior during the deployment, this troubleshooting guide is designed to assist you in identifying and resolving common problems.
Expand Down
6 changes: 4 additions & 2 deletions api-service/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
"accesscontrol": "^2.2.1",
"bcrypt": "^5.1.0",
"body-parser": "^1.20.2",
"core-components": "^1.1.4",
"core-components": "^1.1.6",
"express": "^4.18.2",
"express-validator": "^7.0.1",
"http-status-codes": "^2.2.0",
"luxon": "^3.4.4",
"mongoose": "^7.4.3",
"redis": "^4.6.8"
"nodemailer": "^6.9.8",
"redis": "^4.6.8",
"socket.io": "^4.7.4"
},
"devDependencies": {
"@tsconfig/node16": "^1.0.3",
Expand Down
9 changes: 3 additions & 6 deletions api-service/api/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import ExpressConfig from "./configs/express.config.js"



const app = ExpressConfig();
import ServerConfig from "./configs/server.config"
const app = ServerConfig();
const PORT = process.env.PORT || 8080;

function printInformations() {
Expand All @@ -16,7 +13,7 @@ function printInformations() {
\\____jl__j__jl__j__j|____jl__j__j \\_/ \\___/ l__j l_____j l__j__jl__j |____j
`);
console.log("DS Project - 2022/2023");
console.log("DS + AWS Project - 2022/2023");
console.log("Authors: Giovanni Antonioni, Luca Tassinari, Luca Rubboli");
console.log("Server Running on Port " + PORT);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,4 @@ export class CommunicatorBuilder {
this._mspId
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,5 +73,4 @@ export class CommunicatorFactory {
.mspId(ORG3_MSP_ID)
.build();
}

}
}
24 changes: 12 additions & 12 deletions api-service/api/src/blockchain/communicator/communicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface CommunicatorInterface {
createSigner(): Promise<Signer>
}

export class Communicator implements CommunicatorInterface {
export class Communicator implements CommunicatorInterface {

private _keyPath: string;
private _certPath: string;
Expand All @@ -36,9 +36,9 @@ export interface CommunicatorInterface {
this._mspId = mspId;
}

/**
* Create a grpc client to interact with the blockchain
*/
/**
* Create a grpc client to interact with the blockchain
*/
async createGrpcClient(): Promise<grpc.Client> {
const tlsRootCert = await fs.readFile(this._peerTlsPath);
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert);
Expand All @@ -47,23 +47,23 @@ export interface CommunicatorInterface {
});
}

/**
* Create the identity object that represent the identity that will interact with the blockchain.
*/
/**
* Create the identity object that represent the identity that will interact with the blockchain.
*/
async createIdentity(): Promise<Identity> {
const credentials: Buffer = await fs.readFile(this._certPath);
const mspId: string = this._mspId;
return { mspId, credentials };
}

/**
* Create the signer object that will endorse the transactions.
*/
/**
* Create the signer object that will endorse the transactions.
*/
async createSigner(): Promise<Signer> {
const files = await fs.readdir(this._keyPath);
const keyPath = path.resolve(this._keyPath, files[0]);
const privateKeyPem = await fs.readFile(keyPath);
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
}
}
}
}
2 changes: 1 addition & 1 deletion api-service/api/src/blockchain/errors/error.handling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {BadRequestError, ErrorTypes} from "core-components";
*/
export default function transformHyperledgerError(error: Error) {
let message;
if("details" in error) {
if ("details" in error) {
// @ts-ignore
message = error.details[0].message;
} else {
Expand Down
2 changes: 1 addition & 1 deletion api-service/api/src/blockchain/grpc.client.pool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,4 @@ class GrpcClientPool {
}
}

export default GrpcClientPool;
export default GrpcClientPool;
1 change: 0 additions & 1 deletion api-service/api/src/configs/accesscontrol.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,3 @@ const acObject: AccessControl = new AccessControl(grantsObject);
acObject.lock();

export {acObject as ac};

42 changes: 0 additions & 42 deletions api-service/api/src/configs/express.config.ts

This file was deleted.

15 changes: 15 additions & 0 deletions api-service/api/src/configs/mailer.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import nodemailer from 'nodemailer';
import fs from "fs";

const path = "/run/secrets/google_api_secret";
const secretValue = fs.readFileSync(path, 'utf8').trim();

const config = {
service: 'gmail',
auth: {
user: process.env.MAIL_USER,
pass: secretValue
}
}

export default nodemailer.createTransport(config);
3 changes: 2 additions & 1 deletion api-service/api/src/configs/mongoose.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import mongoose from "mongoose"

const connectionString = process.env.MONGODB_CONNECTION_STRING as string ||
"mongodb://user:pass@localhost:27017/?authMechanism=DEFAULT"

async function MongooseConfig() {
try {
await mongoose.connect(connectionString);
Expand All @@ -10,4 +11,4 @@ async function MongooseConfig() {
}
}

export default MongooseConfig;
export default MongooseConfig;
2 changes: 0 additions & 2 deletions api-service/api/src/configs/redis.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,3 @@ export default class RedisLimiterStorage implements ApiLimiterStorage {
return redisClient.expire(clientId, seconds);
}
}


52 changes: 52 additions & 0 deletions api-service/api/src/configs/server.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import express from "express"
import bodyParser from "body-parser"
import {defaultErrorHandler, defaultResponseHandler, JwtHandler} from "core-components";
import MongooseConfig from "./mongoose.config";
import userRouter from "../routes/user.route";
import electionInfoRouter from "../routes/election.info.route";
import electionRouter from "../routes/election.route";
import codesRoute from "../routes/codes.route";
import {resolve} from "path";
import {createServer, Server} from "node:http";
import SocketIoConfig from "./socket.config";
import notificationsRoute from '../routes/notifications.route'

const ServerConfig = (): Server => {
JwtHandler.config({
ATPrivateKeyPath: resolve("./secrets/at_private.pem"),
RTPrivateKeyPath: resolve("./secrets/rt_private.pem")
});

MongooseConfig();

const app = express();
const httpServer = createServer(app);
const io = SocketIoConfig(httpServer);

// Express configurations
app.use(express.json());
app.use(bodyParser.json());
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, PATCH");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});

// Routes initialization
app.use("/users", userRouter);
app.use("/election", electionRouter(io));
app.use("/election/info", electionInfoRouter);
app.use("/code", codesRoute);
app.use("/notifications", notificationsRoute);

// Use custom response handler.
app.use(defaultResponseHandler);

// Use custom error handler.
app.use(defaultErrorHandler);

return httpServer;
}

export default ServerConfig
Loading

0 comments on commit b942c7d

Please sign in to comment.