Start tracking authors for edits. #6

This commit is contained in:
Magnus Hoff 2017-10-18 16:33:21 +02:00
parent 6067ed8ddd
commit c85715c969
11 changed files with 28 additions and 16 deletions

View file

@ -94,10 +94,6 @@ pub fn static_resource(input: TokenStream) -> TokenStream {
.with_body(body as &'static [u8])
))
}
fn put(self: Box<Self>, _body: ::hyper::Body) -> ResponseFuture {
Box::new(::futures::finished(self.method_not_allowed()))
}
}
impl #impl_generics #name #ty_generics #where_clause {

View file

@ -0,0 +1,3 @@
ALTER TABLE article_revisions ADD COLUMN author TEXT CHECK (author != '');
CREATE INDEX author_lookup ON article_revisions (author);

View file

@ -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;

View file

@ -13,6 +13,8 @@ pub struct ArticleRevision {
pub body: String,
pub latest: bool,
pub author: Option<String>,
}
#[derive(Debug, Queryable)]
@ -27,4 +29,6 @@ pub struct ArticleRevisionStub {
pub title: String,
pub latest: bool,
pub author: Option<String>,
}

View file

@ -41,7 +41,7 @@ impl Resource for ArticleRedirectResource {
}))
}
fn put(self: Box<Self>, _body: hyper::Body) -> ResponseFuture {
fn put(self: Box<Self>, _body: hyper::Body, _identity: Option<String>) -> ResponseFuture {
Box::new(self.head()
.and_then(move |head| {
Ok(head

View file

@ -83,7 +83,7 @@ impl Resource for ArticleResource {
}))
}
fn put(self: Box<Self>, body: hyper::Body) -> ResponseFuture {
fn put(self: Box<Self>, body: hyper::Body, identity: Option<String>) -> 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"))
)
})

View file

@ -94,7 +94,7 @@ impl Resource for NewArticleResource {
}))
}
fn put(self: Box<Self>, body: hyper::Body) -> ResponseFuture {
fn put(self: Box<Self>, body: hyper::Body, identity: Option<String>) -> 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()

View file

@ -87,9 +87,13 @@ impl Service for Site {
type Future = Box<futures::Future<Item = Response, Error = Self::Error>>;
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<String> = 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()))
}
},

View file

@ -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<String>)
-> CpuFuture<models::ArticleRevision, Error>
{
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<String>, title: String, body: String)
pub fn create_article(&self, target_slug: Option<String>, title: String, body: String, author: Option<String>)
-> CpuFuture<models::ArticleRevision, Error>
{
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)

View file

@ -21,7 +21,7 @@ pub trait Resource {
Box::new(futures::finished(self.method_not_allowed()))
}
fn put(self: Box<Self>, body: hyper::Body) -> ResponseFuture
fn put(self: Box<Self>, body: hyper::Body, _identity: Option<String>) -> ResponseFuture
where Self: 'static
{
use futures::{Future, Stream};