vaguely working upload/download implementation
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
/target
 | 
			
		||||
db/punt.sqlite
 | 
			
		||||
uploads
 | 
			
		||||
							
								
								
									
										1542
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1542
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										27
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
[package]
 | 
			
		||||
name = "punt"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
edition = "2021"
 | 
			
		||||
 | 
			
		||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
rocket = {version = "0.5.0-rc.1", features = ["json"]}
 | 
			
		||||
serde = {version = "1", features = ["derive"]}
 | 
			
		||||
tokio = {version = "1", features = ["fs"]}
 | 
			
		||||
serde_json = "1"
 | 
			
		||||
rand = "0.8"
 | 
			
		||||
 | 
			
		||||
[dependencies.libsqlite3-sys]
 | 
			
		||||
version = ">=0.17.2, <0.24.0"
 | 
			
		||||
features = ["bundled"]
 | 
			
		||||
 | 
			
		||||
[dependencies.diesel]
 | 
			
		||||
version = "1.4"
 | 
			
		||||
default-features = false
 | 
			
		||||
features = ["sqlite"]
 | 
			
		||||
 | 
			
		||||
[dependencies.rocket_sync_db_pools]
 | 
			
		||||
version = "0.1.0-rc.1"
 | 
			
		||||
default-features = false
 | 
			
		||||
features = ["diesel_sqlite_pool"]
 | 
			
		||||
							
								
								
									
										4
									
								
								Rocket.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								Rocket.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
# Temporary, will be replaced by env vars and hard-coded defaults eventually so that Punt can function as a single-binary application
 | 
			
		||||
 | 
			
		||||
[global.databases]
 | 
			
		||||
punt = {url = "db/punt.sqlite"}
 | 
			
		||||
							
								
								
									
										1
									
								
								db/migrations/2022-01-16-214545_initial/down.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								db/migrations/2022-01-16-214545_initial/down.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
DROP TABLE uploads;
 | 
			
		||||
							
								
								
									
										5
									
								
								db/migrations/2022-01-16-214545_initial/up.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								db/migrations/2022-01-16-214545_initial/up.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
CREATE TABLE uploads (
 | 
			
		||||
    id TEXT PRIMARY KEY NOT NULL,
 | 
			
		||||
    name TEXT,
 | 
			
		||||
    created_at INTEGER
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										9
									
								
								diesel.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								diesel.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
# For documentation on how to configure this file,
 | 
			
		||||
# see diesel.rs/guides/configuring-diesel-cli
 | 
			
		||||
 | 
			
		||||
[print_schema]
 | 
			
		||||
file = "src/schema.rs"
 | 
			
		||||
 | 
			
		||||
# this will start working whenever Diesel CLI gets around to releasing v1.4.4
 | 
			
		||||
# [migrations_directory]
 | 
			
		||||
# file = "db/migrations"
 | 
			
		||||
							
								
								
									
										40
									
								
								src/data.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/data.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
use rocket_sync_db_pools::database;
 | 
			
		||||
use rocket::serde::Serialize;
 | 
			
		||||
use diesel::prelude::*;
 | 
			
		||||
 | 
			
		||||
use crate::schema::uploads;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[database("punt")]
 | 
			
		||||
pub struct DbConn(diesel::SqliteConnection);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Queryable, Insertable, Serialize)]
 | 
			
		||||
#[table_name="uploads"]
 | 
			
		||||
pub struct FileInfo {
 | 
			
		||||
    pub id: String,
 | 
			
		||||
    pub name: Option<String>,
 | 
			
		||||
    pub created_at: Option<i32> // figure out how to marshal this to a proper time type later
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pub async fn get_file_info(id: String, conn: DbConn) -> QueryResult<FileInfo> {
 | 
			
		||||
    conn.run(|c| uploads::table.find(id).first(c)).await
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pub async fn put_file_info(id: &str, name: Option<&str>, conn: DbConn) -> QueryResult<()> {
 | 
			
		||||
    let file_info = FileInfo {
 | 
			
		||||
        id: id.to_owned(),
 | 
			
		||||
        name: name.map(|n| n.to_owned()),
 | 
			
		||||
        created_at: Some(1642371865),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    conn.run(|c| {
 | 
			
		||||
        diesel::insert_into(uploads::table)
 | 
			
		||||
            .values(file_info)
 | 
			
		||||
            .execute(c)
 | 
			
		||||
    }).await?;
 | 
			
		||||
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
			
		||||
use rand::{Rng, distributions::Alphanumeric};
 | 
			
		||||
use tokio::fs::create_dir;
 | 
			
		||||
use std::io::ErrorKind;
 | 
			
		||||
use rocket::fs::TempFile;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pub fn gen_id() -> String {
 | 
			
		||||
    rand::thread_rng()
 | 
			
		||||
        .sample_iter(Alphanumeric)
 | 
			
		||||
        .map(|c| c as char)
 | 
			
		||||
        .take(16)
 | 
			
		||||
        .collect()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
pub async fn persist_file(file: &mut TempFile<'_>, filename: &str) -> std::io::Result<()> {
 | 
			
		||||
    let dst = format!("uploads/{filename}");
 | 
			
		||||
    match file.persist_to(&dst).await {
 | 
			
		||||
        Err(e) if e.kind() == ErrorKind::NotFound => {
 | 
			
		||||
            create_dir("uploads").await?;
 | 
			
		||||
            file.persist_to(&dst).await
 | 
			
		||||
        },
 | 
			
		||||
        other => other,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
use rocket::{get, post, routes, fs::TempFile};
 | 
			
		||||
use rocket::http::Status;
 | 
			
		||||
use rocket::serde::json::Json;
 | 
			
		||||
#[macro_use] extern crate diesel;
 | 
			
		||||
 | 
			
		||||
mod data;
 | 
			
		||||
mod lib;
 | 
			
		||||
mod schema;
 | 
			
		||||
use data::{DbConn, FileInfo};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[get("/")]
 | 
			
		||||
fn test() -> &'static str {
 | 
			
		||||
    return "Hello, world!";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[get("/<id>")]
 | 
			
		||||
async fn download(id: String, conn: DbConn) -> Result<Json<FileInfo>, Status> {
 | 
			
		||||
    data::get_file_info(id, conn).await
 | 
			
		||||
        .map(|info| Json(info))
 | 
			
		||||
        .map_err(|_| Status::InternalServerError)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[post("/upload", data = "<file>")]
 | 
			
		||||
async fn upload(mut file: TempFile<'_>, conn: DbConn) -> Result<String, Status> {
 | 
			
		||||
    let id = lib::gen_id();
 | 
			
		||||
    data::put_file_info(&id, file.name(), conn).await
 | 
			
		||||
        .map_err(|_| Status::InternalServerError)?;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    lib::persist_file(&mut file, &id).await
 | 
			
		||||
        .map_err(|_| Status::InternalServerError)?;
 | 
			
		||||
    Ok(id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[rocket::launch]
 | 
			
		||||
fn rocket() -> _ {
 | 
			
		||||
    rocket::build()
 | 
			
		||||
        .attach(DbConn::fairing())
 | 
			
		||||
        .mount("/", routes![test, upload, download])
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										7
									
								
								src/schema.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/schema.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
table! {
 | 
			
		||||
    uploads (id) {
 | 
			
		||||
        id -> Text,
 | 
			
		||||
        name -> Nullable<Text>,
 | 
			
		||||
        created_at -> Nullable<Integer>,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user