From 4048dd774c817462c0a692f0f94d979290e725ee Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Tue, 16 Mar 2021 10:54:28 +0100 Subject: feat: create repository --- src/repository/models.rs | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'src/repository/models.rs') diff --git a/src/repository/models.rs b/src/repository/models.rs index 607008e..1fd1649 100644 --- a/src/repository/models.rs +++ b/src/repository/models.rs @@ -1,5 +1,6 @@ use crate::db::get_client; use crate::errors::{AppError, AppErrorType}; + use chrono::NaiveDateTime; use deadpool_postgres::{Client, Pool}; use serde::{Deserialize, Serialize}; @@ -7,6 +8,8 @@ use tokio_pg_mapper::FromTokioPostgresRow; use tokio_pg_mapper_derive::PostgresMapper; use uuid::Uuid; +use std::net::SocketAddr; + #[derive(Serialize, Deserialize, PostgresMapper)] #[pg_mapper(table = "repository")] /// Repository model @@ -18,6 +21,12 @@ pub struct Repository { pub uploader_ip: String, } +/// Struct used to create a new repository +#[derive(Serialize, Deserialize)] +pub struct RepositoryData { + pub url: String, +} + impl Repository { /// Find all repositories inside the database. /// Make a select query and order the repositories by descrescent updated @@ -116,4 +125,63 @@ impl Repository { } } + /// Create a new repository. It uses RepositoryData as support struct + pub async fn create( + pool: Pool, + data: &RepositoryData, + uploader_ip: Option, + ) -> Result { + let client = get_client(pool.clone()).await.unwrap(); + + // Search a repository that matches with that url, because if it's + // exists, the server do not create a clone + let repo_search = Repository::search(&client, data.url.clone()).await; + match repo_search { + Ok(_) => { + return Err(AppError { + message: Some("Repository already exists".to_string()), + cause: Some("".to_string()), + error_type: AppErrorType::AuthorizationError, + }); + } + Err(_) => {} + }; + + let statement = client + .prepare(" + INSERT INTO repository(id, url, uploader_ip) VALUES($1, $2, $3) RETURNING * + ").await?; + + // Create a new UUID v4 + let uuid = Uuid::new_v4(); + + // Match the uploader ip + let user_ip = match uploader_ip { + Some(ip) => ip.to_string(), + None => { + return Err(AppError { + message: Some("Failed to fetch uploader ip".to_string()), + cause: Some("".to_string()), + error_type: AppErrorType::AuthorizationError, + }) + } + }; + + let repo = client + .query(&statement, &[&uuid, &data.url, &user_ip]) + .await? + .iter() + .map(|row| Repository::from_row_ref(row).unwrap()) + .collect::>() + .pop(); + + match repo { + Some(repo) => Ok(repo), + None => Err(AppError { + message: Some("Error creating a new repository".to_string()), + cause: Some("Unknown error".to_string()), + error_type: AppErrorType::DbError, + }), + } + } } -- cgit v1.2.3-18-g5258