From 0ddd4ecd9ddb310b93166620acba33d2065561ca Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Fri, 9 Jun 2023 15:08:43 +0300 Subject: feat(corp/rih): persist data in storage bucket Change-Id: Ide7a21b97e845681584378d348cc36aba951d69f Reviewed-on: https://cl.tvl.fyi/c/depot/+/8730 Tested-by: BuildkiteCI Reviewed-by: tazjin --- corp/rih/backend/src/main.rs | 80 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) (limited to 'corp/rih/backend/src') 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, + 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 { + 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() + } + }); } -- cgit 1.4.1