From 640b39e970c009285127f78135a056103437c614 Mon Sep 17 00:00:00 2001 From: rhigman <73792779+rhigman@users.noreply.github.com> Date: Mon, 9 Sep 2024 10:43:15 +0100 Subject: [PATCH 01/11] Omit chapters with no DOI from Crossref output --- .../src/xml/doideposit_crossref.rs | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/thoth-export-server/src/xml/doideposit_crossref.rs b/thoth-export-server/src/xml/doideposit_crossref.rs index f7b675f3c..53c52fcee 100644 --- a/thoth-export-server/src/xml/doideposit_crossref.rs +++ b/thoth-export-server/src/xml/doideposit_crossref.rs @@ -132,7 +132,11 @@ impl XmlElementBlock for Work { .iter() .filter(|r| r.relation_type == RelationType::HAS_CHILD) { - XmlElementBlock::::xml_element(chapter, w)?; + // If chapter has no DOI, nothing to output (`content_item` element + // representing chapter must contain `doi_data` element with `doi`) + if chapter.related_work.doi.is_some() { + XmlElementBlock::::xml_element(chapter, w)?; + } } Ok(()) }) @@ -692,12 +696,8 @@ fn write_chapter_doi_collection( )); } } else { - // `doi_data` element is mandatory for `content_item`, and must contain - // both `doi` element and `resource` (landing page) element - return Err(ThothError::IncompleteMetadataRecord( - DEPOSIT_ERROR.to_string(), - "Missing chapter DOI".to_string(), - )); + // Caller should only pass in chapters which have DOIs + unreachable!() } Ok(()) } @@ -1436,17 +1436,6 @@ mod tests { output, "Could not generate doideposit::crossref: Missing chapter Landing Page".to_string() ); - - // Restore landing page but remove DOI. Result: error, as above - test_relations.related_work.edition = None; - test_relations.related_work.landing_page = - Some("https://www.book.com/chapter_one".to_string()); - test_relations.related_work.doi = None; - let output = generate_test_output(false, &test_relations); - assert_eq!( - output, - "Could not generate doideposit::crossref: Missing chapter DOI".to_string() - ); } #[test] @@ -1974,6 +1963,9 @@ mod tests { test_work.publications[0].locations.clear(); // Remove last (hardback) publication test_work.publications.pop(); + // Change sole relation to chapter with no DOI + test_work.relations[0].relation_type = RelationType::HAS_CHILD; + test_work.relations[0].related_work.doi = None; let output = generate_test_output(true, &test_work); // Work type changed @@ -2022,6 +2014,18 @@ mod tests { assert!(!output.contains(r#" "#)); assert!(!output.contains(r#" "#)); assert!(!output.contains(r#" "#)); + // Only chapters with no DOI supplied: no `content_item` elements emitted + assert!(!output.contains(r#" "#)); + assert!(!output.contains(r#" Part"#)); + assert!(!output.contains(r#" One"#)); + assert!(!output.contains(r#" 1"#)); + assert!(!output.contains(r#" 02"#)); + assert!(!output.contains(r#" 28"#)); + assert!(!output.contains(r#" 2000"#)); + assert!(!output.contains(r#" "#)); + assert!(!output.contains(r#" 10"#)); + assert!(!output.contains(r#" 20"#)); + assert!(!output.contains(r#" https://www.book.com/part_one"#)); // Change work type, remove landing page, remove XML ISBN, // remove all but the omitted contributor From a378dacac3b9b2d41ff341c4dac4698c75fcf05a Mon Sep 17 00:00:00 2001 From: rhigman <73792779+rhigman@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:33:41 +0100 Subject: [PATCH 02/11] Raise error if no DOIs are found for either parent work or chapters --- .../src/xml/doideposit_crossref.rs | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/thoth-export-server/src/xml/doideposit_crossref.rs b/thoth-export-server/src/xml/doideposit_crossref.rs index 53c52fcee..1d519c434 100644 --- a/thoth-export-server/src/xml/doideposit_crossref.rs +++ b/thoth-export-server/src/xml/doideposit_crossref.rs @@ -79,14 +79,25 @@ impl XmlSpecification for DoiDepositCrossref { impl XmlElementBlock for Work { fn xml_element(&self, w: &mut EventWriter) -> ThothResult<()> { - let work_type = match &self.work_type { + let work = self; + if work.doi.is_none() + && !work + .relations + .iter() + .any(|r| r.relation_type == RelationType::HAS_CHILD && r.related_work.doi.is_some()) + { + return Err(ThothError::IncompleteMetadataRecord( + DEPOSIT_ERROR.to_string(), + "No work or chapter DOIs to deposit".to_string(), + )); + } + let work_type = match &work.work_type { WorkType::MONOGRAPH => "monograph", WorkType::EDITED_BOOK => "edited_book", WorkType::TEXTBOOK => "reference", WorkType::JOURNAL_ISSUE | WorkType::BOOK_SET | WorkType::BOOK_CHAPTER => "other", WorkType::Other(_) => unreachable!(), }; - let work = self; // As an alternative to `book_metadata` and `book_series_metadata` below, // `book_set_metadata` can be used for works which are part of a set. // Omitted at present but could be considered as a future enhancement. @@ -2069,18 +2080,31 @@ mod tests { assert!(!output.contains(r#" 10.00001/BOOK.0001"#)); assert!(!output.contains(r#" https://www.book.com"#)); - // Change work type again, replace landing page but remove DOI + // Remove DOI (so neither work nor chapter DOIs are present). Result: error + test_work.doi = None; + let output = generate_test_output(false, &test_work); + assert_eq!( + output, + "Could not generate doideposit::crossref: No work or chapter DOIs to deposit" + .to_string() + ); + + // Change work type again, replace landing page, replace chapter DOI test_work.work_type = WorkType::JOURNAL_ISSUE; test_work.landing_page = Some("https://www.book.com".to_string()); - test_work.doi = None; + test_work.relations[0].related_work.doi = + Some(Doi::from_str("https://doi.org/10.00001/PART.0001").unwrap()); let output = generate_test_output(true, &test_work); // Work type changed assert!(!output.contains(r#" "#)); assert!(output.contains(r#" "#)); - // No DOI: entire `doi_data` element omitted (even though landing page restored) - assert!(!output.contains(r#" "#)); + // No work DOI: entire work-specific `doi_data` element omitted (even though landing page restored) assert!(!output.contains(r#" 10.00001/BOOK.0001"#)); assert!(!output.contains(r#" https://www.book.com"#)); + // But chapter-specific `doi_data` element will be present (at same nesting level) + assert!(output.contains(r#" "#)); + assert!(output.contains(r#" 10.00001/PART.0001"#)); + assert!(output.contains(r#" https://www.book.com/part_one"#)); // Remove publication date. Result: error test_work.publication_date = None; From 57bb64b9f2f8c64210b19017975490fd9414a5c4 Mon Sep 17 00:00:00 2001 From: rhigman <73792779+rhigman@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:36:50 +0100 Subject: [PATCH 03/11] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ffff9309..694cc16db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed + - [551](https://github.com/thoth-pub/thoth/issues/551) - Only include chapters in Crossref metadata output if they have DOIs + +### Fixed + - [565](https://github.com/thoth-pub/thoth/issues/565) - Don't generate Crossref metadata output if no DOIs (work or chapter) are present ## [[0.12.9]](https://github.com/thoth-pub/thoth/releases/tag/v0.12.9) - 2024-09-06 ### Added From 7b2ed5002920a265cdf79235d9b7731705557f2b Mon Sep 17 00:00:00 2001 From: rhigman <73792779+rhigman@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:04:12 +0100 Subject: [PATCH 04/11] Review markups: remove unnecessary variable, streamline unreachable check --- .../src/xml/doideposit_crossref.rs | 183 +++++++++--------- 1 file changed, 89 insertions(+), 94 deletions(-) diff --git a/thoth-export-server/src/xml/doideposit_crossref.rs b/thoth-export-server/src/xml/doideposit_crossref.rs index 1d519c434..d90d52334 100644 --- a/thoth-export-server/src/xml/doideposit_crossref.rs +++ b/thoth-export-server/src/xml/doideposit_crossref.rs @@ -79,9 +79,8 @@ impl XmlSpecification for DoiDepositCrossref { impl XmlElementBlock for Work { fn xml_element(&self, w: &mut EventWriter) -> ThothResult<()> { - let work = self; - if work.doi.is_none() - && !work + if self.doi.is_none() + && !self .relations .iter() .any(|r| r.relation_type == RelationType::HAS_CHILD && r.related_work.doi.is_some()) @@ -91,7 +90,7 @@ impl XmlElementBlock for Work { "No work or chapter DOIs to deposit".to_string(), )); } - let work_type = match &work.work_type { + let work_type = match &self.work_type { WorkType::MONOGRAPH => "monograph", WorkType::EDITED_BOOK => "edited_book", WorkType::TEXTBOOK => "reference", @@ -117,22 +116,22 @@ impl XmlElementBlock for Work { XmlElementBlock::::xml_element(series, w)?; ordinal = Some(ord); } - write_work_contributions(work, w)?; - write_work_title(work, w)?; - write_work_abstract(work, w)?; + write_work_contributions(self, w)?; + write_work_title(self, w)?; + write_work_abstract(self, w)?; if ordinal.is_some() { let ordinal_i64 = ordinal.unwrap_or(0); write_work_volume(ordinal_i64, w)?; } - write_work_edition(work, w)?; - write_work_publication_date(work, w)?; - write_work_publications(work, w)?; - write_publisher(work, w)?; - write_crossmark_funding_access(work, w)?; - write_doi_collection(work, w)?; - write_work_references(work, w)?; + write_work_edition(self, w)?; + write_work_publication_date(self, w)?; + write_work_publications(self, w)?; + write_publisher(self, w)?; + write_crossmark_funding_access(self, w)?; + write_doi_collection(self, w)?; + write_work_references(self, w)?; Ok(()) })?; @@ -627,88 +626,84 @@ fn write_chapter_doi_collection( chapter: &WorkRelations, w: &mut EventWriter, ) -> ThothResult<()> { - if let Some(doi) = &chapter.related_work.doi { - if let Some(landing_page) = &chapter.related_work.landing_page { - write_element_block("doi_data", w, |w| { - write_element_block("doi", w, |w| { - w.write(XmlEvent::Characters(&doi.to_string())) - .map_err(|e| e.into()) - })?; - write_element_block("resource", w, |w| { - w.write(XmlEvent::Characters(landing_page)) - .map_err(|e| e.into()) - })?; - if let Some(pdf_url) = chapter - .related_work - .publications - .iter() - .find(|p| { - p.publication_type.eq(&PublicationType::PDF) && !p.locations.is_empty() - }) - .and_then(|p| p.locations.iter().find(|l| l.canonical)) - .and_then(|l| l.full_text_url.as_ref()) - { - // Used for CrossRef Similarity Check. URL must point directly to full-text PDF. - // Alternatively, a direct link to full-text HTML can be used (not implemented here). - write_full_element_block( - "collection", - Some(vec![("property", "crawler-based")]), - w, - |w| { - for crawler in ["iParadigms", "google", "msn", "yahoo", "scirus"] { - write_full_element_block( - "item", - Some(vec![("crawler", crawler)]), - w, - |w| { - write_full_element_block( - "resource", - Some(vec![("mime_type", "application/pdf")]), - w, - |w| { - w.write(XmlEvent::Characters(pdf_url)) - .map_err(|e| e.into()) - }, - ) - }, - )?; - } - Ok(()) - }, - )?; - // Used for CrossRef Text and Data Mining. URL must point directly to full-text PDF. - // Alternatively, a direct link to full-text XML can be used (not implemented here). - write_full_element_block( - "collection", - Some(vec![("property", "text-mining")]), - w, - |w| { - write_element_block("item", w, |w| { - write_full_element_block( - "resource", - Some(vec![("mime_type", "application/pdf")]), - w, - |w| { - w.write(XmlEvent::Characters(pdf_url)).map_err(|e| e.into()) - }, - ) - }) - }, - )?; - } - Ok(()) + let doi = &chapter + .related_work + .doi + .as_ref() + .expect("Caller should only pass in chapters which have DOIs"); + if let Some(landing_page) = &chapter.related_work.landing_page { + write_element_block("doi_data", w, |w| { + write_element_block("doi", w, |w| { + w.write(XmlEvent::Characters(&doi.to_string())) + .map_err(|e| e.into()) })?; - } else { - // `doi_data` element is mandatory for `content_item`, and must contain - // both `doi` element and `resource` (landing page) element - return Err(ThothError::IncompleteMetadataRecord( - DEPOSIT_ERROR.to_string(), - "Missing chapter Landing Page".to_string(), - )); - } + write_element_block("resource", w, |w| { + w.write(XmlEvent::Characters(landing_page)) + .map_err(|e| e.into()) + })?; + if let Some(pdf_url) = chapter + .related_work + .publications + .iter() + .find(|p| p.publication_type.eq(&PublicationType::PDF) && !p.locations.is_empty()) + .and_then(|p| p.locations.iter().find(|l| l.canonical)) + .and_then(|l| l.full_text_url.as_ref()) + { + // Used for CrossRef Similarity Check. URL must point directly to full-text PDF. + // Alternatively, a direct link to full-text HTML can be used (not implemented here). + write_full_element_block( + "collection", + Some(vec![("property", "crawler-based")]), + w, + |w| { + for crawler in ["iParadigms", "google", "msn", "yahoo", "scirus"] { + write_full_element_block( + "item", + Some(vec![("crawler", crawler)]), + w, + |w| { + write_full_element_block( + "resource", + Some(vec![("mime_type", "application/pdf")]), + w, + |w| { + w.write(XmlEvent::Characters(pdf_url)) + .map_err(|e| e.into()) + }, + ) + }, + )?; + } + Ok(()) + }, + )?; + // Used for CrossRef Text and Data Mining. URL must point directly to full-text PDF. + // Alternatively, a direct link to full-text XML can be used (not implemented here). + write_full_element_block( + "collection", + Some(vec![("property", "text-mining")]), + w, + |w| { + write_element_block("item", w, |w| { + write_full_element_block( + "resource", + Some(vec![("mime_type", "application/pdf")]), + w, + |w| w.write(XmlEvent::Characters(pdf_url)).map_err(|e| e.into()), + ) + }) + }, + )?; + } + Ok(()) + })?; } else { - // Caller should only pass in chapters which have DOIs - unreachable!() + // `doi_data` element is mandatory for `content_item`, and must contain + // both `doi` element and `resource` (landing page) element + return Err(ThothError::IncompleteMetadataRecord( + DEPOSIT_ERROR.to_string(), + "Missing chapter Landing Page".to_string(), + )); } Ok(()) } From 2ffb3382468ecbad9ade343864dc83f8ea8b0d7c Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:26:40 +0100 Subject: [PATCH 05/11] Upgrade paperclip --- Cargo.lock | 31 +++++++++++++++++++++++-------- thoth-export-server/Cargo.toml | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 795a38997..b6bf32a6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1697,6 +1697,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", + "serde", ] [[package]] @@ -2053,6 +2054,17 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openapiv3" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b83630305ecc3355e998ddd2f926f98aae8e105eb42652174a58757851ba47" +dependencies = [ + "indexmap 1.9.3", + "serde", + "serde_json", +] + [[package]] name = "openssl" version = "0.10.66" @@ -2099,13 +2111,14 @@ dependencies = [ [[package]] name = "paperclip" -version = "0.8.2" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2509afd8f138efe07cd367832289f5cc61d1eb1ec7f1eb75172abca6f7b9b66d" +checksum = "ac41f27e83168c22515ef52d62a0357b5f5b8df846aa391f8b903b0ed7719429" dependencies = [ "anyhow", "itertools", "once_cell", + "openapiv3", "paperclip-actix", "paperclip-core", "paperclip-macros", @@ -2120,15 +2133,16 @@ dependencies = [ [[package]] name = "paperclip-actix" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adf797da91baee514bc03b020fdd6673d2f8c1af8a859e50d6d803a4b3dddd2" +checksum = "d5b6f4c003aa6167df82f1574c951638a8b9a43827059da0cda8b5df88d20ecf" dependencies = [ "actix-service", "actix-web", "futures", "mime_guess", "once_cell", + "openapiv3", "paperclip-core", "paperclip-macros", "serde_json", @@ -2136,13 +2150,14 @@ dependencies = [ [[package]] name = "paperclip-core" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8db363c823fa71c00da73ff8cee3d6902e1ad66b770cc224a74dc7cf54de3aad" +checksum = "8e2e742f71daf34eb8f62ccc5a1a5e1f029eb84be563523a2a5ee049366329f4" dependencies = [ "actix-web", "mime", "once_cell", + "openapiv3", "paperclip-macros", "pin-project-lite", "regex", @@ -2155,9 +2170,9 @@ dependencies = [ [[package]] name = "paperclip-macros" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6e25ce2c5362c8d48dc89e0f9ca076d507f7c1eabd04f0d593cdf5addff90c" +checksum = "0385be5ae9c886c46688290534363a229f2531aa2c5c2bfc3b3ddafed5143aaa" dependencies = [ "heck 0.4.1", "http", diff --git a/thoth-export-server/Cargo.toml b/thoth-export-server/Cargo.toml index f3607cd7a..83395ec92 100644 --- a/thoth-export-server/Cargo.toml +++ b/thoth-export-server/Cargo.toml @@ -23,7 +23,7 @@ futures = "0.3.30" lazy_static = "1.5.0" log = "0.4.20" marc = { version = "3.1.1", features = ["xml"] } -paperclip = { version = "0.8.2", features = ["actix-base", "actix4", "uuid1", "v2"] } +paperclip = { version = "0.9.1", features = ["actix4", "uuid1", "v3"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "1.10.0", features = ["serde"] } From 52111e2597dfebe3c9511b83107d5e87f1284413 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:27:58 +0100 Subject: [PATCH 06/11] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 694cc16db..e38eddc33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] + +### Changed + - Upgrade `paperclip` to v0.9.1 + ### Changed - [551](https://github.com/thoth-pub/thoth/issues/551) - Only include chapters in Crossref metadata output if they have DOIs From 4e5b9c76e7872c53fb64d0c1ac3f0bc484a75252 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:28:27 +0100 Subject: [PATCH 07/11] Add terms of service to export API --- thoth-export-server/src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/thoth-export-server/src/lib.rs b/thoth-export-server/src/lib.rs index 7b85b4702..7ac5ca87d 100644 --- a/thoth-export-server/src/lib.rs +++ b/thoth-export-server/src/lib.rs @@ -31,7 +31,7 @@ struct ApiConfig { impl ApiConfig { pub fn new(public_url: String) -> Self { Self { - api_schema: format!("{public_url}/swagger.json"), + api_schema: format!("{public_url}/openapi.json"), } } } @@ -82,6 +82,7 @@ pub async fn start_server( "Obtain Thoth metadata records in various formats and platform specifications" .to_string(), ), + terms_of_service: Some("https://thoth.pub/policies/terms-thoth-free".to_string()), contact: Some(Contact { name: Some("Thoth Support".to_string()), url: Some("https://thoth.pub".to_string()), @@ -107,6 +108,7 @@ pub async fn start_server( .configure(platform::route) .configure(specification::route) .with_json_spec_at("/swagger.json") + .with_json_spec_v3_at("/openapi.json") .build() }) .workers(threads) From 9fccac18b38061db8cb99edf884ae55b1dbab9fc Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:29:57 +0100 Subject: [PATCH 08/11] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e38eddc33..190520828 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Upgrade `paperclip` to v0.9.1 +### Added + - Implement OpenAPI v3 schema in export API, served under `/openapi.json` + - Added terms of service to export API + ### Changed - [551](https://github.com/thoth-pub/thoth/issues/551) - Only include chapters in Crossref metadata output if they have DOIs From 87d49e6a3b1b6a4ef321ba0cb3b0b85594b4cca8 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:32:11 +0100 Subject: [PATCH 09/11] Upgrade rust 1.81.0 --- Dockerfile | 2 +- Dockerfile.dev | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 16bf45929..3d87552c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG MUSL_IMAGE=clux/muslrust:1.80.1-stable +ARG MUSL_IMAGE=clux/muslrust:1.81.0-stable FROM ${MUSL_IMAGE} as build diff --git a/Dockerfile.dev b/Dockerfile.dev index a90356118..e3ff5cf21 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -1,4 +1,4 @@ -ARG RUST_VERSION=1.80.1 +ARG RUST_VERSION=1.81.0 FROM rust:${RUST_VERSION} From d88d1adc9a07438b61c258b609cb554e1e5d9de3 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:33:56 +0100 Subject: [PATCH 10/11] Update changelog --- CHANGELOG.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 190520828..42f5924c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Changed - - Upgrade `paperclip` to v0.9.1 - ### Added - - Implement OpenAPI v3 schema in export API, served under `/openapi.json` - - Added terms of service to export API + - [628](https://github.com/thoth-pub/thoth/pull/628) - Implement OpenAPI v3 schema in export API, served under `/openapi.json` + - [628](https://github.com/thoth-pub/thoth/pull/628) - Added terms of service to export API ### Changed - [551](https://github.com/thoth-pub/thoth/issues/551) - Only include chapters in Crossref metadata output if they have DOIs + - [628](https://github.com/thoth-pub/thoth/pull/628) - Upgrade `paperclip` to v0.9.1 + - [628](https://github.com/thoth-pub/thoth/pull/628) - Upgrade rust to `1.81.0` in production and development `Dockerfile` ### Fixed - [565](https://github.com/thoth-pub/thoth/issues/565) - Don't generate Crossref metadata output if no DOIs (work or chapter) are present From 39b4edce2c59e7361771ed1b047d43403e942a67 Mon Sep 17 00:00:00 2001 From: Javier Arias Date: Wed, 11 Sep 2024 12:34:18 +0100 Subject: [PATCH 11/11] Update changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42f5924c9..ee583e9ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] - ### Added - [628](https://github.com/thoth-pub/thoth/pull/628) - Implement OpenAPI v3 schema in export API, served under `/openapi.json` - [628](https://github.com/thoth-pub/thoth/pull/628) - Added terms of service to export API