diff --git a/src/roc-zenodo/getZenodoDeposition.js b/src/roc-zenodo/getZenodoDeposition.js index ac921c56..7ffbc6c5 100644 --- a/src/roc-zenodo/getZenodoDeposition.js +++ b/src/roc-zenodo/getZenodoDeposition.js @@ -1,5 +1,7 @@ 'use strict'; +const okOrcid = require('../util/orcid'); + function getZenodoDeposition(entry, self) { const result = { metadata: { @@ -67,10 +69,20 @@ function validateCreators(creators) { if (typeof creator.affiliation !== 'string') { throw new TypeError('creator must have an affiliation'); } - toReturn.push({ + + const creatorToReturn = { name: creatorName, affiliation: creator.affiliation, - }); + }; + + if ('orcid' in creator) { + if (okOrcid(creator.orcid)) { + creatorToReturn.orcid = creator.orcid; + } else { + throw new TypeError(`${creator.orcid} is not a valid ORCID identifier`); + } + } + toReturn.push(creatorToReturn); } return toReturn; } diff --git a/src/util/orcid.js b/src/util/orcid.js new file mode 100644 index 00000000..5b1aea3f --- /dev/null +++ b/src/util/orcid.js @@ -0,0 +1,33 @@ +'use strict'; + +function generateCheckDigit(noHyphenOrcid) { + // https://support.orcid.org/hc/en-us/articles/360006897674-Structure-of-the-ORCID-Identifier + let total = 0; + let zero = '0'.charCodeAt(0); + for (let i = 0; i < 15; i++) { + let digit = noHyphenOrcid.charCodeAt(i) - zero; + total = (total + digit) * 2; + } + let result = (12 - (total % 11)) % 11; + return result === 10 ? 'X' : String(result); +} + +function okOrcid(orcid) { + // based on https://github.com/zimeon/orcid-feed-js + if (typeof orcid !== 'string') { + return false; + } + let noHyphenOrcid = orcid.replace( + /^(\d{4})-(\d{4})-(\d{4})-(\d\d\d[\dX])$/, + '$1$2$3$4', + ); + if (noHyphenOrcid === orcid) { + return false; + } + if (noHyphenOrcid.charAt(15) !== generateCheckDigit(noHyphenOrcid)) { + return false; + } + return true; +} + +module.exports = okOrcid; diff --git a/test/unit/orcid.js b/test/unit/orcid.js new file mode 100644 index 00000000..b3421edf --- /dev/null +++ b/test/unit/orcid.js @@ -0,0 +1,10 @@ +'use strict'; + +const okORCID = require('../../src/util/orcid'); + +it('test ORCID checksum calculation', () => { + expect(okORCID('0000-0003-4894-4660')).toBe(true); + expect(okORCID(undefined)).toBe(false); + expect(okORCID(39070)).toBe(false); + expect(okORCID('0000-0003-4894-4661')).toBe(false); +});