Begining of a RON API to edit profile
authorGreg Burri <greg.burri@gmail.com>
Thu, 14 Nov 2024 00:59:40 +0000 (01:59 +0100)
committerGreg Burri <greg.burri@gmail.com>
Thu, 14 Nov 2024 00:59:40 +0000 (01:59 +0100)
13 files changed:
Cargo.lock
backend/src/data/db.rs
backend/src/main.rs
backend/src/ron_extractor.rs [new file with mode: 0644]
backend/src/services.rs
backend/src/services/ron_api.rs [new file with mode: 0644]
backend/src/services/webapi.rs [deleted file]
backend/templates/base_with_header.html
backend/templates/edit_recipe.html [deleted file]
backend/templates/profile.html
backend/templates/recipe_edit.html [new file with mode: 0644]
common/src/ron_api.rs
deploy.nu

index 0a841ab..fc305e6 100644 (file)
@@ -40,9 +40,9 @@ dependencies = [
 
 [[package]]
 name = "allocator-api2"
-version = "0.2.19"
+version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "611cc2ae7d2e242c457e4be7f97036b8ad9ca152b499f53faf99b1ed8fc2553f"
+checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
 
 [[package]]
 name = "android-tzdata"
@@ -381,9 +381,9 @@ checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
 
 [[package]]
 name = "cc"
-version = "1.1.37"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
+checksum = "1aeb932158bd710538c73702db6945cb68a8fb08c519e6e12706b94263b36db8"
 dependencies = [
  "shlex",
 ]
@@ -420,9 +420,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.20"
+version = "4.5.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
+checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -430,9 +430,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.20"
+version = "4.5.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
+checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
 dependencies = [
  "anstream",
  "anstyle",
@@ -454,9 +454,9 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
 
 [[package]]
 name = "colorchoice"
@@ -542,9 +542,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.14"
+version = "0.2.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
+checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6"
 dependencies = [
  "libc",
 ]
@@ -1640,9 +1640,9 @@ dependencies = [
 
 [[package]]
 name = "psm"
-version = "0.1.23"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205"
+checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810"
 dependencies = [
  "cc",
 ]
@@ -1712,7 +1712,7 @@ dependencies = [
  "ron",
  "serde",
  "sqlx",
- "thiserror 2.0.1",
+ "thiserror 2.0.3",
  "tokio",
  "tower",
  "tower-http",
@@ -1737,7 +1737,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-automata 0.4.8",
+ "regex-automata 0.4.9",
  "regex-syntax 0.8.5",
 ]
 
@@ -1752,9 +1752,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.8"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1828,9 +1828,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
 
 [[package]]
 name = "rustix"
-version = "0.38.39"
+version = "0.38.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee"
+checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
 dependencies = [
  "bitflags",
  "errno",
@@ -1900,18 +1900,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "serde"
-version = "1.0.214"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.214"
+version = "1.0.215"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2121,7 +2121,7 @@ dependencies = [
  "sha2",
  "smallvec",
  "sqlformat",
- "thiserror 1.0.68",
+ "thiserror 1.0.69",
  "tokio",
  "tokio-stream",
  "tracing",
@@ -2205,7 +2205,7 @@ dependencies = [
  "smallvec",
  "sqlx-core",
  "stringprep",
- "thiserror 1.0.68",
+ "thiserror 1.0.69",
  "tracing",
  "whoami",
 ]
@@ -2244,7 +2244,7 @@ dependencies = [
  "smallvec",
  "sqlx-core",
  "stringprep",
- "thiserror 1.0.68",
+ "thiserror 1.0.69",
  "tracing",
  "whoami",
 ]
@@ -2364,27 +2364,27 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.68"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892"
+checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
 dependencies = [
- "thiserror-impl 1.0.68",
+ "thiserror-impl 1.0.69",
 ]
 
 [[package]]
 name = "thiserror"
-version = "2.0.1"
+version = "2.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07c1e40dd48a282ae8edc36c732cbc219144b87fb6a4c7316d611c6b1f06ec0c"
+checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
 dependencies = [
- "thiserror-impl 2.0.1",
+ "thiserror-impl 2.0.3",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.68"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e"
+checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2393,9 +2393,9 @@ dependencies = [
 
 [[package]]
 name = "thiserror-impl"
-version = "2.0.1"
+version = "2.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "874aa7e446f1da8d9c3a5c95b1c5eb41d800045252121dc7f8e0ba370cee55f5"
+checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
 dependencies = [
  "proc-macro2",
  "quote",
index 3e6b291..8fccd78 100644 (file)
@@ -251,6 +251,15 @@ FROM [UserLoginToken] WHERE [token] = $1
             .map_err(DBError::from)
     }
 
+    pub async fn set_user_name(&self, user_id: i64, name: &str) -> Result<()> {
+        sqlx::query("UPDATE [User] SET [name] = $2 WHERE [id] = $1")
+            .bind(user_id)
+            .bind(name)
+            .execute(&self.pool)
+            .await?;
+        Ok(())
+    }
+
     pub async fn sign_up(&self, email: &str, password: &str) -> Result<SignUpResult> {
         self.sign_up_with_given_time(email, password, Utc::now())
             .await
index 03e0977..2394670 100644 (file)
@@ -4,7 +4,7 @@ use axum::{
     extract::{ConnectInfo, FromRef, Request, State},
     middleware::{self, Next},
     response::{Response, Result},
-    routing::get,
+    routing::{get, post, put},
     Router,
 };
 use axum_extra::extract::cookie::CookieJar;
@@ -22,6 +22,7 @@ mod data;
 mod email;
 mod hash;
 mod model;
+mod ron_extractor;
 mod services;
 mod utils;
 
@@ -81,7 +82,6 @@ async fn main() {
             get(services::sign_up_get).post(services::sign_up_post),
         )
         .route("/validation", get(services::sign_up_validation))
-        .route("/recipe/view/:id", get(services::view_recipe))
         .route(
             "/signin",
             get(services::sign_in_get).post(services::sign_in_post),
@@ -95,6 +95,9 @@ async fn main() {
             "/reset_password",
             get(services::reset_password_get).post(services::reset_password_post),
         )
+        .route("/recipe/view/:id", get(services::view_recipe))
+        // RON API.
+        .route("/user/set_name", put(services::ron_api::set_user_name))
         .layer(TraceLayer::new_for_http())
         .route_layer(middleware::from_fn_with_state(
             state.clone(),
diff --git a/backend/src/ron_extractor.rs b/backend/src/ron_extractor.rs
new file mode 100644 (file)
index 0000000..8f52ec6
--- /dev/null
@@ -0,0 +1,102 @@
+use axum::{
+    async_trait,
+    body::Bytes,
+    extract::{FromRequest, Request},
+    http::{header, StatusCode},
+    response::{IntoResponse, Response},
+};
+use ron::{
+    de::from_bytes,
+    ser::{to_string_pretty, PrettyConfig},
+};
+use serde::{de::DeserializeOwned, Serialize};
+
+const RON_CONTENT_TYPE: &'static str = "application/ron";
+
+#[derive(Debug, Serialize, Clone)]
+pub struct RonError {
+    pub error: String,
+}
+
+impl axum::response::IntoResponse for RonError {
+    fn into_response(self) -> Response {
+        let ron_as_str = to_string_pretty(&self, PrettyConfig::new()).unwrap();
+        ron_as_str.into_response()
+    }
+}
+
+impl From<RonError> for Response {
+    fn from(value: RonError) -> Self {
+        value.into_response()
+    }
+}
+
+pub fn ron_error(status: StatusCode, message: &str) -> impl IntoResponse {
+    (
+        status,
+        [(header::CONTENT_TYPE, RON_CONTENT_TYPE)],
+        RonError {
+            error: message.to_string(),
+        },
+    )
+}
+
+pub fn ron_response<T>(ron: T) -> impl IntoResponse
+where
+    T: Serialize,
+{
+    let ron_as_str = to_string_pretty(&ron, PrettyConfig::new()).unwrap();
+    ([(header::CONTENT_TYPE, RON_CONTENT_TYPE)], ron_as_str)
+}
+
+fn parse_body<T>(body: Bytes) -> Result<T, RonError>
+where
+    T: DeserializeOwned,
+{
+    match from_bytes::<T>(&body) {
+        Ok(ron) => Ok(ron),
+        Err(error) => {
+            return Err(RonError {
+                error: format!("Ron parsing error: {}", error),
+            });
+        }
+    }
+}
+
+pub struct ExtractRon<T: DeserializeOwned>(pub T);
+
+#[async_trait]
+impl<S, T> FromRequest<S> for ExtractRon<T>
+where
+    S: Send + Sync,
+    T: DeserializeOwned,
+{
+    type Rejection = Response; // axum::Error::ErrorResponse;
+
+    async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
+        match req.headers().get(header::CONTENT_TYPE) {
+            Some(content_type) => {
+                if content_type != RON_CONTENT_TYPE {
+                    return Err(ron_error(
+                        StatusCode::BAD_REQUEST,
+                        &format!("Invalid content type, must be {}", RON_CONTENT_TYPE),
+                    )
+                    .into_response());
+                }
+            }
+            None => {
+                return Err(
+                    ron_error(StatusCode::BAD_REQUEST, "No content type given").into_response()
+                )
+            }
+        }
+
+        let body = Bytes::from_request(req, state)
+            .await
+            .map_err(IntoResponse::into_response)?;
+
+        let ron = parse_body(body)?;
+
+        Ok(Self(ron))
+    }
+}
index 243dfe5..eee0117 100644 (file)
@@ -4,7 +4,7 @@ use askama::Template;
 use axum::{
     body::Body,
     debug_handler,
-    extract::{connect_info, ConnectInfo, Extension, Host, Path, Query, Request, State},
+    extract::{ConnectInfo, Extension, Host, Path, Query, Request, State},
     http::{HeaderMap, StatusCode},
     response::{IntoResponse, Redirect, Response, Result},
     Form,
@@ -14,14 +14,9 @@ use chrono::Duration;
 use serde::Deserialize;
 use tracing::{event, Level};
 
-use crate::{
-    config::Config,
-    consts::{self, VALIDATION_PASSWORD_RESET_TOKEN_DURATION},
-    data::db,
-    email, model, utils, AppState,
-};
+use crate::{config::Config, consts, data::db, email, model, utils, AppState};
 
-pub mod webapi;
+pub mod ron_api;
 
 impl axum::response::IntoResponse for db::DBError {
     fn into_response(self) -> Response {
@@ -623,8 +618,6 @@ pub async fn ask_reset_password_post(
 struct ResetPasswordTemplate {
     user: Option<model::User>,
     reset_token: String,
-    password_1: String,
-    password_2: String,
     message: String,
     message_password: String,
 }
@@ -638,8 +631,6 @@ pub async fn reset_password_get(
         Ok(ResetPasswordTemplate {
             user,
             reset_token: reset_token.to_string(),
-            password_1: String::new(),
-            password_2: String::new(),
             message: String::new(),
             message_password: String::new(),
         }
@@ -681,8 +672,6 @@ pub async fn reset_password_post(
         Ok(ResetPasswordTemplate {
             user,
             reset_token: form_data.reset_token.clone(),
-            password_1: String::new(),
-            password_2: String::new(),
             message_password: match error {
                 ResetPasswordError::PasswordsNotEqual => "Passwords don't match",
                 ResetPasswordError::InvalidPassword => {
@@ -731,6 +720,16 @@ pub async fn reset_password_post(
     }
 }
 
+///// EDIT PROFILE /////
+
+#[debug_handler]
+pub async fn edit_user(
+    State(connection): State<db::Connection>,
+    Extension(user): Extension<Option<model::User>>,
+) -> Result<impl IntoResponse> {
+    Ok("todo")
+}
+
 ///// 404 /////
 #[debug_handler]
 pub async fn not_found() -> Result<impl IntoResponse> {
diff --git a/backend/src/services/ron_api.rs b/backend/src/services/ron_api.rs
new file mode 100644 (file)
index 0000000..b92b943
--- /dev/null
@@ -0,0 +1,95 @@
+// use actix_web::{
+//     http::{header, header::ContentType, StatusCode},
+//     post, put, web, HttpMessage, HttpRequest, HttpResponse, Responder,
+// };
+// use log::{debug, error, info, log_enabled, Level};
+// use ron::de::from_bytes;
+
+// use super::Result;
+// use crate::data::db;
+
+// #[put("/ron-api/recipe/set-title")]
+// pub async fn set_recipe_title(
+//     req: HttpRequest,
+//     body: web::Bytes,
+//     connection: web::Data<db::Connection>,
+// ) -> Result<HttpResponse> {
+//     let ron_req: common::ron_api::SetRecipeTitle = from_bytes(&body)?;
+//     connection
+//         .set_recipe_title_async(ron_req.recipe_id, &ron_req.title)
+//         .await?;
+//     Ok(HttpResponse::Ok().finish())
+// }
+
+// #[put("/ron-api/recipe/set-description")]
+// pub async fn set_recipe_description(
+//     req: HttpRequest,
+//     body: web::Bytes,
+//     connection: web::Data<db::Connection>,
+// ) -> Result<HttpResponse> {
+//     let ron_req: common::ron_api::SetRecipeDescription = from_bytes(&body)?;
+//     connection
+//         .set_recipe_description_async(ron_req.recipe_id, &ron_req.description)
+//         .await?;
+//     Ok(HttpResponse::Ok().finish())
+// }
+
+// #[put("/ron-api/recipe/add-image)]
+// #[put("/ron-api/recipe/rm-photo")]
+// #[put("/ron-api/recipe/add-ingredient")]
+// #[put("/ron-api/recipe/rm-ingredient")]
+// #[put("/ron-api/recipe/set-ingredients-order")]
+// #[put("/ron-api/recipe/add-group")]
+// #[put("/ron-api/recipe/rm-group")]
+// #[put("/ron-api/recipe/set-groups-order")]
+// #[put("/ron-api/recipe/add-step")]
+// #[put("/ron-api/recipe/rm-step")]
+// #[put("/ron-api/recipe/set-steps-order")]
+
+use askama_axum::IntoResponse;
+use axum::{
+    debug_handler,
+    extract::{Extension, State},
+    http::StatusCode,
+    response::ErrorResponse,
+    response::Result,
+};
+use tracing::{event, Level};
+
+use crate::{
+    data::db,
+    model,
+    ron_extractor::{ron_error, ron_response, ExtractRon},
+};
+
+#[debug_handler]
+pub async fn set_user_name(
+    State(connection): State<db::Connection>,
+    Extension(user): Extension<Option<model::User>>,
+    ExtractRon(ron): ExtractRon<common::ron_api::SetProfileName>,
+) -> Result<StatusCode> {
+    if let Some(user) = user {
+        connection.set_user_name(user.id, &ron.name).await?;
+    } else {
+        return Err(ErrorResponse::from(ron_error(
+            StatusCode::UNAUTHORIZED,
+            "Action not authorized",
+        )));
+    }
+    Ok(StatusCode::OK)
+}
+
+/* Example with RON return value.
+#[debug_handler]
+pub async fn set_user_name(
+    State(connection): State<db::Connection>,
+    Extension(user): Extension<Option<model::User>>,
+    ExtractRon(ron): ExtractRon<common::ron_api::SetProfileName>,
+) -> Result<impl IntoResponse> {
+
+
+    Ok(ron_response(common::ron_api::SetProfileName {
+        name: "abc".to_string(),
+    }))
+}
+*/
diff --git a/backend/src/services/webapi.rs b/backend/src/services/webapi.rs
deleted file mode 100644 (file)
index 93836a2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-// use actix_web::{
-//     http::{header, header::ContentType, StatusCode},
-//     post, put, web, HttpMessage, HttpRequest, HttpResponse, Responder,
-// };
-// use log::{debug, error, info, log_enabled, Level};
-// use ron::de::from_bytes;
-
-// use super::Result;
-// use crate::data::db;
-
-// #[put("/ron-api/recipe/set-title")]
-// pub async fn set_recipe_title(
-//     req: HttpRequest,
-//     body: web::Bytes,
-//     connection: web::Data<db::Connection>,
-// ) -> Result<HttpResponse> {
-//     let ron_req: common::ron_api::SetRecipeTitle = from_bytes(&body)?;
-//     connection
-//         .set_recipe_title_async(ron_req.recipe_id, &ron_req.title)
-//         .await?;
-//     Ok(HttpResponse::Ok().finish())
-// }
-
-// #[put("/ron-api/recipe/set-description")]
-// pub async fn set_recipe_description(
-//     req: HttpRequest,
-//     body: web::Bytes,
-//     connection: web::Data<db::Connection>,
-// ) -> Result<HttpResponse> {
-//     let ron_req: common::ron_api::SetRecipeDescription = from_bytes(&body)?;
-//     connection
-//         .set_recipe_description_async(ron_req.recipe_id, &ron_req.description)
-//         .await?;
-//     Ok(HttpResponse::Ok().finish())
-// }
-
-// #[put("/ron-api/recipe/add-image)]
-// #[put("/ron-api/recipe/rm-photo")]
-// #[put("/ron-api/recipe/add-ingredient")]
-// #[put("/ron-api/recipe/rm-ingredient")]
-// #[put("/ron-api/recipe/set-ingredients-order")]
-// #[put("/ron-api/recipe/add-group")]
-// #[put("/ron-api/recipe/rm-group")]
-// #[put("/ron-api/recipe/set-groups-order")]
-// #[put("/ron-api/recipe/add-step")]
-// #[put("/ron-api/recipe/rm-step")]
-// #[put("/ron-api/recipe/set-steps-order")]
index 8dc71bd..f758547 100644 (file)
@@ -7,7 +7,7 @@
         {% match user %}
         {% when Some with (user) %}
             <a class="create-recipe" href="/recipe/new" >Create a new recipe</a>
-            <span><a href="/edit_profile">{{ user.email }}</a> / <a href="/signout" />Sign out</a></span>
+            <span><a href="/user/edit">{{ user.email }}</a> / <a href="/signout" />Sign out</a></span>
         {% when None %}
             <span>
                 <a href="/signin" >Sign in</a>/<a href="/signup">Sign up</a>/<a href="/ask_reset_password">Lost password</a>
diff --git a/backend/templates/edit_recipe.html b/backend/templates/edit_recipe.html
deleted file mode 100644 (file)
index f999c41..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends "base_with_list.html" %}
-
-{% block content %}
-<label for="title_field">Title</label>
-<input
-    id="title_field"
-    type="text"
-    name="title"
-    value="{{ current_recipe.title }}"
-    autocapitalize="none"
-    autocomplete="title"
-    autofocus="autofocus" />
-
-<label for="description_field">Description</label>
-<input
-    id="title_field"
-    type="text"
-    name="title"
-    value="{{ current_recipe.description }}"
-    autocapitalize="none"
-    autocomplete="title"
-    autofocus="autofocus" />
-{% endblock %}
\ No newline at end of file
index f999c41..9dc573c 100644 (file)
@@ -1,22 +1,12 @@
 {% extends "base_with_list.html" %}
 
 {% block content %}
-<label for="title_field">Title</label>
+<label for="title_field">Name</label>
 <input
-    id="title_field"
+    id="name_field"
     type="text"
-    name="title"
-    value="{{ current_recipe.title }}"
-    autocapitalize="none"
-    autocomplete="title"
-    autofocus="autofocus" />
-
-<label for="description_field">Description</label>
-<input
-    id="title_field"
-    type="text"
-    name="title"
-    value="{{ current_recipe.description }}"
+    name="name"
+    value="{{ user.name }}"
     autocapitalize="none"
     autocomplete="title"
     autofocus="autofocus" />
diff --git a/backend/templates/recipe_edit.html b/backend/templates/recipe_edit.html
new file mode 100644 (file)
index 0000000..f999c41
--- /dev/null
@@ -0,0 +1,23 @@
+{% extends "base_with_list.html" %}
+
+{% block content %}
+<label for="title_field">Title</label>
+<input
+    id="title_field"
+    type="text"
+    name="title"
+    value="{{ current_recipe.title }}"
+    autocapitalize="none"
+    autocomplete="title"
+    autofocus="autofocus" />
+
+<label for="description_field">Description</label>
+<input
+    id="title_field"
+    type="text"
+    name="title"
+    value="{{ current_recipe.description }}"
+    autocapitalize="none"
+    autocomplete="title"
+    autofocus="autofocus" />
+{% endblock %}
\ No newline at end of file
index 1d50b12..ce7b2d1 100644 (file)
@@ -1,5 +1,7 @@
 use serde::{Deserialize, Serialize};
 
+///// RECIPE /////
+
 #[derive(Serialize, Deserialize, Clone)]
 pub struct SetRecipeTitle {
     pub recipe_id: i64,
@@ -91,3 +93,10 @@ pub struct AddRecipeStepReply {
 pub struct RemoveRecipeStep {
     pub step_id: i64,
 }
+
+///// PROFILE /////
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct SetProfileName {
+    pub name: String,
+}
index 3cb718a..684ad0b 100644 (file)
--- a/deploy.nu
+++ b/deploy.nu
@@ -17,6 +17,7 @@ def main [host: string, destination: string, ssh_key: path] {
         scp ...$args
     }
 
+    cargo test
     cargo build --target $target --release
     invoke_ssh [sudo systemctl stop recipes]
     copy_ssh ./target/($target)/release/recipes $destination