Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration to Badgr-server; PaperBadger changes #210

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ Clone (or Fork) PaperBadger and enter the directory: `git clone https://github.c

For an overview of the [architecture](docs/high-level-architecture.md) of the system and other details, visit the [docs](docs/) section.

#### Badges Server
PaperBadger relies on [Badgr Server](https://github.com/concentricsky/badgr-server) to manage all actions related to
badges. You can install Badgr directly from github, or you can use this docker
[local-badgr-server](https://github.com/josmas/local-badgr-server) setup,
especially built for this project, to speed things up a little.

#### Environment variables
If you would like to override the default configuration, create an `.env` file in your favourite text editor and use _default.env_ as a template (do not delete or modify _default.env_).

Expand All @@ -45,11 +51,10 @@ If you would like to develop against the hosted custom badgekit-api we have runn
export PORT=5000
export SESSION_SECRET=USE_SOMETHING_GOOD_LIKE_puUJjfE6QtUnYryb

# Badges
export BADGES_ENDPOINT=http://badgekit-api-test-sciencelab.herokuapp.com/
export BADGES_KEY=master
export BADGES_SECRET=#############
export BADGES_SYSTEM=badgekit
# Badgr Server
export BADGR_ENDPOINT=http://localhost:8000/
export BADGR_USER=#############
export BADGR_PASSWORD=#############

# ORCID Auth
export ORCID_AUTH_CLIENT_ID=#############
Expand All @@ -58,8 +63,9 @@ If you would like to develop against the hosted custom badgekit-api we have runn
export ORCID_AUTH_TOKEN_PATH=#############
export ORCID_REDIRECT_URI=#############

Ask [@acabunoc](http://github.com/acabunoc) for ones marked `###########`. Our custom BadgeKit API code can be found [here](https://github.com/acabunoc/badgekit-api).
Feel free to change `PORT` to any available port.
Note that you will have to provide your own [Badgr](https://github.com/concentricsky/badgr-server) server, and register
for a development account with [ORCID](http://orcid.org/).

#### Run using Docker

Expand Down
14 changes: 8 additions & 6 deletions default.env
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@
export PORT=5000
export SESSION_SECRET=USE_SOMETHING_GOOD_LIKE_puUJjfE6QtUnYryb

# Badges
export BADGES_ENDPOINT=http://badgekit-api-test-sciencelab.herokuapp.com/
export BADGES_KEY=master
export BADGES_SECRET=#############
export BADGES_SYSTEM=badgekit
# Badgr Server
export BADGR_ENDPOINT=http://localhost:8000/
export BADGR_USER=#############
export BADGR_PASSWORD=#############

# ORCID Auth
export ORCID_AUTH_CLIENT_ID=#############
export ORCID_AUTH_CLIENT_SECRET=#############
export ORCID_AUTH_SITE=https://orcid.org
export ORCID_AUTH_TOKEN_PATH=https://orcid.org/oauth/token
export ORCID_AUTH_TOKEN_PATH=https://pub.orcid.org/oauth/token
export ORCID_REDIRECT_URI=http://localhost:5000/orcid_auth_callback

# MongoDB
export MONGOLAB_URI=mongodb://127.0.0.1:27017/test

# Redis
export REDISCLOUD_URL=redis://127.0.0.1:6379/0

# Email
export AWS_ACCESS_KEY=
export AWS_SECRET_KEY=
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build:js": "webpack --config webpack.config.js --progress --profile --colors",
"watch:js": "npm run build:js -- --watch",
"clean": "rm -r public/js/*",
"server": "node src/index.js",
"server": "nodemon src/index.js",
"eslint": "eslint --config .eslintrc.yaml src webpack.config.js public/widgets/widget.js",
"eslint:test": "eslint --config .eslintrc.yaml test",
"lint": "npm run eslint && npm run eslint:test",
Expand All @@ -21,6 +21,7 @@
"dependencies": {
"babel-loader": "^5.0.0",
"badgekit-api-client": "https://github.com/mozilla/badgekit-api-client/tarball/v0.2.4",
"badgr-client": "1.0.0",
"body-parser": "^1.13.2",
"connect-redis": "^3.0.1",
"es5-shim": "^4.1.1",
Expand All @@ -29,26 +30,27 @@
"express-session": "~1.11.2",
"habitat": "^3.1.2",
"imports-loader": "^0.6.4",
"pug": "^2.0.0-alpha8",
"jsx-loader": "^0.13.2",
"mofo-style": "^2.3.0",
"mongoose": "^4.1.4",
"nodemailer": "^1.4.0",
"nodemailer-ses-transport": "^1.3.0",
"npm-run-all": "^1.2.4",
"pug": "^2.0.0-alpha8",
"react": "^0.13.2",
"react-checkbox-group": "^0.1.9",
"react-router": "^0.13.3",
"shortid": "^2.2.2",
"simple-oauth2": "0.5.1",
"validator": "^5.2.0",
"webpack": "^1.8.11",
"whatwg-fetch": "^0.9.0",
"validator": "^5.2.0"
"whatwg-fetch": "^0.9.0"
},
"devDependencies": {
"eslint": "^2.3.0",
"mocha": "^2.2.5",
"nock": "^2.3.0",
"nodemon": "1.10.2",
"supertest": "^1.0.1"
},
"engines": {
Expand Down
4 changes: 2 additions & 2 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,12 @@ app.get('/orcid_auth_callback', function (request, response) {
} else {
// Token Page
request.session.orcid_token_error = oauth2.accessToken.create(result);
response.redirect('/orcid_token_error');
response.redirect('/denied');
}
} else {
// Token Page
request.session.orcid_token = oauth2.accessToken.create(result);
response.redirect(request.session.redirect || '/issue/');
response.redirect('/issue/');
}
});
});
Expand Down
8 changes: 4 additions & 4 deletions src/badges/client/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';

var ApiClient = require('badgekit-api-client');
var ApiClient = require('badgr-client');

module.exports = function (config) {
var auth = {
key: config.get('BADGES_KEY'),
secret: config.get('BADGES_SECRET')
username: config.get('BADGR_USER'),
password: config.get('BADGR_PASSWORD')
};

return new ApiClient(config.get('BADGES_ENDPOINT'), auth);
return new ApiClient(config.get('BADGR_ENDPOINT'), auth);
};
79 changes: 33 additions & 46 deletions src/badges/service/index.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
/* eslint camelcase: ["error", {properties: "never"}]*/
'use strict';

var path = require('path');
var helpers = require(path.join(process.cwd(), 'src', 'helpers'));

// We really want a singleton here
var instance, client, system;
var instance, client;

function BadgeService() {}

BadgeService.prototype.createBadge = function (orcid, badge, dois, name) {
BadgeService.prototype.createBadge = function (orcid, badge, dois) {
return function (callback) {
var evidence = helpers.urlFromDOI(dois._1, dois._2);
var context = {
system: system,
badge: badge,
instance: {
email: helpers.emailFromORCID(orcid),
evidenceUrl: evidence,
authorName: name
}

var options = {
issuerSlug: 'mozilla-science' // TODO Can we move this value to the library?
};
options.badgeSlug = badge;
options.recipient_identifier = helpers.emailFromORCID(orcid);
options.evidence = helpers.urlFromDOI(dois._1, dois._2);
options.create_notification = false;

client.createBadgeInstance(context, function (err, badgeResult) {
client.createBadgeInstance(options, function (err, badgeResult) {
if (err) {
console.error(err);
return callback(err);
Expand All @@ -34,56 +33,45 @@ BadgeService.prototype.createBadge = function (orcid, badge, dois, name) {

BadgeService.prototype.getBadges = function (orcid, badge, dois) {
return function (callback) {

var options = {
issuerSlug: 'mozilla-science' // TODO Can we move this value to the library?
};

// The client takes care of all the filtering, depending on the flags sent (evidence, badge, and recipient)
var evidenceUrl = dois ? helpers.urlFromDOI(dois._1, dois._2) : null;
if (evidenceUrl) {
options.evidence = evidenceUrl;
}

if (orcid) {
options.recipient = helpers.emailFromORCID(orcid);
}

if(badge) {
options.badgeSlug = badge;
}

var clientCallback = function (err, badges) {
var filtered;
if (err) {
console.error(err);
return callback(err);
}

// filter for the badge
if (badges) {
filtered = badges.filter(function (entry) {
var goodBadge = (!badge || entry.badge.slug === badge);
var goodDoi = (!dois || entry.evidenceUrl === evidenceUrl);
return goodBadge && goodDoi;
});

filtered = filtered.map(helpers.modEntry);
}

if (filtered && filtered.length === 0) {
if (badges && badges.length === 0) {
callback('client return empty result');
} else {
callback(null, filtered);
callback(null, badges);
}
};

var context = {
system: system
};
var options = {};
if (orcid) {
options.email = helpers.emailFromORCID(orcid);
} else {
context.badge = badge || '*';
}
if (evidenceUrl) {
options.paginate = {
evidenceUrl: evidenceUrl
};
}
client.getBadgeInstances(context, options, clientCallback);
client.getBadgeInstances(options, clientCallback);
};
};

BadgeService.prototype.getAllBadges = function () {
return function (callback) {
client.getAllBadges({
system: system
}, function (err, badges) {
client.getAllBadges(function (err, badges) {
if (err) {
console.error(err);
callback(err);
Expand All @@ -95,9 +83,8 @@ BadgeService.prototype.getAllBadges = function () {
};

module.exports = {
init: function (apiClient, config) {
init: function (apiClient) {
client = apiClient;
system = config.get('BADGES_SYSTEM');
},

getInstance: function () {
Expand Down
8 changes: 7 additions & 1 deletion src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ function DOIFromURL(url) {
return m[1];
}

function badgeClassFromURL(url) {
var badgeClass = url.split('/');
return badgeClass[badgeClass.length - 1];
}

module.exports = {
emailFromORCID: emailFromORCID,
ORCIDFromEmail: ORCIDFromEmail,
modEntry: modEntry,
urlFromDOI: urlFromDOI,
DOIFromURL: DOIFromURL
DOIFromURL: DOIFromURL,
badgeClassFromURL: badgeClassFromURL
};
3 changes: 1 addition & 2 deletions src/routes/papers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ function createBadges(request, response) {
response.status(400).end();
return;
}
var name = request.session.orcid_token.token.name;
var badges = request.body.badges || [request.param.badge];

// Delete the claim code once it's been used
Expand All @@ -204,7 +203,7 @@ function createBadges(request, response) {
var getTheBadges = badgerService.createBadge(request.params.orcid, badge, {
'_1': request.params.doi1,
'_2': request.params.doi2
}, name);
});
getTheBadges(function (error, aBadge) {
if (error !== null) {
console.log('Get error from return Badges ' + error);
Expand Down
4 changes: 2 additions & 2 deletions templates/components/badge.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ var Badge = React.createClass({
return (
<div className="badge pure-u-1-8">
<a href={slug} >
<img src={badge.imageUrl}/>
<img src={badge.image}/>
<span> {badge.name} </span>
</a>
</div>
);
}
});

module.exports = Badge;
module.exports = Badge;
28 changes: 22 additions & 6 deletions templates/components/badgeInstance.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,39 @@ var React = require('react');


var BadgeInstance = React.createClass({

// The following two functions also exist in helpers.js in the node codebase.
badgeClassFromURL: function(url) {
var badgeClass = url.split('/');
return badgeClass[badgeClass.length - 1];
},

ORCIDFromEmail: function(email) {
var orcidRe = /(\d{4}-\d{4}-\d{4}-\d{3}[\dX])@orcid\.org/;
var m = orcidRe.exec(email);
if (m !== null) {
return m[1];
}
},

render: function() {
var badgeInstance = this.props.badge,
doiRe = /(10\.\d{3}\d+)\/(.*)\b/,
m = doiRe.exec(badgeInstance.evidenceUrl),
m = doiRe.exec(badgeInstance.json.evidence),
paperUrl = '/v/#/papers/' + m[1] + '/' + encodeURIComponent(m[2]) + '/badges';

return (
<div className="badge pure-u-1-4">
<div className="pure-u-1-2">
<img src={ badgeInstance.badge.imageUrl }/>
<img src={ badgeInstance.json.image }/>
</div>
<h4><a href={ '/v/#/badges/' + badgeInstance.badge.slug }>{ badgeInstance.badge.name }</a></h4>
<a href={ '/v/#/users/' + badgeInstance.orcid + '/badges'}> { badgeInstance.orcid } </a><br />
<a href={ paperUrl } > { badgeInstance.evidenceUrl } </a>
<h4><a href={ '/v/#/badges/' + this.badgeClassFromURL(badgeInstance.badge_class) }>{ this.badgeClassFromURL(badgeInstance.badge_class) }</a></h4>
<a href={ '/v/#/users/' + this.ORCIDFromEmail(badgeInstance.recipient_identifier) + '/badges'}>
{ this.ORCIDFromEmail(badgeInstance.recipient_identifier) } </a><br />
<a href={ paperUrl } > { badgeInstance.json.evidence } </a>
</div>
);
}
});

module.exports = BadgeInstance;
module.exports = BadgeInstance;
Loading