From c85715c969f6adccbe818554c2f62141b71b7153 Mon Sep 17 00:00:00 2001 From: Magnus Hoff Date: Wed, 18 Oct 2017 16:33:21 +0200 Subject: [PATCH] Start tracking authors for edits. #6 --- libs/static_resource_derive/src/lib.rs | 4 ---- .../down.sql | 0 .../up.sql | 3 +++ src/main.rs | 2 +- src/models.rs | 4 ++++ src/resources/article_redirect_resource.rs | 2 +- src/resources/article_resource.rs | 6 +++--- src/resources/new_article_resource.rs | 4 ++-- src/site.rs | 8 ++++++-- src/state.rs | 9 +++++++-- src/web/resource.rs | 2 +- 11 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 migrations/20171018134042_add_author_to_article_revisions/down.sql create mode 100644 migrations/20171018134042_add_author_to_article_revisions/up.sql diff --git a/libs/static_resource_derive/src/lib.rs b/libs/static_resource_derive/src/lib.rs index f271d33..6055b93 100644 --- a/libs/static_resource_derive/src/lib.rs +++ b/libs/static_resource_derive/src/lib.rs @@ -94,10 +94,6 @@ pub fn static_resource(input: TokenStream) -> TokenStream { .with_body(body as &'static [u8]) )) } - - fn put(self: Box, _body: ::hyper::Body) -> ResponseFuture { - Box::new(::futures::finished(self.method_not_allowed())) - } } impl #impl_generics #name #ty_generics #where_clause { diff --git a/migrations/20171018134042_add_author_to_article_revisions/down.sql b/migrations/20171018134042_add_author_to_article_revisions/down.sql new file mode 100644 index 0000000..e69de29 diff --git a/migrations/20171018134042_add_author_to_article_revisions/up.sql b/migrations/20171018134042_add_author_to_article_revisions/up.sql new file mode 100644 index 0000000..91e4777 --- /dev/null +++ b/migrations/20171018134042_add_author_to_article_revisions/up.sql @@ -0,0 +1,3 @@ +ALTER TABLE article_revisions ADD COLUMN author TEXT CHECK (author != ''); + +CREATE INDEX author_lookup ON article_revisions (author); diff --git a/src/main.rs b/src/main.rs index 7a9c327..53f85af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ #[macro_use] extern crate bart_derive; #[macro_use] extern crate diesel; #[macro_use] extern crate diesel_codegen; +#[macro_use] extern crate hyper; #[macro_use] extern crate lazy_static; #[macro_use] extern crate serde_derive; #[macro_use] extern crate static_resource_derive; @@ -11,7 +12,6 @@ extern crate chrono; extern crate clap; extern crate futures; extern crate futures_cpupool; -extern crate hyper; extern crate percent_encoding; extern crate pulldown_cmark; extern crate r2d2; diff --git a/src/models.rs b/src/models.rs index 033e58c..8dec900 100644 --- a/src/models.rs +++ b/src/models.rs @@ -13,6 +13,8 @@ pub struct ArticleRevision { pub body: String, pub latest: bool, + + pub author: Option, } #[derive(Debug, Queryable)] @@ -27,4 +29,6 @@ pub struct ArticleRevisionStub { pub title: String, pub latest: bool, + + pub author: Option, } diff --git a/src/resources/article_redirect_resource.rs b/src/resources/article_redirect_resource.rs index 942fcb9..26b5b7b 100644 --- a/src/resources/article_redirect_resource.rs +++ b/src/resources/article_redirect_resource.rs @@ -41,7 +41,7 @@ impl Resource for ArticleRedirectResource { })) } - fn put(self: Box, _body: hyper::Body) -> ResponseFuture { + fn put(self: Box, _body: hyper::Body, _identity: Option) -> ResponseFuture { Box::new(self.head() .and_then(move |head| { Ok(head diff --git a/src/resources/article_resource.rs b/src/resources/article_resource.rs index f01596a..5b68b6e 100644 --- a/src/resources/article_resource.rs +++ b/src/resources/article_resource.rs @@ -83,7 +83,7 @@ impl Resource for ArticleResource { })) } - fn put(self: Box, body: hyper::Body) -> ResponseFuture { + fn put(self: Box, body: hyper::Body, identity: Option) -> ResponseFuture { // TODO Check incoming Content-Type use chrono::{TimeZone, Local}; @@ -120,7 +120,7 @@ impl Resource for ArticleResource { .map_err(Into::into) }) .and_then(move |update: UpdateArticle| { - self.state.update_article(self.article_id, update.base_revision, update.title, update.body) + self.state.update_article(self.article_id, update.base_revision, update.title, update.body, identity) }) .and_then(|updated| { futures::finished(Response::new() @@ -134,7 +134,7 @@ impl Resource for ArticleResource { title: &updated.title, rendered: render_markdown(&updated.body), }.to_string(), - created: &Local.from_utc_datetime(&updated.created).to_string(), + created: &Local.from_utc_datetime(&updated.created).to_rfc2822(), }).expect("Should never fail")) ) }) diff --git a/src/resources/new_article_resource.rs b/src/resources/new_article_resource.rs index c65ded7..2464aa5 100644 --- a/src/resources/new_article_resource.rs +++ b/src/resources/new_article_resource.rs @@ -94,7 +94,7 @@ impl Resource for NewArticleResource { })) } - fn put(self: Box, body: hyper::Body) -> ResponseFuture { + fn put(self: Box, body: hyper::Body, identity: Option) -> ResponseFuture { // TODO Check incoming Content-Type use chrono::{TimeZone, Local}; @@ -135,7 +135,7 @@ impl Resource for NewArticleResource { // TODO Check that update.base_revision == NDASH // ... which seems silly. But there should be a mechanism to indicate that // the client is actually trying to create a new article - self.state.create_article(self.slug.clone(), arg.title, arg.body) + self.state.create_article(self.slug.clone(), arg.title, arg.body, identity) }) .and_then(|updated| { futures::finished(Response::new() diff --git a/src/site.rs b/src/site.rs index 6400cfe..6890fd9 100644 --- a/src/site.rs +++ b/src/site.rs @@ -87,9 +87,13 @@ impl Service for Site { type Future = Box>; fn call(&self, req: Request) -> Self::Future { - let (method, uri, _http_version, _headers, body) = req.deconstruct(); + let (method, uri, _http_version, headers, body) = req.deconstruct(); + println!("{} {}", method, uri); + header! { (XIdentity, "X-Identity") => [String] } + let identity: Option = headers.get().map(|x: &XIdentity| x.to_string()); + let base = root_base_from_request_uri(uri.path()); let base2 = base.clone(); // Bah, stupid clone @@ -101,7 +105,7 @@ impl Service for Site { Options => Box::new(futures::finished(resource.options())), Head => resource.head(), Get => resource.get(), - Put => resource.put(body), + Put => resource.put(body, identity), _ => Box::new(futures::finished(resource.method_not_allowed())) } }, diff --git a/src/state.rs b/src/state.rs index 7e3a0d8..cb4518a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -35,6 +35,7 @@ struct NewRevision<'a> { slug: &'a str, title: &'a str, body: &'a str, + author: Option<&'a str>, latest: bool, } @@ -117,6 +118,7 @@ impl State { article_revisions::slug, article_revisions::title, article_revisions::latest, + article_revisions::author, )) .into_boxed(); @@ -146,6 +148,7 @@ impl State { article_revisions::slug, article_revisions::title, article_revisions::latest, + article_revisions::author, )) .load(&*connection_pool.get()?)?) }) @@ -195,7 +198,7 @@ impl State { }) } - pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String) + pub fn update_article(&self, article_id: i32, base_revision: i32, title: String, body: String, author: Option) -> CpuFuture { let connection_pool = self.connection_pool.clone(); @@ -239,6 +242,7 @@ impl State { slug: &slug, title: &title, body: &body, + author: author.as_ref().map(|x| &**x), latest: true, }) .into(article_revisions::table) @@ -253,7 +257,7 @@ impl State { }) } - pub fn create_article(&self, target_slug: Option, title: String, body: String) + pub fn create_article(&self, target_slug: Option, title: String, body: String, author: Option) -> CpuFuture { let connection_pool = self.connection_pool.clone(); @@ -288,6 +292,7 @@ impl State { slug: &slug, title: &title, body: &body, + author: author.as_ref().map(|x| &**x), latest: true, }) .into(article_revisions::table) diff --git a/src/web/resource.rs b/src/web/resource.rs index 373e43b..37a0096 100644 --- a/src/web/resource.rs +++ b/src/web/resource.rs @@ -21,7 +21,7 @@ pub trait Resource { Box::new(futures::finished(self.method_not_allowed())) } - fn put(self: Box, body: hyper::Body) -> ResponseFuture + fn put(self: Box, body: hyper::Body, _identity: Option) -> ResponseFuture where Self: 'static { use futures::{Future, Stream};