about summary refs log tree commit diff
path: root/corp/rih/backend/src
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2023-06-09T12·08+0300
committertazjin <tazjin@tvl.su>2023-06-09T12·21+0000
commit0ddd4ecd9ddb310b93166620acba33d2065561ca (patch)
tree1b5d42800a465dbd8a9e9d643b4b4db1cd5b4957 /corp/rih/backend/src
parentaea8c79ca384d5d290b138de0f2ba5af8559ee2d (diff)
feat(corp/rih): persist data in storage bucket r/6250
Change-Id: Ide7a21b97e845681584378d348cc36aba951d69f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8730
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'corp/rih/backend/src')
-rw-r--r--corp/rih/backend/src/main.rs80
1 files changed, 78 insertions, 2 deletions
diff --git a/corp/rih/backend/src/main.rs b/corp/rih/backend/src/main.rs
index 719d3c19af67..28e4e8dfde00 100644
--- a/corp/rih/backend/src/main.rs
+++ b/corp/rih/backend/src/main.rs
@@ -1,8 +1,84 @@
+use anyhow::{bail, Context, Result};
 use rouille::{Request, Response};
+use serde::{Deserialize, Serialize};
+use std::collections::BTreeSet;
 use std::env;
+use std::net::SocketAddr;
+use std::time::{SystemTime, UNIX_EPOCH};
+use uuid::Uuid;
 
-fn main() {
+/// Represents a single record as filled in by a user. This is the
+/// primary data structure we want to populate and persist somewhere.
+#[derive(Debug, Deserialize, Serialize)]
+struct Record {
+    // Record-specific metadata
+    uuid: Uuid,
+
+    // Personal information
+    name: String,
+    email: String,
+    citizenship: String, // TODO
+    personal_details: String,
+
+    // Job information
+    position: String,
+    technologies: BTreeSet<String>,
+    job_details: String,
+    work_background: String,
+}
+
+impl Record {
+    fn validate(&self) -> bool {
+        true
+    }
+}
+
+fn persist_record(ip: &SocketAddr, record: &Record) -> Result<()> {
+    let bucket_name = "rih-backend-data";
+    let credentials = s3::creds::Credentials::from_env()?;
+    let yandex_region: s3::Region = s3::Region::Custom {
+        region: "ru-central1".to_string(),
+        endpoint: "storage.yandexcloud.net".to_string(),
+    };
+
+    let bucket = s3::Bucket::new(bucket_name, yandex_region, credentials)?;
+
+    let path_uuid = Uuid::new_v4();
+    let epoch = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
+    let path = format!("/records/{}-{}.json", epoch, path_uuid);
+
+    let data = serde_json::json!({
+        "ip": ip.to_string(),
+        "record": record,
+    });
+
+    let _response = bucket.put_object(path, data.to_string().as_bytes());
+    Ok(())
+}
+
+fn handle_submit(req: &Request) -> Result<Response> {
+    let record: Record = rouille::input::json::json_input(req)?;
+
+    if !record.validate() {
+        bail!("invalid record: {:?}", record);
+    }
+
+    persist_record(req.remote_addr(), &record)?;
+
+    Ok(Response::text("success"))
+}
+
+fn main() -> Result<()> {
     let port = env::var("PORT").unwrap_or_else(|_| /* rihb = */ "7442".to_string());
     let listen = format!("0.0.0.0:{port}");
-    rouille::start_server(&listen, move |_request| Response::text("hello world"));
+    rouille::start_server(&listen, move |request| {
+        if request.url() == "/submit" {
+            match handle_submit(request) {
+                Ok(response) => response,
+                Err(_err) => Response::empty_400(), // TODO
+            }
+        } else {
+            Response::empty_404()
+        }
+    });
 }