Просмотр исходного кода

Create route to rotate api key for homes.

Lee Morgan 2 месяцев назад
Родитель
Сommit
0b995de80c

+ 6 - 0
docs/paths/home/rotate_key.yaml

@@ -19,8 +19,14 @@ requestBody:
       schema:
         type: object
         required:
+          - email
           - password
         properties:
+          email:
+            type: string
+            format: email
+            description: Email of user that is admin for home
+            example: john.smith@mail.com
           password:
             type: string
             description: Current user password

+ 3 - 1
sql/homes.sql

@@ -3,4 +3,6 @@ CREATE TABLE IF NOT EXISTS homes (
     api_key UUID NOT NULL UNIQUE,
     name TEXT NOT NULL,
     created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
-)
+);
+
+CREATE INDEX api_key_idx ON homes (api_key);

+ 1 - 0
src/controllers/home/mod.rs

@@ -1,3 +1,4 @@
 pub mod create;
 pub mod delete;
 pub mod get_many;
+pub mod rotate_key;

+ 35 - 0
src/controllers/home/rotate_key.rs

@@ -0,0 +1,35 @@
+use actix_web::{HttpResponse, web, post};
+use serde::Deserialize;
+use sqlx::PgPool;
+use uuid::Uuid;
+use serde_json::json;
+use crate::{
+    app_error::AppError,
+    logic::compare_password,
+    models::{
+        user::User,
+        home::Home
+    }
+};
+
+#[derive(Deserialize)]
+struct Body {
+    email: String,
+    password: String
+}
+
+#[post("/home/{home_id}/apikey")]
+pub async fn route(
+    db: web::Data<PgPool>,
+    params: web::Path<String>,
+    body: web::Json<Body>
+) -> Result<HttpResponse, AppError> {
+    let body = body.into_inner();
+    let email = body.email.to_lowercase();
+    let user = User::find_one_by_email(&db, &email).await?;
+    compare_password(&body.password, &user.pass_hash)?;
+    let home_id = Uuid::parse_str(&params.into_inner())?;
+    let new_key = Uuid::now_v7();
+    Home::update_api_key(&db, home_id, new_key).await?;
+    Ok(HttpResponse::Ok().json(json!({"success": true})))
+}

+ 1 - 17
src/controllers/user/login.rs

@@ -2,17 +2,10 @@ use actix_web::{HttpResponse, web, post};
 use serde::Deserialize;
 use serde_json::json;
 use sqlx::PgPool;
-use argon2::{
-    Argon2,
-    password_hash::{
-        PasswordHash,
-        PasswordVerifier
-    }
-};
 use crate::{
     app_error::AppError,
     models::user::User,
-    logic::create_cookie
+    logic::{create_cookie, compare_password}
 };
 
 #[derive(Deserialize)]
@@ -32,12 +25,3 @@ pub async fn route(
     let cookie = create_cookie("user".to_string(), user.id.to_string());
     Ok(HttpResponse::Ok().cookie(cookie).json(json!({"success": true})))
 }
-
-fn compare_password(pass: &String, hash: &String) -> Result<(), AppError> {
-    let parsed_hash = PasswordHash::new(hash)
-        .map_err(|e| AppError::InternalError(e.to_string()))?;
-
-    Argon2::default()
-        .verify_password(pass.as_bytes(), &parsed_hash)
-       .map_err(|_| AppError::Auth)
-}

+ 17 - 0
src/logic/compare_password.rs

@@ -0,0 +1,17 @@
+use argon2::{
+    Argon2,
+    password_hash::{
+        PasswordHash,
+        PasswordVerifier
+    }
+};
+use crate::app_error::AppError;
+
+pub fn compare_password(pass: &String, hash: &String) -> Result<(), AppError> {
+    let parsed_hash = PasswordHash::new(hash)
+        .map_err(|e| AppError::InternalError(e.to_string()))?;
+
+    Argon2::default()
+        .verify_password(pass.as_bytes(), &parsed_hash)
+        .map_err(|_| AppError::Auth)
+}

+ 2 - 0
src/logic/mod.rs

@@ -1,5 +1,7 @@
 pub mod create_cookie;
 pub mod remove_cookie;
+pub mod compare_password;
 
 pub use create_cookie::create_cookie;
 pub use remove_cookie::remove_cookie;
+pub use compare_password::compare_password;

+ 14 - 0
src/models/home.rs

@@ -77,4 +77,18 @@ impl Home {
 
         Ok(homes)
     }
+
+    pub async fn update_api_key(db: &PgPool, home_id: Uuid, new_key: Uuid) -> Result<(), AppError> {
+        sqlx::query(
+            "UPDATE homes
+            SET api_key = $1
+            where id = $2"
+        )
+            .bind(new_key)
+            .bind(home_id)
+            .execute(db)
+            .await?;
+
+        Ok(())
+    }
 }

+ 3 - 1
src/routes/home.rs

@@ -2,11 +2,13 @@ use actix_web::web;
 use crate::controllers::home::{
     create,
     delete,
-    get_many
+    get_many,
+    rotate_key
 };
 
 pub fn config(cfg: &mut web::ServiceConfig) {
     cfg.service(create::route);
     cfg.service(delete::route);
     cfg.service(get_many::route);
+    cfg.service(rotate_key::route);
 }