feat: test for unique event names and return event IDs on update API calls
This commit is contained in:
parent
f89b3e6d4c
commit
20c3ee1f11
4 changed files with 115 additions and 8 deletions
|
@ -1,5 +1,20 @@
|
||||||
{
|
{
|
||||||
"db": "PostgreSQL",
|
"db": "PostgreSQL",
|
||||||
|
"14cdc724af64942e93994f97e9eafc8272d15605eff7aab9e5177d01f2bf6118": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"nullable": [],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text",
|
||||||
|
"Timestamptz",
|
||||||
|
"Text",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "INSERT INTO librepages_site_deploy_events\n (event_type, time, site, pub_id) VALUES (\n (SELECT iD from librepages_deploy_event_type WHERE name = $1),\n $2,\n (SELECT ID from librepages_sites WHERE hostname = $3),\n $4\n );\n "
|
||||||
|
},
|
||||||
"1ac91b492001493430c686d9cd7d6be03ada4b4c431d7bc112ef2105eba0e82d": {
|
"1ac91b492001493430c686d9cd7d6be03ada4b4c431d7bc112ef2105eba0e82d": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
@ -97,6 +112,39 @@
|
||||||
},
|
},
|
||||||
"query": "SELECT EXISTS (SELECT 1 from librepages_sites WHERE hostname = $1)"
|
"query": "SELECT EXISTS (SELECT 1 from librepages_sites WHERE hostname = $1)"
|
||||||
},
|
},
|
||||||
|
"39854fcbfb0247377c6c5ca70c2c0fa7804548848bf56f881eea2f8242e7a09d": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "time",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pub_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text",
|
||||||
|
"Uuid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "SELECT\n librepages_deploy_event_type.name,\n librepages_site_deploy_events.time,\n librepages_site_deploy_events.pub_id\n FROM\n librepages_site_deploy_events\n INNER JOIN librepages_deploy_event_type ON\n librepages_deploy_event_type.ID = librepages_site_deploy_events.event_type\n WHERE\n librepages_site_deploy_events.site = (\n SELECT ID FROM librepages_sites WHERE hostname = $1\n )\n AND\n librepages_site_deploy_events.pub_id = $2\n "
|
||||||
|
},
|
||||||
"416b9f0412f0d7ee05d4a350839c5a6d1e06c1d7f8942744f6d806ddc47084c2": {
|
"416b9f0412f0d7ee05d4a350839c5a6d1e06c1d7f8942744f6d806ddc47084c2": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
|
@ -347,6 +395,38 @@
|
||||||
},
|
},
|
||||||
"query": "SELECT email FROM librepages_users WHERE name = $1"
|
"query": "SELECT email FROM librepages_users WHERE name = $1"
|
||||||
},
|
},
|
||||||
|
"d2327c1bcb40e18518c2112413a19a9b26eb0f54f83c53e968c9752d70c8dd4e": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "name",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Varchar"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "time",
|
||||||
|
"ordinal": 1,
|
||||||
|
"type_info": "Timestamptz"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "pub_id",
|
||||||
|
"ordinal": 2,
|
||||||
|
"type_info": "Uuid"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Text"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "SELECT\n librepages_deploy_event_type.name,\n librepages_site_deploy_events.time,\n librepages_site_deploy_events.pub_id\n FROM\n librepages_site_deploy_events\n INNER JOIN librepages_deploy_event_type ON\n librepages_deploy_event_type.ID = librepages_site_deploy_events.event_type\n WHERE\n librepages_site_deploy_events.site = (\n SELECT ID FROM librepages_sites WHERE hostname = $1\n );\n "
|
||||||
|
},
|
||||||
"e4adf1bc9175eeb9d61b495653bb452039cc38818c8792acdc6a1c732b6f4554": {
|
"e4adf1bc9175eeb9d61b495653bb452039cc38818c8792acdc6a1c732b6f4554": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
@ -367,7 +447,7 @@
|
||||||
},
|
},
|
||||||
"query": "SELECT EXISTS (SELECT 1 from librepages_deploy_event_type WHERE name = $1)"
|
"query": "SELECT EXISTS (SELECT 1 from librepages_deploy_event_type WHERE name = $1)"
|
||||||
},
|
},
|
||||||
"ed935cd75e805ddd7223ea8ba298ff94018cf305c519120279a5d1f7bb99e23e": {
|
"f651da8f411b7977cb87dd8d4bd5d167661d7ef1d865747e76219453d386d593": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [],
|
"columns": [],
|
||||||
"nullable": [],
|
"nullable": [],
|
||||||
|
@ -377,7 +457,7 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"query": "INSERT INTO librepages_deploy_event_type\n (name) VALUES ($1);"
|
"query": "INSERT INTO librepages_deploy_event_type\n (name) VALUES ($1) ON CONFLICT (name) DO NOTHING;"
|
||||||
},
|
},
|
||||||
"faa4170a309f19a4abf1ca3f8dd3c0526945aa00f028ebf8bd7063825d448f5b": {
|
"faa4170a309f19a4abf1ca3f8dd3c0526945aa00f028ebf8bd7063825d448f5b": {
|
||||||
"describe": {
|
"describe": {
|
||||||
|
|
|
@ -17,8 +17,10 @@
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::ctx::Ctx;
|
use crate::ctx::Ctx;
|
||||||
|
use crate::db;
|
||||||
use crate::db::Site;
|
use crate::db::Site;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::page::Page;
|
use crate::page::Page;
|
||||||
|
@ -58,10 +60,13 @@ impl Ctx {
|
||||||
if let Some(_config) = page_config::Config::load(&page.path, &page.branch) {
|
if let Some(_config) = page_config::Config::load(&page.path, &page.branch) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
self.db
|
||||||
|
.log_event(&page.domain, &db::EVENT_TYPE_CREATE)
|
||||||
|
.await?;
|
||||||
Ok(page)
|
Ok(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_site(&self, secret: &str, branch: Option<String>) -> ServiceResult<()> {
|
pub async fn update_site(&self, secret: &str, branch: Option<String>) -> ServiceResult<Uuid> {
|
||||||
if let Ok(db_site) = self.db.get_site_from_secret(secret).await {
|
if let Ok(db_site) = self.db.get_site_from_secret(secret).await {
|
||||||
let page = Page::from_site(&self.settings, db_site);
|
let page = Page::from_site(&self.settings, db_site);
|
||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
|
@ -81,7 +86,10 @@ impl Ctx {
|
||||||
if let Some(_config) = page_config::Config::load(&page.path, &page.branch) {
|
if let Some(_config) = page_config::Config::load(&page.path, &page.branch) {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
Ok(())
|
println!("{}", page.domain);
|
||||||
|
self.db
|
||||||
|
.log_event(&page.domain, &db::EVENT_TYPE_UPDATE)
|
||||||
|
.await
|
||||||
} else {
|
} else {
|
||||||
Err(ServiceError::WebsiteNotFound)
|
Err(ServiceError::WebsiteNotFound)
|
||||||
}
|
}
|
||||||
|
|
12
src/db.rs
12
src/db.rs
|
@ -408,7 +408,7 @@ impl Database {
|
||||||
if !self.event_type_exists(&e).await? {
|
if !self.event_type_exists(&e).await? {
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"INSERT INTO librepages_deploy_event_type
|
"INSERT INTO librepages_deploy_event_type
|
||||||
(name) VALUES ($1);",
|
(name) VALUES ($1) ON CONFLICT (name) DO NOTHING;",
|
||||||
e.name
|
e.name
|
||||||
)
|
)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
|
@ -603,7 +603,7 @@ pub const EVENT_TYPE_CREATE: Event = Event::new("site.event.create");
|
||||||
pub const EVENT_TYPE_UPDATE: Event = Event::new("site.event.update");
|
pub const EVENT_TYPE_UPDATE: Event = Event::new("site.event.update");
|
||||||
pub const EVENT_TYPE_DELETE: Event = Event::new("site.event.delete");
|
pub const EVENT_TYPE_DELETE: Event = Event::new("site.event.delete");
|
||||||
|
|
||||||
pub const EVENTS: [Event; 3] = [EVENT_TYPE_DELETE, EVENT_TYPE_DELETE, EVENT_TYPE_CREATE];
|
pub const EVENTS: [Event; 3] = [EVENT_TYPE_CREATE, EVENT_TYPE_DELETE, EVENT_TYPE_UPDATE];
|
||||||
|
|
||||||
struct InnerLibrepagesEvent {
|
struct InnerLibrepagesEvent {
|
||||||
name: String,
|
name: String,
|
||||||
|
@ -671,9 +671,17 @@ fn map_register_err(e: sqlx::Error) -> ServiceError {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn event_names_are_unique() {
|
||||||
|
let mut uniq = HashSet::new();
|
||||||
|
assert!(EVENTS.into_iter().all(move |x| uniq.insert(x.name)));
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn db_works() {
|
async fn db_works() {
|
||||||
let settings = Settings::new().unwrap();
|
let settings = Settings::new().unwrap();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpResponse, Responder};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::page::Page;
|
use crate::page::Page;
|
||||||
|
@ -43,13 +44,19 @@ pub struct DeployEvent {
|
||||||
pub branch: String,
|
pub branch: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct DeployEventResp {
|
||||||
|
pub id: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_web_codegen_const_routes::post(path = "crate::V1_API_ROUTES.deploy.update")]
|
#[actix_web_codegen_const_routes::post(path = "crate::V1_API_ROUTES.deploy.update")]
|
||||||
#[tracing::instrument(name = "Update webpages", skip(payload, ctx))]
|
#[tracing::instrument(name = "Update webpages", skip(payload, ctx))]
|
||||||
async fn update(payload: web::Json<DeployEvent>, ctx: AppCtx) -> ServiceResult<impl Responder> {
|
async fn update(payload: web::Json<DeployEvent>, ctx: AppCtx) -> ServiceResult<impl Responder> {
|
||||||
let payload = payload.into_inner();
|
let payload = payload.into_inner();
|
||||||
ctx.update_site(&payload.secret, Some(payload.branch))
|
let id = ctx
|
||||||
|
.update_site(&payload.secret, Some(payload.branch))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(HttpResponse::Ok())
|
Ok(HttpResponse::Ok().json(DeployEventResp { id }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||||
|
@ -131,6 +138,10 @@ mod tests {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
check_status!(resp, StatusCode::OK);
|
check_status!(resp, StatusCode::OK);
|
||||||
|
let event_id: DeployEventResp = actix_web::test::read_body_json(resp).await;
|
||||||
|
let update_event = ctx.db.get_event(&page.domain, &event_id.id).await.unwrap();
|
||||||
|
assert_eq!(&update_event.site, &page.domain);
|
||||||
|
assert_eq!(update_event.id, event_id.id);
|
||||||
|
|
||||||
payload.secret = page.branch.clone();
|
payload.secret = page.branch.clone();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue