Skip to content

Commit

Permalink
migration script for badge instance data
Browse files Browse the repository at this point in the history
  • Loading branch information
josmas committed Sep 29, 2016
1 parent 2946507 commit 665e11d
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
.env
env.docker
.db.env
bin/badgekit_to_badgr/local.sqlite3
node_modules/
npm-debug.log
npm-debug.log.*
Expand Down
52 changes: 52 additions & 0 deletions bin/badgekit_to_badgr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Data Migration from badgekit-server to badgr-server

This section has its on environment file, and its own module dependencies (stated below) to avoid polluting the main app.

## How to generate the source database
Even though the _badgekit.db_ file is available directly in this folder, it was generated with: https://github.com/dumblob/mysql2sqlite and can be generated again as:

```
>./mysql2sqlite May_31_2016_362499FADFED219BBD3A417FC213E484.sql | sqlite3 badgekit.db
```

_May_31_2016_362499FADFED219BBD3A417FC213E484.sql_ is a dump of the badgekit
server used in PaperBadger.

### Investigating some of the data in the original DB

A csv file with data from badge instances can be generated from the badgekit.db
with:

```
sqlite> .header on
sqlite> .mode csv
sqlite> .once badgeinstances.csv
sqlite> select b.slug, a.* from badgeinstances a, badges b where a.badgeId=b.id;
sqlite> .exit
```

This is just to figure which parts of the info go into each table. The automated
migration created from this info can be run with `node migrateBKtoBS.js`.

## How to generate the destination database
_badges_only.local.sqlite3_ was created manually by inserting only badges
information directly through the badgr-server interface (note: this can be
automated).

## Running the script
Note that the script at _migrateBKtoBS.js_ only migrates data for badge instances.

A few packages are needed to run this script:

`npm install sqlite3 fs-extra`

Then simply:

`node migrateBKtoBS.js`

At the moment of writing, 294 instances will be migrated.

### Location of the badgr-server
The URL of the badgr-server is necessary for a number of fields in the instances
(such as where images are going to be available from). There is a _default.db.env_
file that can be customised locally as _.db.env_. Environment variables can also be used.
Binary file added bin/badgekit_to_badgr/badgekit.db
Binary file not shown.
Binary file added bin/badgekit_to_badgr/badges_only.local.sqlite3
Binary file not shown.
6 changes: 6 additions & 0 deletions bin/badgekit_to_badgr/default.db.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copy this file to .db.env or just set these environment variables

# Badgr
export BADGR_ENDPOINT=http://localhost:8000/
export BADGR_USER=#############
export BADGR_PASSWORD=#############
144 changes: 144 additions & 0 deletions bin/badgekit_to_badgr/migrateBKtoBS.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
'use strict';

var sqlite3 = require('sqlite3');
var fs = require('fs-extra');

var env = (function () {
var Habitat = require('habitat');
Habitat.load('.db.env');
Habitat.load('default.db.env');
return new Habitat();
})();

// Make a Sync copy of the DB with badges to get started with
fs.copySync('badges_only.local.sqlite3', 'local.sqlite3');

// Destination DB for badge instances
var badgesDB = new sqlite3.Database('local.sqlite3', function(err){
if (err) {
throw err;
}
});

// Source DB for badge instances; exported from badgekit-server
var bkDB = new sqlite3.Database('badgekit.db', function(err){
if (err) {
throw err;
}
});

function lookUpBadgeData(badgesList, dataItem) {
var badgeData = {};
badgesList.forEach(function(item){
// A few of the slugs are different in the two databases, in some cases the difference is just an underscore, but
// in other cases (like the three below) the full name is different. The ones without difference are taken care of
// in the first if statement.
if (item.slug.replace(/-/g, '') === dataItem.slug.replace(/_/g, '')) {
badgeData = { 'image': item.image, 'id': item.id };
}

if (item.slug === 'funding-acquisition' && dataItem.slug === 'funding' ) {
badgeData = { 'image': item.image, 'id': item.id };
}

if (item.slug === 'writing-original-draft' && dataItem.slug === 'writing_initial' ) {
badgeData = { 'image': item.image, 'id': item.id };
}

if (item.slug === 'writing-review-editing' && dataItem.slug === 'writing_review' ) {
badgeData = { 'image': item.image, 'id': item.id };
}
});

return badgeData;
}

function insertToInstance(badgesIdSlug, data) {
console.info(data);
var badgeData = lookUpBadgeData(badgesIdSlug, data);

var serverUrl = env.get('BADGR_ENDPOINT') + 'public/';
// using data.newSlug instead of generating a new UID (it is a UID in the original DB).
var jsonAssertion = {
'issuedOn': data.issuedOn,
'uid': data.newSlug,
'verify': {
'url': serverUrl + 'assertions/' + data.newSlug,
'type': 'hosted'
},
'image': serverUrl + 'assertions/' + data.newSlug + '/image',
'recipient': { // Not real credentials
'type': 'email',
'salt': '4a5b2567-83e7-43b4-bf42-c2530377c953',
'hashed': true,
'identity': 'sha256$98b1d080e491f9df4504ff5fc11b16e73de75043b4eada358e22f58206fd10a9'
},
'evidence': data.evidenceUrl,
'type': 'Assertion',
'@context': 'https://w3id.org/openbadges/v1',
'badge': serverUrl + 'badges/' + data.slug,
'id': serverUrl + 'assertions/' + data.newSlug
};

var recipient = {
'id': data.id,
'created_at': data.issuedOn,
'json': jsonAssertion,
'slug': data.newSlug,
'image': badgeData.image,
'revoked': false,
'revocation_reason': '',
'created_by_id': 1, // Hardcoded from b@d.gr user
'issuer_id': 2, // Hardcoded from b@d.gr user's first issuer
'identifier': 'get_full_url',
'recipient_identifier': data.email,
'badgeclass_id': badgeData.id
};

badgesDB.run('INSERT INTO issuer_badgeinstance VALUES(:id, :created_at, :json, :slug, :image,' +
':revoked, :revocation_reason, :created_by_id, :issuer_id, :identifier, :recipient_identifier,' +
':badgeclass_id)', {
':id': recipient.id,
':created_at': new Date(recipient.created_at),
':json': JSON.stringify(recipient.json),
':slug': recipient.slug,
':image': recipient.image,
':revoked': recipient.revoked,
':revocation_reason': recipient.revocation_reason,
':created_by_id': recipient.created_by_id,
':issuer_id': recipient.issuer_id,
':identifier': recipient.identifier,
':recipient_identifier': recipient.recipient_identifier,
':badgeclass_id': recipient.badgeclass_id
}, function(e){
if (e) {
console.log(e);
console.log('Failed id: ' , recipient.id); // Let other queries run anyway
}
});

}

badgesDB.serialize(function(){
badgesDB.all('SELECT slug, id, image FROM issuer_badgeclass', function(err, badgesIdSlug) {

bkDB.serialize(function(){
bkDB.all('select a.id, b.slug, a.slug as newSlug, a.email, a.issuedOn, a.evidenceUrl from badgeinstances a, ' +
'badges b where a.badgeId=b.id', function(er, data){

if (er) {
throw er;
}

data.forEach(function(dataItem){
insertToInstance(badgesIdSlug, dataItem);
});

// Close both DBs
badgesDB.close();
bkDB.close();
});
});

});
});

0 comments on commit 665e11d

Please sign in to comment.