Skip to content

Commit

Permalink
Merge pull request #9 from K-nto/feature/authentication
Browse files Browse the repository at this point in the history
Feature/authentication
  • Loading branch information
bizk authored Oct 31, 2022
2 parents ec842fd + 05ffac8 commit 41faec2
Show file tree
Hide file tree
Showing 17 changed files with 234 additions and 79 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ build/
node_modules/
.env
.vscode/settings.json
org1.example.com

139 changes: 126 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,136 @@
# Kinto-storage-service
<div align="center">

## Run
<img src="resources/Kintoisologo.png" alt="logo" width="200" height="auto" />
<h1>Kinto storage service</h1>

<h5>
UADE Informatics Engineering thesis project - 2022
</h5>

`npm run start`
TODO: Add watch mode for dev
<p>
Kinto storage service, handles strorage and authentication operations.
</p>

<h4>
<a href="https://github.com/K-nto/Kinto-storage-service/">Documentation</a>
<span> · </span>
<a href="https://github.com/K-nto/Kinto-storage-service/issues/">Report Bug</a>
<span> · </span>
<a href="https://github.com/K-nto/Kinto-storage-service/issues/">Request Feature</a>
</h4>
</div>

### first version of ipfs connection
<br />

start ipfs node in your computer with
`jsipfs daemon`
# :notebook_with_decorative_cover: Table of Contents

make sure it's reachable (`localhost:5001/webui`) and, if not, configure CORS properly (there are instructions there)
- [About the Project](#star2-about-the-project)
- [Tech Stack](#space_invader-tech-stack)
- [Features](#dart-features)
- [Setup](#Setup)
- [Prerequisites](#bangbang-prerequisites)
- [Usage](#eyes-usage)
- [License](#warning-license)
- [Contact](#handshake-contact)
- [Acknowledgements](#gem-acknowledgements)

have fun
## :star2: About the Project

## Docs
This service manages storage operatiuons, hyperledger blockchain connection, auuthentication and interactions, and IPFS network operations.

TODO: Add Swagger support
### :space_invader: Tech Stack

## Reference
<ul>
<li><a href="https://nodejs.org/">Node</a></li>
<li><a href="https://www.typescriptlang.org/">Typescript</a></li>
<li><a href="https://ipfs.tech/">IPFS</a></li>
<li><a href="https://www.hyperledger.org/use/fabric/">Hyperledger fabric</a></li>
</ul>

https://www.toptal.com/express-js/nodejs-typescript-rest-api-pt-1
### :dart: Features

- Authenticates users with hyperledger blockchain
- Stoores and retreives files from IPFS network
- Submit operations into hyperledger blockchain

## :toolbox: Setup

### :bangbang: Prerequisites

- **Node** This project uses node and npm as package manager, make sure it is installed.

```bash
node -v
npm -v
```

- **ipfs** This project uses IPFS to store files connect to an IPFS network or create your own by running the following command

```bash
jsipfs daemon
```

### :key: Environment Variables

To run this project, you will need to add the following environment variables to your .env file, here it is an example of a localhost configuiration

```bash
PORT=8081

ENV=localhost
CCP_PATH=./org1.example.com/connection-org1.json
WALLET_PATH=./wallet
ADMIN_WALLET=admin
ADMIN_WALLET_SECRET=adminpw
CA_ORG_ID=ca.org1.example.com

IPFS_API=http://127.0.0.1:5001/api/v0
```

## :gear: Usage

Clone the project

```bash
git clone https://github.com/K-nto/Kinto-network-status-service.git
```

Go to the project directory

```bash
cd Kinto-network-status-service
```

Install dependencies.

```bash
npm install
```

Start the service.

```bash
npm run start
```

## :warning: License

Distributed under the no License. See LICENSE.txt for more information.

<!-- Contact -->

## :handshake: Contact

Federico Javier Parodi - Fedejp - [Linkedin](https://www.linkedin.com/in/fedejp) - [Github](https://github.com/Fedejp)

Carlos Santiago Yanzon - Bizk - [Linkedin](https://www.linkedin.com/in/carlos-santiago-yanzon/) - [Github](https://github.com/bizk)

Project Link: [https://github.com/K-nto](https://github.com/K-nto)

## :gem: Acknowledgements

We thank and aknowledge the authors of these resources for their work.

- [Awesome README](https://github.com/matiassingers/awesome-readme)
- [Emoji Cheat Sheet](https://github.com/ikatyang/emoji-cheat-sheet/blob/master/README.md#travel--places)
- [Readme Template](https://github.com/othneildrew/Best-README-Template)
Binary file added resources/Kintoisologo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions src/common/authorization.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {testUsers} from '../users/testUsers';

/** Returns true if the request is originated by a valid public/private key pair
* Probably better in the HL Authenticator class
*/
export const authorized = (userId: string, authToken: string = '') => {
// @TODO: authorize for realsies
// call HL authenticator here or sth
return (
authToken &&
testUsers.find(user => user.address === userId) &&
userId == authToken
);
};

export const getUserInfo = (walletAddress: string) => {
return testUsers.find(user => user.address === walletAddress);
};
3 changes: 2 additions & 1 deletion src/files/files.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import fileUpload from 'express-fileupload';
import {StorageOperationController} from '../hyperledger/StorageOperationController';
import ipfsService from '../ipfs/ipfs.service';
import {KFSEntry} from './files.interfaces';
import {IEncryptedFile} from './interfaces/IEncryptedFile.interface';

class FilesController {
async createFile(userId: string, file: fileUpload.UploadedFile) {
async createFile(userId: string, file: IEncryptedFile) {
console.log(
`[INFO] files.controller - createFile: Create file for user with id ${userId}`
);
Expand Down
31 changes: 24 additions & 7 deletions src/files/files.routes.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {Application, Request, Response, NextFunction} from 'express';
import fileUpload from 'express-fileupload';
import {authorized} from '../common/authorization.service';
import {CommonRoutesConfig} from '../common/common.routes.config';
import {FILES, USERS} from '../common/common.routes.consts';
import filesController from './files.controller';
import {IEncryptedFile} from './interfaces/IEncryptedFile.interface';

export class FilesRoutes extends CommonRoutesConfig {
constructor(app: Application) {
Expand All @@ -14,12 +16,20 @@ export class FilesRoutes extends CommonRoutesConfig {
.route(`/${USERS}/:userId/${FILES}`)
.all((req: Request, res: Response, next: NextFunction) => {
// Middleware executed on every route. @TODO: Validation @TODO: User authentication @TODO: Register on Hyperledger
console.debug('[Hyperledeger] Authenticated user: ', req.params.userId);
if (!authorized(req.params.userId, req.headers.authorization)) {
console.debug(
'[Authorization] Failed authentication for user: ',
req.params.userId
);

res.status(403).send('Invalid credentials');
return;
}
console.debug(
'[Hyperledeger] Generated transaction: ',
Math.random().toString(16).substr(16)
'[Authorization] Authenticated user: ',
req.params.userId
);

next();
})
.get((req: Request, res: Response) =>
Expand All @@ -31,11 +41,18 @@ export class FilesRoutes extends CommonRoutesConfig {
)
)
.post((req: Request, res: Response) => {
const file = <fileUpload.UploadedFile>req.files?.file;
const file: IEncryptedFile = {...req.body};

if (!file) res.status(400).send('Missing file');
if (
!file ||
!file.address ||
!file.fileData ||
!file.name ||
!file.type
)
return res.status(400).send('Missing file');

filesController
return filesController
.createFile(req.params.userId, file)
.then(result => res.status(201).send(result))
.catch(error =>
Expand Down Expand Up @@ -85,7 +102,7 @@ export class FilesRoutes extends CommonRoutesConfig {
const userId = req.body.userId;
if (!userId) res.status(400).send('Missing userId');

filesController
return filesController
.deleteFile(userId, fileName)
.then(message => res.status(200).send(message))
.catch(error =>
Expand Down
6 changes: 6 additions & 0 deletions src/files/interfaces/IEncryptedFile.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface IEncryptedFile {
name: string;
type: string;
address: string;
fileData: string;
}
2 changes: 1 addition & 1 deletion src/hyperledger/HyperledgerController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class HyperledgerController {
);
const resultBytes =
transactionArgs.length > 0
? await contract.evaluateTransaction(transaction, ...transactionArgs)
? await contract.submitTransaction(transaction, ...transactionArgs)
: await contract.evaluateTransaction(transaction);

// eslint-disable-next-line node/no-unsupported-features/node-builtins
Expand Down
2 changes: 1 addition & 1 deletion src/hyperledger/StorageOperationController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export class StorageOperationController {
'kinto',
'createFileOperation',
fileHash,
walletAddress,
walletAddress.toString(),
operation
);
console.log('[DEBUG] createFileOperation:', transactionResultPayload);
Expand Down
27 changes: 15 additions & 12 deletions src/ipfs/ipfs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import {MFSEntry} from 'ipfs-core-types/src/files';
import {create, IPFSHTTPClient} from 'ipfs-http-client';
import all from 'it-all';
import {KFSEntry} from '../files/files.interfaces';
/**
* @TODO: Better error handling
*/
import {IEncryptedFile} from '../files/interfaces/IEncryptedFile.interface';

const IPFS_DEFAULT_URL = 'http://127.0.0.1:5001/api/v0';

class IPFSService {
private static ipfsHttpClient: IPFSHTTPClient;
/**
Expand All @@ -17,7 +18,7 @@ class IPFSService {
// @TBD: Network url
if (!IPFSService.ipfsHttpClient)
IPFSService.ipfsHttpClient = create({
url: 'http://127.0.0.1:5002/api/v0',
url: process.env.IPFS_API ?? IPFS_DEFAULT_URL,
});
}

Expand All @@ -33,14 +34,17 @@ class IPFSService {
*/
public async createFile(
userId: string,
file: UploadedFile
file: IEncryptedFile
): Promise<KFSEntry[]> {
const filePath = `/${file.name}`;
console.log('[DEBUG] IPFSService - createFile', userId, file);

await IPFSService.ipfsHttpClient.files.write(filePath, file.data, {
create: true,
});
console.log('[DEBUG] IPFSService - createFile', userId, file.name);
await IPFSService.ipfsHttpClient.files.write(
filePath,
JSON.stringify(file),
{
create: true,
}
);
return await this.listFiles(filePath);
}

Expand Down Expand Up @@ -70,8 +74,7 @@ class IPFSService {
for await (const chunk of IPFSService.ipfsHttpClient.cat(cid)) {
fileChunks.push(chunk);
}
return Buffer.concat(fileChunks);
// return Buffer.from(fileChunks.toString())
return Buffer.concat(fileChunks).toString().split('}')[0].concat('}');
}
/**
* Overwrites a file that already exists (AKA, has the same name) in the root dir
Expand Down
41 changes: 0 additions & 41 deletions src/nodes/nodes.routes.config.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import debug from 'debug';
import {CommonRoutesConfig} from './common/common.routes.config';
import {UsersRoutes} from './users/users.routes.config';
import {FilesRoutes} from './files/files.routes.config';
import {NodesRoutes} from './nodes/nodes.routes.config';
import express from 'express';
import * as http from 'http';
import {HyperledgerController} from './hyperledger/HyperledgerController';
Expand All @@ -24,7 +23,6 @@ app.use(cors());

routes.push(new UsersRoutes(app));
routes.push(new FilesRoutes(app));
routes.push(new NodesRoutes(app));

const runningMessage = `Server running at http://localhost:${port}`;
app.get('/', (req: express.Request, res: express.Response) => {
Expand Down
Loading

0 comments on commit 41faec2

Please sign in to comment.