page -> post
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Hamcha 2023-07-07 01:38:56 +02:00
parent 3d50d2b4b0
commit e626ef87dc
Signed by: hamcha
GPG key ID: 1669C533B8CF6D89
5 changed files with 59 additions and 59 deletions

View file

@ -1,4 +1,4 @@
pub mod page; pub mod post;
pub mod site; pub mod site;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]

View file

@ -7,8 +7,8 @@ use uuid::Uuid;
use super::Error; use super::Error;
#[derive(Deserialize, Serialize, FromRow)] #[derive(Deserialize, Serialize, FromRow)]
pub struct Page { pub struct Post {
/// Page ID /// Post ID
pub id: Uuid, pub id: Uuid,
/// Site ID /// Site ID
@ -17,20 +17,20 @@ pub struct Page {
/// Author ID /// Author ID
pub author: Uuid, pub author: Uuid,
/// URL-friendly short code for the page /// URL-friendly short code for the post
pub slug: String, pub slug: String,
/// Page title /// Post title
pub title: String, pub title: String,
/// Page description (for SEO/content) /// Post description (for SEO/content)
pub description: Option<String>, pub description: Option<String>,
/// Page tags (for internal search) /// Post tags (for internal search)
pub tags: Vec<String>, pub tags: Vec<String>,
/// Page blocks (content) /// Post blocks (content)
pub blocks: Json<Vec<PageBlock>>, pub blocks: Json<Vec<PostBlock>>,
/// Times /// Times
pub created_at: NaiveDateTime, pub created_at: NaiveDateTime,
@ -40,7 +40,7 @@ pub struct Page {
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
#[serde(tag = "kind")] #[serde(tag = "kind")]
pub enum PageBlock { pub enum PostBlock {
MarkupV1 { MarkupV1 {
/// Markup format (markdown, html, plain) /// Markup format (markdown, html, plain)
format: String, format: String,
@ -73,50 +73,50 @@ pub struct ImageElement {
pub caption: Option<String>, pub caption: Option<String>,
} }
/// Data to create a new page /// Data to create a new post
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct CreatePageData { pub struct CreatePostData {
pub slug: String, pub slug: String,
pub title: String, pub title: String,
pub description: Option<String>, pub description: Option<String>,
pub tags: Vec<String>, pub tags: Vec<String>,
pub blocks: Vec<PageBlock>, pub blocks: Vec<PostBlock>,
} }
/// Data to update a new page /// Data to update a new post
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct UpdatePageData { pub struct UpdatePostData {
pub slug: Option<String>, pub slug: Option<String>,
pub title: Option<String>, pub title: Option<String>,
pub description: Option<String>, pub description: Option<String>,
pub tags: Option<Vec<String>>, pub tags: Option<Vec<String>>,
pub blocks: Option<Vec<PageBlock>>, pub blocks: Option<Vec<PostBlock>>,
} }
#[async_trait] #[async_trait]
pub trait PageRepository { pub trait PostRepository {
/// Get a page from its slug /// Get a post from its slug
async fn get_page_from_url(&self, site: &str, slug: &str) -> Result<Page, Error>; async fn get_post_from_url(&self, site: &str, slug: &str) -> Result<Post, Error>;
/// Create a new page /// Create a new post
async fn create_page( async fn create_post(
&self, &self,
owner: &Uuid, owner: &Uuid,
site: &Uuid, site: &Uuid,
data: CreatePageData, data: CreatePostData,
) -> Result<(), Error>; ) -> Result<(), Error>;
/// Update a page /// Update a post
async fn update_page( async fn update_post(
&self, &self,
owner: &Uuid, owner: &Uuid,
site: &Uuid, site: &Uuid,
slug: &str, slug: &str,
data: UpdatePageData, data: UpdatePostData,
) -> Result<(), Error>; ) -> Result<(), Error>;
/// Delete a page /// Delete a post
async fn delete_page( async fn delete_post(
&self, &self,
owner: &Uuid, owner: &Uuid,
site: &Uuid, site: &Uuid,

View file

@ -3,7 +3,7 @@ use std::sync::Arc;
use crate::state::AppState; use crate::state::AppState;
pub mod page; pub mod post;
pub mod site; pub mod site;
pub struct Database { pub struct Database {

View file

@ -4,34 +4,34 @@ use uuid::Uuid;
use crate::content::{ use crate::content::{
self, self,
page::{CreatePageData, Page, PageRepository, UpdatePageData}, post::{CreatePostData, Post, PostRepository, UpdatePostData},
Error, Error,
}; };
use super::Database; use super::Database;
#[async_trait] #[async_trait]
impl PageRepository for Database { impl PostRepository for Database {
async fn get_page_from_url(&self, site: &str, slug: &str) -> Result<Page, content::Error> { async fn get_post_from_url(&self, site: &str, slug: &str) -> Result<Post, content::Error> {
let page_query = sqlx::query_as( let post_query = sqlx::query_as(
"SELECT pages.* FROM pages JOIN sites ON site = sites.id WHERE slug = $1 AND name = $2 AND pages.deleted_at IS NULL AND sites.deleted_at IS NULL") "SELECT pages.* FROM pages JOIN sites ON site = sites.id WHERE slug = $1 AND name = $2 AND pages.deleted_at IS NULL AND sites.deleted_at IS NULL")
.bind(slug) .bind(slug)
.bind(site); .bind(site);
let page: Page = page_query let post: Post = post_query
.fetch_one(&self.pool) .fetch_one(&self.pool)
.await .await
.map_err(|e| match e { .map_err(|e| match e {
sqlx::Error::RowNotFound => Error::NotFound, sqlx::Error::RowNotFound => Error::NotFound,
_ => e.into(), _ => e.into(),
})?; })?;
Ok(page) Ok(post)
} }
async fn create_page( async fn create_post(
&self, &self,
owner: &Uuid, owner: &Uuid,
site: &Uuid, site: &Uuid,
data: CreatePageData, data: CreatePostData,
) -> Result<(), Error> { ) -> Result<(), Error> {
sqlx::query!( sqlx::query!(
"INSERT INTO pages (author, site, slug, title, description, tags, blocks) VALUES ($1, $2, $3, $4, $5, $6, $7)", "INSERT INTO pages (author, site, slug, title, description, tags, blocks) VALUES ($1, $2, $3, $4, $5, $6, $7)",
@ -51,12 +51,12 @@ impl PageRepository for Database {
Ok(()) Ok(())
} }
async fn update_page( async fn update_post(
&self, &self,
owner: &Uuid, owner: &Uuid,
site: &Uuid, site: &Uuid,
page: &str, slug: &str,
data: UpdatePageData, data: UpdatePostData,
) -> Result<(), Error> { ) -> Result<(), Error> {
let result = sqlx::query!( let result = sqlx::query!(
"UPDATE pages SET title = COALESCE($1, title), description = COALESCE($2, description), tags = COALESCE($3, tags), blocks = COALESCE($4, blocks) WHERE author = $5 AND site = $6 AND slug = $7 AND deleted_at IS NULL", "UPDATE pages SET title = COALESCE($1, title), description = COALESCE($2, description), tags = COALESCE($3, tags), blocks = COALESCE($4, blocks) WHERE author = $5 AND site = $6 AND slug = $7 AND deleted_at IS NULL",
@ -66,7 +66,7 @@ impl PageRepository for Database {
data.blocks.map(|x| json!(x)), data.blocks.map(|x| json!(x)),
owner, owner,
site, site,
page slug
).execute(&self.pool).await.map_err(|err| match err { ).execute(&self.pool).await.map_err(|err| match err {
sqlx::Error::Database(dberr) if dberr.constraint() == Some("pages_site_slug_unique") => { sqlx::Error::Database(dberr) if dberr.constraint() == Some("pages_site_slug_unique") => {
Error::IdentifierNotAvailable Error::IdentifierNotAvailable
@ -81,11 +81,11 @@ impl PageRepository for Database {
Ok(()) Ok(())
} }
async fn delete_page( async fn delete_post(
&self, &self,
owner: &Uuid, owner: &Uuid,
site: &Uuid, site: &Uuid,
page: &str, slug: &str,
soft_delete: bool, soft_delete: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let result = if soft_delete { let result = if soft_delete {
@ -93,14 +93,14 @@ impl PageRepository for Database {
"UPDATE pages SET deleted_at = NOW() WHERE author = $1 AND site = $2 AND slug = $3 AND deleted_at IS NULL", "UPDATE pages SET deleted_at = NOW() WHERE author = $1 AND site = $2 AND slug = $3 AND deleted_at IS NULL",
owner, owner,
site, site,
page slug
).execute(&self.pool).await? ).execute(&self.pool).await?
} else { } else {
sqlx::query!( sqlx::query!(
"DELETE FROM pages WHERE author = $1 AND site = $2 AND slug = $3", "DELETE FROM pages WHERE author = $1 AND site = $2 AND slug = $3",
owner, owner,
site, site,
page slug
) )
.execute(&self.pool) .execute(&self.pool)
.await? .await?

View file

@ -9,7 +9,7 @@ use std::sync::Arc;
use crate::{ use crate::{
content::{ content::{
page::{CreatePageData, PageRepository, UpdatePageData}, post::{CreatePostData, PostRepository, UpdatePostData},
site::SiteRepository, site::SiteRepository,
}, },
database::Database, database::Database,
@ -17,42 +17,42 @@ use crate::{
state::AppState, state::AppState,
}; };
async fn get_page<Repo: PageRepository>( async fn get_post<Repo: PostRepository>(
repository: Repo, repository: Repo,
Path((site, slug)): Path<(String, String)>, Path((site, slug)): Path<(String, String)>,
) -> Result<impl IntoResponse, ApiError<'static>> { ) -> Result<impl IntoResponse, ApiError<'static>> {
Ok(Json(repository.get_page_from_url(&site, &slug).await?)) Ok(Json(repository.get_post_from_url(&site, &slug).await?))
} }
async fn create_page<Repo: PageRepository + SiteRepository>( async fn create_post<Repo: PostRepository + SiteRepository>(
repository: Repo, repository: Repo,
Path(site): Path<String>, Path(site): Path<String>,
RequireUser(user): RequireUser, RequireUser(user): RequireUser,
JsonBody(page): JsonBody<CreatePageData>, JsonBody(data): JsonBody<CreatePostData>,
) -> Result<impl IntoResponse, ApiError<'static>> { ) -> Result<impl IntoResponse, ApiError<'static>> {
// Resolve site // Resolve site
let site_id = repository.get_site_id(&site, &user.id).await?; let site_id = repository.get_site_id(&site, &user.id).await?;
repository.create_page(&user.id, &site_id, page).await?; repository.create_post(&user.id, &site_id, data).await?;
Ok(Json(json!({ "ok": true }))) Ok(Json(json!({ "ok": true })))
} }
async fn update_page<Repo: PageRepository + SiteRepository>( async fn update_post<Repo: PostRepository + SiteRepository>(
repository: Repo, repository: Repo,
Path((site, slug)): Path<(String, String)>, Path((site, slug)): Path<(String, String)>,
RequireUser(user): RequireUser, RequireUser(user): RequireUser,
JsonBody(page): JsonBody<UpdatePageData>, JsonBody(data): JsonBody<UpdatePostData>,
) -> Result<impl IntoResponse, ApiError<'static>> { ) -> Result<impl IntoResponse, ApiError<'static>> {
// Resolve site // Resolve site
let site_id = repository.get_site_id(&site, &user.id).await?; let site_id = repository.get_site_id(&site, &user.id).await?;
repository repository
.update_page(&user.id, &site_id, &slug, page) .update_post(&user.id, &site_id, &slug, data)
.await?; .await?;
Ok(Json(json!({ "ok": true }))) Ok(Json(json!({ "ok": true })))
} }
async fn delete_page<Repo: PageRepository + SiteRepository>( async fn delete_post<Repo: PostRepository + SiteRepository>(
repository: Repo, repository: Repo,
Path((site, slug)): Path<(String, String)>, Path((site, slug)): Path<(String, String)>,
RequireUser(user): RequireUser, RequireUser(user): RequireUser,
@ -61,18 +61,18 @@ async fn delete_page<Repo: PageRepository + SiteRepository>(
let site_id = repository.get_site_id(&site, &user.id).await?; let site_id = repository.get_site_id(&site, &user.id).await?;
repository repository
.delete_page(&user.id, &site_id, &slug, true) .delete_post(&user.id, &site_id, &slug, true)
.await?; .await?;
Ok(Json(json!({ "ok": true }))) Ok(Json(json!({ "ok": true })))
} }
pub fn router() -> Router<Arc<AppState>> { pub fn router() -> Router<Arc<AppState>> {
Router::new() Router::new()
.route("/:site", post(create_page::<Database>)) .route("/:site", post(create_post::<Database>))
.route( .route(
"/:site/:slug", "/:site/:slug",
get(get_page::<Database>) get(get_post::<Database>)
.put(update_page::<Database>) .put(update_post::<Database>)
.delete(delete_page::<Database>), .delete(delete_post::<Database>),
) )
} }