NotFound error and add validation

This commit is contained in:
Tyler Hallada 2023-05-07 19:50:44 -04:00
parent de157a3b1e
commit f30be5f451
3 changed files with 26 additions and 8 deletions

View File

@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS "items" (
"id" SERIAL PRIMARY KEY NOT NULL,
"title" VARCHAR(255) NOT NULL,
"url" VARCHAR(255) NOT NULL,
"description" VARCHAR(255),
"url" VARCHAR(2048) NOT NULL,
"description" TEXT,
"created_at" timestamp(3) NOT NULL,
"updated_at" timestamp(3) NOT NULL,
"deleted_at" timestamp(3)

View File

@ -21,8 +21,13 @@ pub enum Error {
#[error("validation error in request body")]
InvalidEntity(#[from] ValidationErrors),
#[error("{0} not found")]
NotFound(&'static str),
}
pub type Result<T, E = Error> = ::std::result::Result<T, E>;
impl IntoResponse for Error {
fn into_response(self) -> Response {
#[serde_with::serde_as]
@ -59,7 +64,7 @@ impl Error {
use Error::*;
match self {
Sqlx(sqlx::Error::RowNotFound) => StatusCode::NOT_FOUND,
NotFound(_) => StatusCode::NOT_FOUND,
Sqlx(_) | Anyhow(_) => StatusCode::INTERNAL_SERVER_ERROR,
InvalidEntity(_) => StatusCode::UNPROCESSABLE_ENTITY,
}

View File

@ -1,6 +1,9 @@
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use validator::Validate;
use crate::error::{Error, Result};
#[derive(Debug, Serialize, Deserialize)]
pub struct Item {
@ -13,17 +16,26 @@ pub struct Item {
deleted_at: Option<NaiveDateTime>,
}
#[derive(Deserialize)]
#[derive(Debug, Deserialize, Validate)]
pub struct CreateItem {
#[validate(length(max = 255))]
title: String,
#[validate(url)]
url: String,
#[validate(length(max = 524288))]
description: Option<String>,
}
pub async fn get_item(pool: PgPool, id: i32) -> sqlx::Result<Item> {
pub async fn get_item(pool: PgPool, id: i32) -> Result<Item> {
sqlx::query_as!(Item, "SELECT * FROM items WHERE id = $1", id)
.fetch_one(&pool)
.await
.map_err(|error| {
if let sqlx::error::Error::RowNotFound = error {
return Error::NotFound("item");
}
Error::Sqlx(error)
})
}
pub async fn get_items(pool: PgPool) -> sqlx::Result<Vec<Item>> {
@ -32,8 +44,9 @@ pub async fn get_items(pool: PgPool) -> sqlx::Result<Vec<Item>> {
.await
}
pub async fn create_item(pool: PgPool, payload: CreateItem) -> sqlx::Result<Item> {
sqlx::query_as!(
pub async fn create_item(pool: PgPool, payload: CreateItem) -> Result<Item> {
payload.validate()?;
Ok(sqlx::query_as!(
Item,
"INSERT INTO items (
title, url, description, created_at, updated_at
@ -45,5 +58,5 @@ pub async fn create_item(pool: PgPool, payload: CreateItem) -> sqlx::Result<Item
payload.description
)
.fetch_one(&pool)
.await
.await?)
}