Skip to content

Commit

Permalink
Merge branch 'Cybersecurity-LINKS:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
agmangas authored Dec 4, 2024
2 parents 08f308e + bef57d8 commit 924b6ab
Show file tree
Hide file tree
Showing 58 changed files with 234 additions and 889 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
mongodb_data_container
# smart-contracts
# smart-contracts
ipfs
blocks
.idea
data
5 changes: 4 additions & 1 deletion actix-server/.env
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ STRONGHOLD_SNAPSHOT_PATH="./example.stronghold"

KEY_STORAGE_STRONGHOLD_SNAPSHOT_PATH="./key_storage.stronghold"
KEY_STORAGE_STRONGHOLD_PASSWORD="some_hopefully_secure_password"
KEY_STORAGE_MNEMONIC="raise script athlete plastic stamp lion exhibit mention hint leopard curve gap parade adult surge large pizza claw unveil spy sorry industry salmon juice"
KEY_STORAGE_MNEMONIC="raise script athlete plastic stamp lion exhibit mention hint leopard curve gap parade adult surge large pizza claw unveil spy sorry industry salmon juice"

#Log
LOG_FILE_NAME="dlog.log"
34 changes: 0 additions & 34 deletions actix-server/api/Trust-service.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -263,40 +263,6 @@
"description": "Get Log from IPFS"
},
"response": []
},
{
"name": "Log",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "",
"type": "file",
"src": ""
}
]
},
"url": {
"raw": "http://127.0.0.1:8081/api/log",
"protocol": "http",
"host": [
"127",
"0",
"0",
"1"
],
"port": "8081",
"path": [
"api",
"log"
]
},
"description": "Publish a file on IPFS"
},
"response": []
}
]
}
37 changes: 0 additions & 37 deletions actix-server/api/specifications.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,26 +179,6 @@ paths:
schema:
type: string
format: binary
post:
tags:
- Logs
summary: Upload or Update the log file to IPFS
description: "This endpoint allows to upload the log file to IPFS."
operationId: upload_log
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
description: The log file to be uploaded
required: true
responses:
200:
description: File uploaded successfully

components:
schemas:
Expand Down Expand Up @@ -265,23 +245,6 @@ components:
type: string
description: DID of the user, owner of the asset
description: Input for minting the NFT
LogRequest:
type: object
properties:
file:
type: string
format: binary
description: The log file to be uploaded
required:
- file
description: Input for uploading the log file
LogUploadResponse:
type: object
properties:
message:
type: string
description: Confirmation message
description: Response after uploading the log file
LogFileResponse:
type: string
format: binary
Expand Down
4 changes: 4 additions & 0 deletions actix-server/dlog.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"did:iota:rms:0xda9e0e3e4b55215eec70014119af5f21fd1ca0c371afe9365052134bd3c29b34","id-asset-1"
"did:iota:rms:0xda9e0e3e4b55215eec70014119af5f21fd1ca0c371afe9365052134bd3c29b34","id-asset-1"
"did:iota:rms:0xda9e0e3e4b55215eec70014119af5f21fd1ca0c371afe9365052134bd3c29b34","id-asset-1"
"did:iota:rms:0xda9e0e3e4b55215eec70014119af5f21fd1ca0c371afe9365052134bd3c29b34","id-asset-1"
139 changes: 51 additions & 88 deletions actix-server/src/controllers/log_controller.rs
Original file line number Diff line number Diff line change
@@ -1,94 +1,67 @@
// SPDX-FileCopyrightText: 2023 Fondazione LINKS
//
// SPDX-License-Identifier: APACHE-2.0

use std::env;
use std::io::{Cursor};
use std::fs::File;
use actix_web::{get, post};
use actix_web::{web, HttpResponse, Error};
use actix_multipart::Multipart;
use actix_web::http::uri::Scheme;
use futures_util::{StreamExt as _, TryStreamExt};
use ipfs_api_backend_actix::{IpfsApi, IpfsClient, TryFromUri};
use log::log;
use ipfs_api_backend_actix::{IpfsClient, TryFromUri};
use crate::errors::TrustServiceError;
use crate::models::log_model::Log;
use crate::services::mongodb_repo::MongoRepo;

/// This API takes a file, checks that the filename is correct,
/// then it publishes that file to IPFS.
/// It gets the CID from IPFS, then stores the CID in the DB.
/// Update the document in the DB with the same name or create it.
#[post("")]
async fn publish_log(mut payload: Multipart, mongodb_repo: web::Data<MongoRepo>) -> Result<HttpResponse, TrustServiceError> {

let mut file_count = 0;
let mut file_data = Vec::new();
let mut filename = String::new();

while let Some(item) = payload.next().await {
// Read a file for each loop
file_count += 1;// increment the number of files
if file_count > 1 { // if more that a loop is executed, error just one file allowed
return Ok(HttpResponse::BadRequest().body("Only one file allowed"));
}

let mut field = item?;
if let Some(content_disposition) = field.content_disposition() {
if let Some(fname) = content_disposition.get_filename() {
filename = fname.to_string();
if filename == "" { file_count -= 1}//if the name is empy no file was sent decrement file_count

// this 'while' stores the file in the file_data variable
while let Some(chunk) = field.next().await {
let data = chunk?;
file_data.extend_from_slice(&data);
}
} else {
return Ok(HttpResponse::BadRequest().body("Cannot read filename"));
}
} else {
return Ok(HttpResponse::BadRequest().body("Content-Disposition missing"));
use crate::services::ipfs::IpfsService;

/// This function, before publishing the log file,
/// if in the db is already stored a CID,
/// it takes the CID and deletes the corresponding file form IPFS.
/// Then it takes the actual log file,
/// and publishes it to IPFS.
/// It receives the CID from IPFS, and stores the new CID in the DB.
/// When storing the CID it updates the document in the DB with the same file name or create it.
pub async fn publish_log_internal(mongodb_repo: &MongoRepo) -> Result<(), TrustServiceError> {

let ipfs_client = IpfsService::new();

let mongo_cid_request = mongodb_repo.get_log_cid().await;

match mongo_cid_request {
Ok(cid) => {
log::info!("Old log to delete CID: {}", cid);
ipfs_client.delete_file(cid.as_str()).await?;
}
Err(TrustServiceError::MongoFileNotFound) => log::info!("Mongo CID not found"),
Err(_) => Err(TrustServiceError::IpfsUploadError)?
}

log::info!("Publishing new log file to IPFS");
let filename = env::var("LOG_FILE_NAME").expect("$LOG_FILE_NAME must be set.");

// No file check
if file_count == 0 {
return Ok(HttpResponse::BadRequest().body("Missing file"));
}

// Verification of the file name
if filename != std::env::var("LOG_FILE_NAME")
.expect("$LOG_FILE_NAME must be set.") {
return Ok(HttpResponse::BadRequest().body("Wrong file"));
}
let file = File::open(filename.clone()).map_err(|e| TrustServiceError::FileOpenError)?;


// Upload the file on IPFS
let ipfs_client =
if env::var("RUNNING_IN_DOCKER").is_ok(){
IpfsClient::from_host_and_port(Scheme::HTTP, "ipfs", 5001).unwrap()
} else {
IpfsClient::default()
};

let data = Cursor::new(file_data);
let add_result = ipfs_client.add(data).await;

let cid = match add_result {
Ok(res) => {
//log::info!("{:?}", res);
log::info!("File uploaded to IPFS with cid: {}", res.hash);
Ok((res.hash))
},
Err(_e) => Err(TrustServiceError::IpfsUploadError),
};

let cid = ipfs_client.add_file(filename.as_str()).await?;
log::info!("Log added to IPFS with: {cid}");
let log_doc = Log {
name: filename,
cid: cid?,
cid: cid,
};

log::info!("Storing CID in the DB");
mongodb_repo.store_log_cid(log_doc).await?;

drop(ipfs_client);
Ok(())
}

/// This API call the publish_log_internal to push the log to IPFS
/*
#[post("")]
async fn publish_log(mongodb_repo: web::Data<MongoRepo>) -> Result<HttpResponse, TrustServiceError> {
publish_log_internal(&mongodb_repo).await?;
Ok(HttpResponse::Ok().body("File uploaded successfully"))
}
*/

/// This API retrieves the log file from IPFS
/// It reads the CID from the DB
Expand All @@ -99,24 +72,14 @@ async fn get_log(mongodb_repo: web::Data<MongoRepo>) -> Result<HttpResponse, Err

// get the CID from the DB
let cid = mongodb_repo.get_log_cid().await?;

let ipfs_client =
if env::var("RUNNING_IN_DOCKER").is_ok(){
IpfsClient::from_host_and_port(Scheme::HTTP, "ipfs", 5001).unwrap()
} else {
IpfsClient::default()
};

log::info!("Retrieving from IPFS");
let ipfs_client = IpfsService::new();

// retrieve from IPFS
let file = ipfs_client
.cat(&cid)
.map_ok(|chunk| chunk.to_vec())
.try_concat()
.await
.map_err(|_| "error reading full file");

let file = ipfs_client.get_file(cid.as_str()).await;

drop(ipfs_client);

match file {
Ok(data) => Ok(HttpResponse::Ok().body(data)),
Err(e) => Ok(HttpResponse::InternalServerError().body(format!("Error: {}", e))),
Expand All @@ -127,7 +90,7 @@ pub fn scoped_config(cfg: &mut web::ServiceConfig) {
cfg.service(
// prefixes all resources and routes attached to it...
web::scope("/log")
.service(publish_log)
// .service(publish_log)
.service(get_log)
);
}
5 changes: 4 additions & 1 deletion actix-server/src/controllers/proof_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ use crate::models::tangle_proof::TangleProof;
async fn get_proof(
path: web::Path<String>,
iota_state: web::Data<IotaState>,
mongo_repo: web::Data<MongoRepo>
) -> Result<HttpResponse, TrustServiceError> {
// TODO: check if it is a proof in the db
let proof_id = path.into_inner();
let proof = iota_state.resolve_proof(proof_id).await?;
let proof = iota_state.resolve_proof(proof_id.clone()).await?;

let publisher_document: IotaDocument = iota_state.resolve_did(proof.did_publisher.as_str()).await?;
//log::warn!("TROVATO2: {:?}", proof.did_publisher.as_str());
mongo_repo.get_asset_by_proof(proof_id.clone()).await?;
proof.verify(&publisher_document)?;

Ok(HttpResponse::Ok().json(proof))
Expand Down
18 changes: 18 additions & 0 deletions actix-server/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use actix_multipart::MultipartError;
use actix_web::{HttpResponse, ResponseError, http::header::ContentType};
use log::error;
use reqwest::StatusCode;

#[derive(thiserror::Error, Debug)]
Expand Down Expand Up @@ -56,13 +57,25 @@ pub enum TrustServiceError {
GenericError(#[from] anyhow::Error),
#[error("File not Found in Mongo")]
MongoFileNotFound,

#[error("IPFS upload error")]
IpfsUploadError,
#[error("IPFS connection error")]
IpfsConnError,
#[error("IPFS read error")]
IpfsReadError,
#[error("IPFS unpin error")]
IpfsUnpinError,
#[error("IPFS block_rm error")]
IpfsBlockRmError,

#[error("Multipart error: {0}")]
MultipartError(String),

#[error("Error opening file")]
FileOpenError,
#[error("Error while writing file")]
FileWriteError,
}

impl From<MultipartError> for TrustServiceError {
Expand Down Expand Up @@ -106,7 +119,12 @@ impl ResponseError for TrustServiceError {
TrustServiceError::MongoFileNotFound => StatusCode::NOT_FOUND,
TrustServiceError::IpfsUploadError => StatusCode::INTERNAL_SERVER_ERROR,
TrustServiceError::IpfsConnError => StatusCode::INTERNAL_SERVER_ERROR,
TrustServiceError::IpfsReadError => StatusCode::NOT_FOUND,
TrustServiceError::IpfsUnpinError => StatusCode::INTERNAL_SERVER_ERROR,
TrustServiceError::IpfsBlockRmError => StatusCode::INTERNAL_SERVER_ERROR,
TrustServiceError::MultipartError(_) => StatusCode::BAD_REQUEST,
TrustServiceError::FileOpenError => StatusCode::INTERNAL_SERVER_ERROR,
TrustServiceError::FileWriteError => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}
Loading

0 comments on commit 924b6ab

Please sign in to comment.