aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rust/src/api_helpers.rs55
-rw-r--r--rust/src/api_server.rs66
-rw-r--r--rust/src/database_models.rs11
-rw-r--r--rust/src/database_schema.rs2
-rw-r--r--rust/tests/test_api_server.rs55
5 files changed, 142 insertions, 47 deletions
diff --git a/rust/src/api_helpers.rs b/rust/src/api_helpers.rs
index ef07ee55..91c6200d 100644
--- a/rust/src/api_helpers.rs
+++ b/rust/src/api_helpers.rs
@@ -4,9 +4,8 @@ use database_schema::*;
use diesel;
use diesel::prelude::*;
use errors::*;
-use uuid::Uuid;
use regex::Regex;
-
+use uuid::Uuid;
pub fn get_or_create_editgroup(editor_id: Uuid, conn: &PgConnection) -> Result<Uuid> {
// check for current active
@@ -119,74 +118,80 @@ pub fn check_pmcid(raw: &str) -> Result<()> {
if RE.is_match(raw) {
Ok(())
} else {
- Err(ErrorKind::MalformedExternalId(
- format!("not a valid PubMed Central ID (PMCID): '{}' (expected, eg, 'PMC12345')", raw)
- ).into())
+ Err(ErrorKind::MalformedExternalId(format!(
+ "not a valid PubMed Central ID (PMCID): '{}' (expected, eg, 'PMC12345')",
+ raw
+ )).into())
}
}
pub fn check_pmid(raw: &str) -> Result<()> {
lazy_static! {
- static ref RE: Regex = Regex::new(r"^\d+$").unwrap();
+ static ref RE: Regex = Regex::new(r"^\d+$").unwrap();
}
if RE.is_match(raw) {
Ok(())
} else {
- Err(ErrorKind::MalformedExternalId(
- format!("not a valid PubMed ID (PMID): '{}' (expected, eg, '1234')", raw)
- ).into())
+ Err(ErrorKind::MalformedExternalId(format!(
+ "not a valid PubMed ID (PMID): '{}' (expected, eg, '1234')",
+ raw
+ )).into())
}
}
pub fn check_wikidata_qid(raw: &str) -> Result<()> {
lazy_static! {
- static ref RE: Regex = Regex::new(r"^Q\d+$").unwrap();
+ static ref RE: Regex = Regex::new(r"^Q\d+$").unwrap();
}
if RE.is_match(raw) {
Ok(())
} else {
- Err(ErrorKind::MalformedExternalId(
- format!("not a valid Wikidata QID: '{}' (expected, eg, 'Q1234')", raw)
- ).into())
+ Err(ErrorKind::MalformedExternalId(format!(
+ "not a valid Wikidata QID: '{}' (expected, eg, 'Q1234')",
+ raw
+ )).into())
}
}
pub fn check_doi(raw: &str) -> Result<()> {
lazy_static! {
- static ref RE: Regex = Regex::new(r"^10.\d{3,6}/.+$").unwrap();
+ static ref RE: Regex = Regex::new(r"^10.\d{3,6}/.+$").unwrap();
}
if RE.is_match(raw) {
Ok(())
} else {
- Err(ErrorKind::MalformedExternalId(
- format!("not a valid DOI: '{}' (expected, eg, '10.1234/aksjdfh')", raw)
- ).into())
+ Err(ErrorKind::MalformedExternalId(format!(
+ "not a valid DOI: '{}' (expected, eg, '10.1234/aksjdfh')",
+ raw
+ )).into())
}
}
pub fn check_issn(raw: &str) -> Result<()> {
lazy_static! {
- static ref RE: Regex = Regex::new(r"^\d{4}-\d{3}[0-9X]$").unwrap();
+ static ref RE: Regex = Regex::new(r"^\d{4}-\d{3}[0-9X]$").unwrap();
}
if RE.is_match(raw) {
Ok(())
} else {
- Err(ErrorKind::MalformedExternalId(
- format!("not a valid ISSN: '{}' (expected, eg, '1234-5678')", raw)
- ).into())
+ Err(ErrorKind::MalformedExternalId(format!(
+ "not a valid ISSN: '{}' (expected, eg, '1234-5678')",
+ raw
+ )).into())
}
}
pub fn check_orcid(raw: &str) -> Result<()> {
lazy_static! {
- static ref RE: Regex = Regex::new(r"^\d{4}-\d{4}-\d{4}-\d{4}$").unwrap();
+ static ref RE: Regex = Regex::new(r"^\d{4}-\d{4}-\d{4}-\d{4}$").unwrap();
}
if RE.is_match(raw) {
Ok(())
} else {
- Err(ErrorKind::MalformedExternalId(
- format!("not a valid ORCID: '{}' (expected, eg, '0123-4567-3456-6789')", raw)
- ).into())
+ Err(ErrorKind::MalformedExternalId(format!(
+ "not a valid ORCID: '{}' (expected, eg, '0123-4567-3456-6789')",
+ raw
+ )).into())
}
}
diff --git a/rust/src/api_server.rs b/rust/src/api_server.rs
index 64c028be..d172cb16 100644
--- a/rust/src/api_server.rs
+++ b/rust/src/api_server.rs
@@ -4,16 +4,17 @@ use api_helpers::*;
use chrono;
use database_models::*;
use database_schema::{
- changelog, container_edit, container_ident, container_rev, creator_edit, creator_ident,
- creator_rev, editgroup, editor, file_edit, file_ident, file_release, file_rev, file_rev_url,
- release_contrib, release_edit, release_ident, release_ref, release_rev, release_rev_abstract,
- work_edit, work_ident, work_rev,
+ abstracts, changelog, container_edit, container_ident, container_rev, creator_edit,
+ creator_ident, creator_rev, editgroup, editor, file_edit, file_ident, file_release, file_rev,
+ file_rev_url, release_contrib, release_edit, release_ident, release_ref, release_rev,
+ release_rev_abstract, work_edit, work_ident, work_rev,
};
use diesel::prelude::*;
use diesel::{self, insert_into};
use errors::*;
use fatcat_api::models;
use fatcat_api::models::*;
+use sha1::Sha1;
use uuid::Uuid;
use ConnectionPool;
@@ -221,24 +222,26 @@ fn release_row2entity(
.into_iter()
.map(|c: ReleaseContribRow| ReleaseContrib {
index: c.index,
- raw: c.raw,
+ raw_name: c.raw_name,
role: c.role,
extra: c.extra_json,
creator_id: c.creator_ident_id.map(|v| uuid2fcid(&v)),
})
.collect();
- // XXX: join abstracts table
let abstracts: Vec<ReleaseEntityAbstracts> = release_rev_abstract::table
+ .inner_join(abstracts::table)
.filter(release_rev_abstract::release_rev.eq(rev.id))
.get_results(conn)?
.into_iter()
- .map(|r: ReleaseRevAbstractRow| ReleaseEntityAbstracts {
- sha1: Some(r.abstract_sha1),
- mimetype: r.mimetype,
- lang: r.lang,
- content: None,
- })
+ .map(
+ |r: (ReleaseRevAbstractRow, AbstractsRow)| ReleaseEntityAbstracts {
+ sha1: Some(r.0.abstract_sha1),
+ mimetype: r.0.mimetype,
+ lang: r.0.lang,
+ content: Some(r.1.content),
+ },
+ )
.collect();
Ok(ReleaseEntity {
@@ -767,6 +770,7 @@ impl Server {
if contrib_list.is_empty() {
Some(vec![])
} else {
+ println!("{:#?}", contrib_list);
let contrib_rows: Vec<ReleaseContribNewRow> = contrib_list
.iter()
.map(|c| ReleaseContribNewRow {
@@ -774,7 +778,7 @@ impl Server {
creator_ident_id: c.creator_id
.clone()
.map(|v| fcid2uuid(&v).expect("valid fatcat identifier")),
- raw: c.raw.clone(),
+ raw_name: c.raw_name.clone(),
index: c.index,
role: c.role.clone(),
extra_json: c.extra.clone(),
@@ -789,6 +793,42 @@ impl Server {
}
};
+ if let Some(abstract_list) = entity.abstracts {
+ // For rows that specify content, we need to insert the abstract if it doesn't exist
+ // already
+ let new_abstracts: Vec<AbstractsRow> = abstract_list
+ .iter()
+ .filter(|ea| ea.content.is_some())
+ .map(|c| AbstractsRow {
+ sha1: Sha1::from(c.content.clone().unwrap()).hexdigest(),
+ content: c.content.clone().unwrap(),
+ })
+ .collect();
+ if !new_abstracts.is_empty() {
+ // Sort of an "upsert"; only inserts new abstract rows if they don't already exist
+ insert_into(abstracts::table)
+ .values(new_abstracts)
+ //.on_conflict(abstracts::sha1)
+ //.do_nothing()
+ .execute(conn)?;
+ }
+ let release_abstract_rows: Vec<ReleaseRevAbstractNewRow> = abstract_list
+ .into_iter()
+ .map(|c| ReleaseRevAbstractNewRow {
+ release_rev: edit.rev_id.unwrap(),
+ abstract_sha1: match c.content {
+ Some(ref content) => Sha1::from(content).hexdigest(),
+ None => c.sha1.expect("either abstract_sha1 or content is required"),
+ },
+ lang: c.lang,
+ mimetype: c.mimetype,
+ })
+ .collect();
+ insert_into(release_rev_abstract::table)
+ .values(release_abstract_rows)
+ .execute(conn)?;
+ }
+
edit.into_model()
}
diff --git a/rust/src/database_models.rs b/rust/src/database_models.rs
index f875b492..50176f5f 100644
--- a/rust/src/database_models.rs
+++ b/rust/src/database_models.rs
@@ -225,7 +225,7 @@ pub struct ReleaseContribRow {
pub id: i64,
pub release_rev: Uuid,
pub creator_ident_id: Option<Uuid>,
- pub raw: Option<String>,
+ pub raw_name: Option<String>,
pub role: Option<String>,
pub index: Option<i64>,
pub extra_json: Option<serde_json::Value>,
@@ -236,7 +236,7 @@ pub struct ReleaseContribRow {
pub struct ReleaseContribNewRow {
pub release_rev: Uuid,
pub creator_ident_id: Option<Uuid>,
- pub raw: Option<String>,
+ pub raw_name: Option<String>,
pub role: Option<String>,
pub index: Option<i64>,
pub extra_json: Option<serde_json::Value>,
@@ -278,6 +278,13 @@ pub struct FileReleaseRow {
pub target_release_ident_id: Uuid,
}
+#[derive(Debug, Queryable, Insertable, Associations, AsChangeset)]
+#[table_name = "abstracts"]
+pub struct AbstractsRow {
+ pub sha1: String,
+ pub content: String,
+}
+
#[derive(Debug, Queryable, Identifiable, Associations, AsChangeset)]
#[table_name = "editgroup"]
pub struct EditgroupRow {
diff --git a/rust/src/database_schema.rs b/rust/src/database_schema.rs
index c23e3f83..f935302a 100644
--- a/rust/src/database_schema.rs
+++ b/rust/src/database_schema.rs
@@ -157,7 +157,7 @@ table! {
id -> Int8,
release_rev -> Uuid,
creator_ident_id -> Nullable<Uuid>,
- raw -> Nullable<Text>,
+ raw_name -> Nullable<Text>,
role -> Nullable<Text>,
index -> Nullable<Int8>,
extra_json -> Nullable<Json>,
diff --git a/rust/tests/test_api_server.rs b/rust/tests/test_api_server.rs
index b9880ba1..f43101c0 100644
--- a/rust/tests/test_api_server.rs
+++ b/rust/tests/test_api_server.rs
@@ -422,11 +422,11 @@ fn test_post_release() {
}],
"contribs": [{
"index": 1,
- "raw": "textual description of contributor (aka, name)",
+ "raw_name": "textual description of contributor (aka, name)",
"creator_id": "aaaaaaaaaaaaaircaaaaaaaaae",
"contrib_type": "author"
},{
- "raw": "shorter"
+ "raw_name": "shorter"
}],
"extra": { "source": "speculation" }
}"#,
@@ -620,11 +620,11 @@ fn test_400() {
}],
"contribs": [{
"index": 1,
- "raw": "textual description of contributor (aka, name)",
+ "raw_name": "textual description of contributor (aka, name)",
"creator_id": "aaaaaaaaaaaaaircaaaaaaaaae",
"contrib_type": "author"
},{
- "raw": "shorter"
+ "raw_name": "shorter"
}],
"extra": { "source": "speculation" }
}"#,
@@ -820,8 +820,8 @@ fn test_abstracts() {
&router,
),
status::Ok,
- // SHA-1 of first abstract string
- Some("4e30ded694c6a7775b9e7b019dfda6be0dd60944"),
+ // SHA-1 of first abstract string (with no trailing newline)
+ Some("65c171bd8c968e12ede25ad95f02cd4b2ce9db52"),
);
check_response(
request::get(
@@ -842,3 +842,46 @@ fn test_abstracts() {
Some("24iu3i25u2"),
);
}
+
+#[test]
+fn test_contribs() {
+ let (headers, router, conn) = setup();
+
+ check_response(
+ request::post(
+ "http://localhost:9411/v0/release",
+ headers.clone(),
+ r#"{"title": "some paper",
+ "doi": "10.1234/iiiiiii",
+ "contribs": [{
+ "index": 1,
+ "raw_name": "textual description of contributor (aka, name)",
+ "creator_id": "aaaaaaaaaaaaaircaaaaaaaaae",
+ "contrib_type": "author",
+ "extra": {"key": "value 28328424942"}
+ },{
+ "raw_name": "shorter"
+ }]
+ }"#,
+ &router,
+ ),
+ status::Created,
+ None,
+ );
+
+ let editor_id = Uuid::parse_str("00000000-0000-0000-AAAA-000000000001").unwrap();
+ let editgroup_id = get_or_create_editgroup(editor_id, &conn).unwrap();
+ check_response(
+ request::post(
+ &format!(
+ "http://localhost:9411/v0/editgroup/{}/accept",
+ uuid2fcid(&editgroup_id)
+ ),
+ headers.clone(),
+ "",
+ &router,
+ ),
+ status::Ok,
+ None,
+ );
+}