Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
74dde50
GPII-3138: Added CouchDB views for retrieving snapset data.
cindyli Jun 27, 2018
ee30bb2
GPII-3138: Update snapsets in the data base
klown Jul 6, 2018
1c0f38a
GPII-3138: Update snapsets in the data base
klown Jul 6, 2018
b5dd8c0
GPII-3138: Update snapsets in the data base
klown Jul 6, 2018
f7068c0
GPII-3138: Update snapsets in the data base
klown Jul 9, 2018
e2f4e63
GPII-3138: Update snapsets in the data base
klown Jul 9, 2018
554ae82
GPII-3138: Update snapsets in the data base
klown Jul 9, 2018
f145f66
GPII-3138: Delete and reload snapsets in the data base
klown Jul 10, 2018
8f54a33
GPII-3138: Merged upstream master GPII branch into GPII-3138
klown Jul 16, 2018
67f7bd6
GPII-3138: Add a couchDB view to return all GPII keys.
cindyli Jul 18, 2018
c48d7ae
Merge pull request #1 from cindyli/GPII-3138
klown Jul 18, 2018
f029df2
GPII-3138: Merged Cindy's pull request with new database view
klown Jul 18, 2018
5f2f1b5
GPII-3138: Delete and (re)load snapsets into the database
klown Jul 20, 2018
750cdf3
GPII-3138: Delete and reload snapsets into the database
klown Jul 23, 2018
0e41600
GPII-3138: Delete and reload snapsets into the database
klown Jul 24, 2018
22d6605
GPII-3138: Delete and load snapsets Prefs Safes.
klown Jul 25, 2018
574236f
GPII-3138: Delete and load snapsets Prefs Safes into the database.
klown Jul 25, 2018
d6547d3
GPII-3138: Delete and load snapsets Prefs Safes into the database.
klown Jul 25, 2018
8520379
GPII-3138: Delete and load snapsets into the database
klown Jul 25, 2018
ef1e721
GPII-3138: Merged upstream GPII master branch.
klown Jul 26, 2018
0181c42
GPII-3138: Delete and load snapsets into the database
klown Jul 27, 2018
9bb64af
GPII-3138: Update snapsets into the database
klown Jul 30, 2018
a4541ba
GPII-3138: Update snapsets into the database
klown Jul 30, 2018
e026465
GPII-3138: Merged changes from upstreasm master GPII branch.
klown Jul 31, 2018
f4c41a6
GPII-3138: Update snapsets into the database
klown Jul 31, 2018
6723b6e
GPII-3138: Update snapsets into the database
klown Jul 31, 2018
2e0bb55
GPII-3138: Update snapsets into the database
klown Jul 31, 2018
fae02da
GPII-3138: Use UUIDs for demo user keys as well as creating 20 empty …
cindyli Aug 1, 2018
831a762
Merge pull request #2 from cindyli/GPII-3138
klown Aug 1, 2018
582b3d7
GPII-3138: Update snapsets in the database
klown Aug 5, 2018
c401c97
GPII-3138: Update snapsets in the database
klown Aug 7, 2018
54defe7
GPII-3138: Update snapsets in the database
klown Aug 7, 2018
58fdde7
GPII-3138: Update snapsets in the database
klown Aug 9, 2018
0862af6
GPII-3138: Merged changes from upstream master GPII branch.
klown Aug 10, 2018
79abd7d
GPII-3138: Merged changes from upstream master GPII branch
klown Aug 27, 2018
2b8cbeb
GPII-3138: Update snapsets in the database
klown Aug 28, 2018
59f03a8
GPII-3138: Update snapsets in the database
klown Aug 30, 2018
6ee716e
GPII-3138: Update snapsets in the database
klown Sep 10, 2018
9a090a1
GPII-3138: Update snapsets in the database
klown Sep 11, 2018
a9eec11
GPII-3138: Update snapsets in the database
klown Sep 11, 2018
a4cf452
GPII-3138: Update snapsets in the database
klown Sep 12, 2018
63c1a11
GPII-3138: Update snapsets in the database
klown Sep 13, 2018
7ce1b84
GPII-3138: Update snapsets in the database
klown Sep 18, 2018
afc6888
GPII-3138: Update snapsets in the database
klown Sep 19, 2018
75456ba
GPII-3138: Update snapsets in the database
klown Sep 19, 2018
230c8f0
GPII-3138: Update snapsets in the database
klown Sep 19, 2018
23b27e4
GPII-3138 Merged upstream master GPII branch
klown Oct 9, 2018
33f1741
GPII-3138: Update snapsets in the database.
klown Oct 9, 2018
2c48ca5
GPII-3138: Update snapsets in the database
klown Oct 11, 2018
d9ac25e
GPII-3138: Update snapsets in the database
klown Oct 15, 2018
ebde69d
GPII-3138: Update snapsets in the database
klown Oct 17, 2018
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
4 changes: 2 additions & 2 deletions scripts/convertPrefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ https://github.com/GPII/universal/blob/master/LICENSE.txt
*/

// This script reads files from an input directory that contains preferences JSON5 files and convert them to JSON files of GPII keys and
// preferences safes suitable for direct loading into CouchDB or PouchDB, which comply with the new GPII data model:
// preferences safes suitable for direct loading into CouchDB or PouchDB, which comply with the new GPII data model:
// https://wiki.gpii.net/w/Keys,_KeyTokens,_and_Preferences in the target directory
// Usage: node scripts/convertPrefs.js {input_path} {target_path}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the usage too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

//
Expand Down Expand Up @@ -61,7 +61,7 @@ rimraf(targetDir, function () {
"_id": prefsSafeId,
"type": "prefsSafe",
"schemaVersion": "0.1",
"prefsSafeType": "user",
"prefsSafeType": "snapset",
"name": gpiiKey,
"password": null,
"email": null,
Expand Down
162 changes: 162 additions & 0 deletions scripts/deleteSnapsets.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*!
Copyright 2018 OCAD University
Licensed under the New BSD license. You may not use this file except in
compliance with this License.
You may obtain a copy of the License at
https://github.com/GPII/universal/blob/master/LICENSE.txt
*/

// This script modifies the preferences data base:
// 1. Finds all the Prefs Safes of type "snapset" (prefsSafesType = "snapset"),
// 2. Finds all the GPII Keys associated with each snapset Prefs Safe
// 3. Deletes the found Prefs Safes and associated GPII Keys
//
// A sample command that runs this script:
// node deleteSnapsets.js $COUCHDBURL

"use strict";

var http = require("http"),
url = require("url"),
fluid = require("infusion");

var gpii = fluid.registerNamespace("gpii");
fluid.registerNamespace("gpii.dataLoader");
fluid.setLogging(fluid.logLevel.INFO)

var dbLoader = gpii.dataLoader;
dbLoader.couchDbUrl = process.argv[2];
if (!fluid.isValue(dbLoader.couchDbUrl)) {
fluid.log ("COUCHDB_URL environment variable must be defined");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be useful to also output the command usage: node deleteSnapsets.js $COUCHDBURL

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

process.exit(1);
}
fluid.log("COUCHDB_URL: '" + dbLoader.couchDbUrl + "'");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

COUCHDB_URL can (and usually will) contain credentials. Please do not write it to the log without sanitization.

It looks like url.parse may be helpful in reporting useful data like hostname without reporting sensitive data like password.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out, @mrtyler. I've gone with logging the

  • protocol
  • host
  • port
  • pathname

I don't think any of those contain sensitive information, but I could be wrong. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

dbLoader.prefsSafesViewUrl = dbLoader.couchDbUrl + "/_design/views/_view/findSnapsetPrefsSafes";
dbLoader.gpiiKeyViewUrl = dbLoader.couchDbUrl + "/_design/views/_view/findGpiiKeysByPrefsSafeId";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think to define the full url here to provide a general view: dbLoader.gpiiKeyViewUrl = dbLoader.couchDbUrl + "/_design/views/_view/findGpiiKeysByPrefsSafeId%22%gpiiKey%22". When this var is used later on, replace %gpiiKey with actual key values using fluid.stringTemplate().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we now use the get-all-gpiikeys view, this is no longer needed -- "overtaken by events".

dbLoader.parsedCouchDbUrl = url.parse(dbLoader.couchDbUrl);
dbLoader.docsToRemove=[];

/**
* Find the Prefs Safes of type "snapSet", add them to an array of records to
* remove, then use them to find their associated GPII Key(s).
* @param {Object} response - The response from the data base containing the
* snapSet Prefs Safes as a JSON string.
*/
dbLoader.processSnapsets = function (response) {
var snapSetsString = "";
response.setEncoding("utf8");
response.on("data", function (chunk) {
snapSetsString += chunk;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See below

});
response.on("end", function () {
dbLoader.snapSets = JSON.parse(snapSetsString);
fluid.each(dbLoader.snapSets.rows, function (aSnapset) {
aSnapset.value._deleted = true;
dbLoader.docsToRemove.push(aSnapset.value);
});
dbLoader.addGpiiKeysAndBulkDelete(dbLoader.snapSets.rows, dbLoader.docsToRemove);
});
};

/**
* Find the GPII key records associated with the given snapset Prefs Safes,
* delete each one as found, and then batch delete all the snapset Prefs Safes.
* @param {Array} snapSets - The snapsets of interest.
* @param {Array} docsToRemove - Array of records to delete.
*/
dbLoader.addGpiiKeysAndBulkDelete = function (snapSets, docsToRemove) {
fluid.each(snapSets, function (aSnapset) {
var gpiiKeyId = aSnapset.value._id;
fluid.log("Snapset: " + gpiiKeyId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output a more meaningful message such as "Finding GPII keys associated with the snapset prefs safe id: ".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated all the log messages to be very simple, such as you have suggested. Actual snapset or gpiikeys internal information such as the "_id" field are no longer logged.

var gpiiKeyViewUrl = dbLoader.gpiiKeyViewUrl + "?key=%22" + gpiiKeyId + "%22";
var getGpiiKeysRequest = http.request(gpiiKeyViewUrl, function (resp) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worrying lack of abstraction in all of this work. At the least there should be a wrapper for the process of invoking an HTTP request and waiting for responses from it as some kind of promise-producer. I don't want to slow down this work one atom so I'm not suggesting that it be re-expressed using https://github.com/fluid-project/kettle/blob/master/docs/DataSources.md#simple-example-of-using-an-http-datasource but something needs to happen to unwrap the tangle in this method which by line 88 we are 4 closures deep. It's hard to follow this expression of the algorithm, it is brittle, and seems prone to races which are already causing confusion. Also consider utilities like https://docs.fluidproject.org/infusion/development/PromisesAPI.html#fluidpromisesequencesources-options

var respString = "";
resp.setEncoding("utf8");
resp.on("data", function (chunk) {
respString += chunk;
});
// This response "end" event doesn't finish until after the call to
// doBatchDelete() below, which is too late to add the GPII Key to
// docsToRemove and have them removed.
// Note - if there is a way to determine the final "end" event, then
// it could call doBatchDelete().
resp.on("end", function () {
var gpiiKeyRecords = JSON.parse(respString);
fluid.each(gpiiKeyRecords.rows, function (gpiiKey) {
fluid.log("GPII Key: " + gpiiKey.value._id);
dbLoader.deleteGpiiKey(gpiiKey.value);
});
});
});
getGpiiKeysRequest.on("error", function (e) {
fluid.log("Error finding snapsets' associated GPII Keys: " + e.message);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be "snapset's", unless the error message is going to contain errors from all the snapsets that failed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The closest log message to this old one now has no apostrophe: "Error finding snapset Prefs Safes associated GPII Keys".

});
getGpiiKeysRequest.end();
});
dbLoader.doBatchDelete(docsToRemove);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting all prefs safe records here at the end of the script doesn't guarantee it to be run as the last task due to the aync nature of http requests above for getting and deleting gpii keys.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but it's another instance of "overtaken by events": The latest code handles the asynchrony.

};

/**
* Delete the given GPII Key record.
* @param {Object} gpiiKey - The key to delete.
*/
dbLoader.deleteGpiiKey = function (gpiiKey) {
var deleteOptions = {
hostname: dbLoader.parsedCouchDbUrl.hostname,
port: dbLoader.parsedCouchDbUrl.port,
path: "", // filled in below.
method: "DELETE",
headers: {
"Accept": "application/json"
}
};
deleteOptions.path = "/gpii/" + gpiiKey._id + "?rev=" + gpiiKey._rev;
var deleteGpiiKeyRequest = http.request(deleteOptions, function (res) {
fluid.log("STATUS: " + res.statusCode);
fluid.log("HEADERS: " + JSON.stringify(res.headers, null, 2));
});
deleteGpiiKeyRequest.on("error", function (e) {
fluid.log("Error finding GPII Key: " + e.message);
});
deleteGpiiKeyRequest.end();
};

/**
* Delete the snapset Prefs Safes and their associated GPII Keys.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function only deletes prefs safes, not gpii keys.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the use of promises, this now does delete all prefs safes and associated gpii keys.

* @param {Array} docsToRemove - Array of records to delete.
*/
dbLoader.doBatchDelete = function (docsToRemove) {
var batchDeleteOptions = {
hostname: dbLoader.parsedCouchDbUrl.hostname,
port: dbLoader.parsedCouchDbUrl.port,
path: "/gpii/_bulk_docs",
method: "POST",
headers: {
"Accept": "application/json",
"Content-Length": 0, // filled in below
"Content-Type": "application/json"
}
};
var batchPostData = JSON.stringify({"docs": docsToRemove});
batchDeleteOptions.headers["Content-Length"] = Buffer.byteLength(batchPostData);
var batchDeleteReq = http.request(batchDeleteOptions, function (res) {
fluid.log("STATUS: " + res.statusCode);
fluid.log("HEADERS: " + JSON.stringify(res.headers, null, 2));
res.on('end', function () {
fluid.log('Batch deletion of snapsets');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snapsets -> snapset prefs safes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the refactoring, the log message includes "Prefs Safes", and also "GPII Keys".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is clearer as "Finished batch deletion of..."?

Copy link
Member Author

@klown klown Jul 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one is now "Bulk deletion completed."

});
});
batchDeleteReq.on('error', function (e) {
fluid.log("Error deleting snapset Prefs Safes: " + e.message);
});
batchDeleteReq.write(batchPostData);
batchDeleteReq.end();
};

dbLoader.snapSetsRequest = http.request(dbLoader.prefsSafesViewUrl, dbLoader.processSnapsets);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The couchdb url on the GPII cloud might be using https instead http. Will find out by testing with the developer cloud.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any progress on this, @cindyli ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about the confusion. I meant YOU will find out when testing with the cloud, not me. It's also worth to check with @mrtyler on this information since production/staging might act differently than dev clusters.

dbLoader.snapSetsRequest.on("error", function (e) {
fluid.log("Error finding snapsets Prefs Safes: " + e.message);
});
dbLoader.snapSetsRequest.end();
12 changes: 9 additions & 3 deletions scripts/vagrantCloudBasedContainers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,15 @@ COUCHDB_IMAGE=couchdb
COUCHDB_PORT=5984
COUCHDB_HEALTHCHECK_DELAY=2
COUCHDB_HEALTHCHECK_TIMEOUT=30
if [ "$NO_REBUILD" == "true" ] ; then
CLEAR_INDEX=
else
CLEAR_INDEX=1
fi

STATIC_DATA_DIR="/home/vagrant/sync/universal/testData/dbData"
BUILD_DATA_DIR="/home/vagrant/sync/universal/build/dbData"
UNIVERSAL_DIR="/home/vagrant/sync/universal"
STATIC_DATA_DIR="$UNIVERSAL_DIR/testData/dbData"
BUILD_DATA_DIR="$UNIVERSAL_DIR/build/dbData"

DATALOADER_IMAGE="gpii/gpii-dataloader"
DATALOADER_COUCHDB_URL="http://couchdb:${COUCHDB_PORT}/gpii"
Expand Down Expand Up @@ -77,7 +83,7 @@ docker run -d -p $COUCHDB_PORT:$COUCHDB_PORT --name couchdb $COUCHDB_IMAGE
wget -O /dev/null --retry-connrefused --waitretry=$COUCHDB_HEALTHCHECK_DELAY --read-timeout=20 --timeout=1 --tries=$COUCHDB_HEALTHCHECK_TIMEOUT http://localhost:$COUCHDB_PORT

# Load the CouchDB data
docker run --rm --link couchdb -v $STATIC_DATA_DIR:/static_data -e STATIC_DATA_DIR=/static_data -v $BUILD_DATA_DIR:/build_data -e BUILD_DATA_DIR=/build_data -e COUCHDB_URL=$DATALOADER_COUCHDB_URL -e CLEAR_INDEX=1 $DATALOADER_IMAGE
docker run --rm --link couchdb -v $STATIC_DATA_DIR:/static_data -e STATIC_DATA_DIR=/static_data -v $BUILD_DATA_DIR:/build_data -e BUILD_DATA_DIR=/build_data -e COUCHDB_URL=$DATALOADER_COUCHDB_URL -e CLEAR_INDEX=$CLEAR_INDEX -v $UNIVERSAL_DIR:/universal -e NODE_PATH=/universal $DATALOADER_IMAGE

# Wait for the CouchDB views become accessible. Accessing the view URL forced the view index to build which take time.
# The URL returns 500 when the index is not ready, so use "--retry-on-http-error" option to continue retries at 500 response code.
Expand Down
6 changes: 6 additions & 0 deletions testData/dbData/views.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
},
"findAuthorizationByAccessToken": {
"map": "function(doc) {if (doc.type === 'gpiiAppInstallationAuthorization' && doc.revoked === false) {emit(doc.accessToken, {'_id': doc.clientId, 'authorization': doc})}}"
},
"findSnapsetPrefsSafes": {
"map": "function(doc) {if (doc.type === 'prefsSafe' && doc.prefsSafeType === 'snapset') {emit(doc._id, doc)}}"
},
"findGpiiKeysByPrefsSafeId": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This view is no longer used and can be removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, deleted.

"map": "function(doc) {if (doc.type === 'gpiiKey') {emit(doc.prefsSafeId, doc)}}"
}
}
}
Expand Down