๐Ÿ“๐Ÿ–ผ๏ธ๐Ÿน A small thing where I can upload a file and get a link back. https://media.strawmelonjuice.com/
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implemented file size count and moved impl fn to files.rs module.


Signed-off-by: MLC Bloeiman <mar@strawmelonjuice.com>

+141 -63
+4 -1
.sqlx/query-04c6e15fe956565cc574b5fd9250fce7c3bc9289c542918b8d445333e52436d8.json
··· 17 17 "parameters": { 18 18 "Right": 1 19 19 }, 20 - "nullable": [false, false] 20 + "nullable": [ 21 + false, 22 + false 23 + ] 21 24 }, 22 25 "hash": "04c6e15fe956565cc574b5fd9250fce7c3bc9289c542918b8d445333e52436d8" 23 26 }
+3 -1
.sqlx/query-079e3705c8dd388552d4b9613b20c544440eb3ae3db9f63827e4e8e9b9092414.json
··· 12 12 "parameters": { 13 13 "Right": 1 14 14 }, 15 - "nullable": [false] 15 + "nullable": [ 16 + false 17 + ] 16 18 }, 17 19 "hash": "079e3705c8dd388552d4b9613b20c544440eb3ae3db9f63827e4e8e9b9092414" 18 20 }
+5 -1
.sqlx/query-17fce9ddd017f0bbb006dcde882f8d51f16ea08377d54ccb070e3be6eb56b739.json
··· 22 22 "parameters": { 23 23 "Right": 0 24 24 }, 25 - "nullable": [false, false, false] 25 + "nullable": [ 26 + false, 27 + false, 28 + false 29 + ] 26 30 }, 27 31 "hash": "17fce9ddd017f0bbb006dcde882f8d51f16ea08377d54ccb070e3be6eb56b739" 28 32 }
+4 -1
.sqlx/query-19e4c0a30a8fa7daec04de70e1536424d5d6efc7d6bc7e62e6817b23251c5133.json
··· 17 17 "parameters": { 18 18 "Right": 1 19 19 }, 20 - "nullable": [false, false] 20 + "nullable": [ 21 + false, 22 + false 23 + ] 21 24 }, 22 25 "hash": "19e4c0a30a8fa7daec04de70e1536424d5d6efc7d6bc7e62e6817b23251c5133" 23 26 }
+5 -1
.sqlx/query-55cdc86205af3f03b3cff9dbc25158f02c53dd14f9ad98f00102a2d715e202f8.json
··· 22 22 "parameters": { 23 23 "Right": 0 24 24 }, 25 - "nullable": [false, false, true] 25 + "nullable": [ 26 + false, 27 + false, 28 + true 29 + ] 26 30 }, 27 31 "hash": "55cdc86205af3f03b3cff9dbc25158f02c53dd14f9ad98f00102a2d715e202f8" 28 32 }
+3 -1
.sqlx/query-6837d2c9f9ed1c8b7e78cdd52cbae1a79d4e84b3edf419fbdbf47f17e60a2be4.json
··· 12 12 "parameters": { 13 13 "Right": 1 14 14 }, 15 - "nullable": [false] 15 + "nullable": [ 16 + false 17 + ] 16 18 }, 17 19 "hash": "6837d2c9f9ed1c8b7e78cdd52cbae1a79d4e84b3edf419fbdbf47f17e60a2be4" 18 20 }
+3 -1
.sqlx/query-7aff488a4e7e7bef59132cebc22b21c525302b96d67c94169cc89c17f1743bc4.json
··· 12 12 "parameters": { 13 13 "Right": 1 14 14 }, 15 - "nullable": [false] 15 + "nullable": [ 16 + false 17 + ] 16 18 }, 17 19 "hash": "7aff488a4e7e7bef59132cebc22b21c525302b96d67c94169cc89c17f1743bc4" 18 20 }
+5 -1
.sqlx/query-8807ddf479b83d395d7d442786b43c01e1018f98e5e05757d6f1d5675263dc41.json
··· 22 22 "parameters": { 23 23 "Right": 0 24 24 }, 25 - "nullable": [false, false, false] 25 + "nullable": [ 26 + false, 27 + false, 28 + false 29 + ] 26 30 }, 27 31 "hash": "8807ddf479b83d395d7d442786b43c01e1018f98e5e05757d6f1d5675263dc41" 28 32 }
+6 -1
.sqlx/query-ace5da0bc6eabaf15af75d667a6bb32110d8e17f65a41d87d63ab3138788a889.json
··· 27 27 "parameters": { 28 28 "Right": 1 29 29 }, 30 - "nullable": [false, false, false, false] 30 + "nullable": [ 31 + false, 32 + false, 33 + false, 34 + false 35 + ] 31 36 }, 32 37 "hash": "ace5da0bc6eabaf15af75d667a6bb32110d8e17f65a41d87d63ab3138788a889" 33 38 }
+4 -1
.sqlx/query-b7aee89059fcb605e23e86a68a65b651d9d9b1e9992ae287a4c18627e557d91f.json
··· 17 17 "parameters": { 18 18 "Right": 1 19 19 }, 20 - "nullable": [false, false] 20 + "nullable": [ 21 + false, 22 + false 23 + ] 21 24 }, 22 25 "hash": "b7aee89059fcb605e23e86a68a65b651d9d9b1e9992ae287a4c18627e557d91f" 23 26 }
+3 -1
.sqlx/query-d7b174621a692187cb0b02f61ccf2ad6866536d2eb66b594fe597a4e6d5e6115.json
··· 12 12 "parameters": { 13 13 "Right": 0 14 14 }, 15 - "nullable": [false] 15 + "nullable": [ 16 + false 17 + ] 16 18 }, 17 19 "hash": "d7b174621a692187cb0b02f61ccf2ad6866536d2eb66b594fe597a4e6d5e6115" 18 20 }
+82
server-rs/src/app/files.rs
··· 1 1 use super::*; 2 + use crate::routes::api::{File, User}; 3 + use std::fs; 2 4 impl App { 3 5 pub(crate) async fn add_file( 4 6 &self, ··· 50 52 std::fs::create_dir_all(&path).unwrap(); 51 53 std::fs::write(format!("{}/{}", path, filename), file_bytes).unwrap(); 52 54 Ok(file_id) 55 + } 56 + 57 + /// Get files for a given user. 58 + /// Admin -> All files 59 + /// Non-Admin -> Their own files 60 + pub(crate) async fn files_for_user( 61 + &self, 62 + user: User, 63 + ) -> std::result::Result<Vec<File>, DbError> { 64 + 65 + if user.is_admin { 66 + let files = query!( 67 + "SELECT id as 'id: Uuid', filename, username FROM file_mapping LEFT JOIN users ON users.uid = file_mapping.owner_uid" 68 + ) 69 + .fetch_all(&self.db) 70 + .await?; 71 + 72 + let files: Vec<File> = files 73 + .iter() 74 + .map(|file| { 75 + let file_path = format!("./data/files/{}/{}", file.id, file.filename); 76 + let file_on_fs = std::path::Path::new(&file_path); 77 + 78 + let file_metadata = fs::metadata(file_on_fs); 79 + 80 + let size_mb = if let Ok(file_metadata) = file_metadata { 81 + let bytes = file_metadata.len() as f64; 82 + // I divided by 1_000_000.0 in original impl I think. 83 + bytes / 1048576.0 84 + } else { 85 + // If we couldn't get the metadata just return 0. 86 + 0.0 87 + }; 88 + 89 + File { 90 + id: file.id, 91 + filename: file.filename.clone(), 92 + owner: file.username.clone(), 93 + size_mb, 94 + } 95 + }) 96 + .collect(); 97 + 98 + return Ok(files); 99 + } 100 + 101 + let files = query!( 102 + "SELECT id as 'id: Uuid', filename FROM file_mapping WHERE owner_uid = ?1", 103 + user.id 104 + ) 105 + .fetch_all(&self.db) 106 + .await?; 107 + 108 + let files: Vec<File> = files 109 + .iter() 110 + .map(|file| { 111 + let file_path = format!("./data/files/{}/{}", file.id, file.filename); 112 + let file_on_fs = std::path::Path::new(&file_path); 113 + 114 + let file_metadata = fs::metadata(file_on_fs); 115 + 116 + let size_mb = if let Ok(file_metadata) = file_metadata { 117 + let bytes = file_metadata.len() as f64; 118 + // I divided by 1_000_000.0 in original impl I think. 119 + bytes / 1048576.0 120 + } else { 121 + // If we couldn't get the metadata just return 0. 122 + 0.0 123 + }; 124 + 125 + File { 126 + id: file.id, 127 + filename: file.filename.clone(), 128 + owner: Some(user.username.clone()), 129 + size_mb, 130 + } 131 + }) 132 + .collect(); 133 + 134 + return Ok(files); 53 135 } 54 136 } 55 137
+14 -52
server-rs/src/routes/api.rs
··· 1 + use std::fs; 1 2 use crate::{App, Database, DbError}; 2 3 use rocket::State; 3 4 use rocket::http::Status; ··· 183 184 }; 184 185 185 186 // get the relevant files for this user 186 - let files = match files_for_user(&app.db, user).await { 187 + let files = match app.files_for_user(user).await { 187 188 Ok(v) => v, 188 189 Err(_) => { 189 190 return Err(( ··· 196 197 return Ok(Json(files)); 197 198 } 198 199 199 - /// Get files for a given user. 200 - /// Admin -> All files 201 - /// Non-Admin -> Their own files 202 - async fn files_for_user(conn: &Database, user: User) -> Result<Vec<File>, DbError> { 203 - if user.is_admin { 204 - let files = query!( 205 - "SELECT id as 'id: Uuid', filename, username FROM file_mapping LEFT JOIN users ON users.uid = file_mapping.owner_uid" 206 - ) 207 - .fetch_all(conn) 208 - .await?; 209 200 210 - let files: Vec<File> = files 211 - .iter() 212 - .map(|file| File { 213 - id: file.id, 214 - filename: file.filename.clone(), 215 - owner: file.username.clone(), 216 - size_mb: 0, 217 - }) 218 - .collect(); 219 - 220 - return Ok(files); 221 - } 222 - 223 - let files = query!( 224 - "SELECT id as 'id: Uuid', filename FROM file_mapping WHERE owner_uid = ?1", 225 - user.id 226 - ) 227 - .fetch_all(conn) 228 - .await?; 229 - 230 - let files: Vec<File> = files 231 - .iter() 232 - .map(|file| File { 233 - id: file.id, 234 - filename: file.filename.clone(), 235 - owner: Some(user.username.clone()), 236 - size_mb: 0, 237 - }) 238 - .collect(); 239 - 240 - return Ok(files); 241 - } 242 201 243 202 /// Gets a User from the database using it's uuid 244 203 async fn user_from_id(conn: &Database, user_id: Uuid) -> Result<User, DbError> { ··· 261 220 #[derive(Serialize)] 262 221 #[serde(crate = "rocket::serde")] 263 222 pub(crate) struct User { 264 - id: Uuid, 265 - username: String, 266 - max_megabytes: i64, 267 - user_megabytes: f64, 268 - is_admin: bool, 223 + pub(crate) id: Uuid, 224 + pub(crate) username: String, 225 + pub(crate) max_megabytes: i64, 226 + pub(crate) user_megabytes: f64, 227 + pub(crate) is_admin: bool, 269 228 } 270 229 230 + /// A file listing, as it is transferred to the client. 271 231 #[derive(Serialize)] 272 232 #[serde(crate = "rocket::serde")] 273 233 pub(crate) struct File { 274 - id: Uuid, 275 - owner: Option<String>, 276 - filename: String, 277 - size_mb: i32, 234 + pub(crate) id: Uuid, 235 + pub(crate) owner: Option<String>, 236 + pub(crate) filename: String, 237 + // these are in mb's as initially I was thinking of setting 1mb as minimum... I am so dumb. 238 + // However, because they are a floating point number instead of an int nowadays, they can do much lower too. 239 + pub(crate) size_mb: f64, 278 240 } 279 241 280 242 #[post("/user/fetch", data = "<single_identify>")]