diff --git a/.gitignore b/.gitignore index d074aac329494a87b34f005d21d280a96b42c844..4a4d573d925083d5124d2effb6d876166b82230a 100644 --- a/.gitignore +++ b/.gitignore @@ -41,8 +41,8 @@ bower_components build/Release # Dependency directories -node_modules/ -jspm_packages/ +**node_modules/ +**jspm_packages/ # Typescript v1 declaration files typings/ diff --git a/app.js b/login/app.js similarity index 69% rename from app.js rename to login/app.js index e0813426995fafaffcd91c9e4de8e2fb563dafa0..d187f73a03641759af0be1d7b6e8b55e6c080f2e 100644 --- a/app.js +++ b/login/app.js @@ -17,14 +17,4 @@ app.use(express.static(path.join(__dirname, 'public'))); app.use('/', indexRouter); app.use('/users', usersRouter); -app.get("/user/:userid/", function (req, res) { - res.send({test: 'data'}); -}); - -app.get("/:str/blah/:name/:id", function (req, res) { - res.send("Get request to " + req.url + " was received!"); - res.send(req.params); -}); - - module.exports = app; diff --git a/login/bin/www b/login/bin/www new file mode 100755 index 0000000000000000000000000000000000000000..402db4725f804680db31c126543a552be9b9206a --- /dev/null +++ b/login/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('login:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/login/package.json b/login/package.json new file mode 100644 index 0000000000000000000000000000000000000000..b68cb9c85d5ab775ffd7a9e5942f7fde4b0e052e --- /dev/null +++ b/login/package.json @@ -0,0 +1,14 @@ +{ + "name": "login", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "cookie-parser": "~1.4.3", + "debug": "~2.6.9", + "express": "~4.16.0", + "morgan": "~1.9.0" + } +} diff --git a/login/public/index.html b/login/public/index.html new file mode 100644 index 0000000000000000000000000000000000000000..ab1ad8a94fe2f508b199d111855f322c1fb20bee --- /dev/null +++ b/login/public/index.html @@ -0,0 +1,13 @@ +<html> + +<head> + <title>Express</title> + <link rel="stylesheet" href="/stylesheets/style.css"> +</head> + +<body> + <h1>Express</h1> + <p>Welcome to Express</p> +</body> + +</html> diff --git a/login/public/stylesheets/style.css b/login/public/stylesheets/style.css new file mode 100644 index 0000000000000000000000000000000000000000..9453385b9916ce9bc5e88d2f5d8cd8a554223590 --- /dev/null +++ b/login/public/stylesheets/style.css @@ -0,0 +1,8 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} diff --git a/routes/index.js b/login/routes/index.js similarity index 100% rename from routes/index.js rename to login/routes/index.js diff --git a/routes/users.js b/login/routes/users.js similarity index 64% rename from routes/users.js rename to login/routes/users.js index 93721a074d853c1891cd6f1b40bf78bb90b2cfa8..623e4302bee32ccc080d1c83ee2e55a426c9bac8 100644 --- a/routes/users.js +++ b/login/routes/users.js @@ -6,8 +6,4 @@ router.get('/', function(req, res, next) { res.send('respond with a resource'); }); -router.get('/:id', function(req, res, next) { - res.send("information about user with ID " + req.params.id); -}); - module.exports = router; diff --git a/misc/import_memberdb.js b/misc/import_memberdb.js index 33de5d96b2057adc19b1011de4e70b171be5d602..3701edc6cd8d34938e83723fd178e66848032747 100755 --- a/misc/import_memberdb.js +++ b/misc/import_memberdb.js @@ -8,7 +8,7 @@ const conf = require('./pg.json'); const Member = require('../models/memberSchema'); const TLA = require('../models/tlaSchema'); const Fuse = require('fuse.js'); -const tlaParse = require('./tlaParser'); +const tlaParser = require('./tlaParser'); /* DEPRECATED: specify stuff via environment variables PGUSER=uccmemberdb PGHOST=localhost PGPASSWORD=[redacted] PGDATABASE=uccmemberdb_2018 PGPORT=5432 node misc/import_memberdb.js @@ -54,7 +54,9 @@ db.once('open', function() { }); const tlafile = process.argv[2]; -var tlas = tlaParse(tlafile); +var tlas = tlaParser.parse(tlafile); +tlaParser.print(tlas); +console.log('Finished parsing TLAs, got ' + tlas.length + ' different TLAs.'); /** old memberdb schema from postgresql: CREATE TABLE memberdb_member ( @@ -99,9 +101,6 @@ function processOldMembers(err, res) { }; function matchTLAs(members) { - // clone original TLA array so we can remove TLAs we find and end up with a list of unclaimed TLAs. - var tlasUnused = tlas.slice(0); - // Fuse doesn't like to search across multiple fields so we have to combine firstname and lastname again to make it work. var fixedTLAs = []; for (var i = 0; i < tlas.length; i++) { @@ -124,26 +123,61 @@ function matchTLAs(members) { }; var fuse = new Fuse(fixedTLAs, options); // "list" is the item array + var saved = 0; + var toSave = 0; + + function tryCloseDB() { + saved += 0.5; + if (saved == toSave) { + // everything is saved, time to stop. + db.close(function (err) { + if (err) { + console.warn(err); + console.warn("could not close mongodb connection!"); + } else { + console.log("closed mongodb connection."); + } + }); + } + } + // now loop through members and find their TLAs for (var mi = 0; mi < members.length; mi++) { var m = members[mi]; + var results = fuse.search(m.firstname + " " + m.lastname); // console.log("searching for tlas for " + m.firstname + " " + m.lastname); if (results.length > 0) { console.log(m.firstname + " has " + results.length + " tlas, using [" + results[0].tla + "]"); // Some false positives: only use the first TLA. m.tlas = [results[0].tla]; - var usedId = tlasUnused.indexOf(results[0].tla); - tlasUnused.splice(usedId, usedId + 1); - m.save(); + + // Update Member to include TLAs we found + toSave++; + m.save(function (err) { + // since the saving is done asynchronously, we need to close the db after everything has been saved. + if (err) { + console.warn("error saving TLA to member!"); + console.warn(err); + } + tryCloseDB(); + }); + + // query and update TLA document so we can associate it with a member. + TLA.findOneAndUpdate({tla: results[0].tla}, {_memberId: m._id}, function (err, doc) { + if (err) { + console.warn(err); + } + console.warn("Updated TLA [" + doc.tla + "] with member ID " + doc._memberId); + tryCloseDB(); + }); } if (results.length == 0) { // console.log(m.firstname + " has no TLA."); } } - console.log(tlas.length - tlasUnused.length + " TLAs assigned to members, total " + tlas.length + ", unclaimed " + (tlasUnused.length)); - return members; + console.log(toSave + " TLAs assigned to members, total " + tlas.length + ", unclaimed " + (tlas.length - toSave)); } function convertMember(row) { @@ -183,5 +217,4 @@ function convertMember(row) { function verifyMongoMembers(err, res) { console.log("Currently " + res.length + " members in mongodb."); matchTLAs(res); - db.close(); } \ No newline at end of file diff --git a/misc/tlaParser.js b/misc/tlaParser.js index e923f00589c654b584e8fcdf51528949b4cc317a..195d00de8d9769ce06c9c54a853a66cee88993c1 100644 --- a/misc/tlaParser.js +++ b/misc/tlaParser.js @@ -1,6 +1,6 @@ const fs = require('fs'); -module.exports = function parseTLAs(tlafile) { +module.exports.parse = function parseTLAs(tlafile) { console.log("Loading TLAs from '" + tlafile + "'..."); var tlas = []; try { @@ -40,15 +40,18 @@ module.exports = function parseTLAs(tlafile) { }; tlas.push(tla); console.log(tla.firstname + " / " + tla.lastname + " / " + tla.tla); - // process.stdout.write("[" + s[0] + "] " + ((tlas.length % 16 == 0) ? "\n" : "")); } - // process.stdout.write("\n"); } catch (err) { console.warn("Error parsing TLA data!"); console.warn(err); process.exit(1); } - - console.log('Finished parsing TLAs, got ' + tlas.length + ' different TLAs.'); return tlas; -} \ No newline at end of file +}; + +module.exports.print = function(tlas) { + for (var i = 0; i < tlas.length; i++) { + process.stdout.write("[" + tlas[i].tla + "] " + ((i % 16 == 15) ? "\n" : "")); + } + process.stdout.write("\n"); +}; \ No newline at end of file diff --git a/user/app.js b/user/app.js new file mode 100644 index 0000000000000000000000000000000000000000..9d4d489523eb979df6eaa993c92a3f7e0db4be3f --- /dev/null +++ b/user/app.js @@ -0,0 +1,20 @@ +var express = require('express'); +var path = require('path'); +var cookieParser = require('cookie-parser'); +var logger = require('morgan'); + +var indexRouter = require('./routes/index'); +var usersRouter = require('./routes/users'); + +var app = express(); + +app.use(logger('dev')); +app.use(express.json()); +app.use(express.urlencoded({ extended: false })); +app.use(cookieParser()); +//app.use(express.static(path.join(__dirname, 'public'))); + +app.use(indexRouter); +app.use('/users', usersRouter); + +module.exports = app; diff --git a/bin/www b/user/bin/www similarity index 93% rename from bin/www rename to user/bin/www index 130bb51e643ecbee01874cca037ddd2a6570f425..5c91add6d055e49338f740fe0e1e5c7467864970 100755 --- a/bin/www +++ b/user/bin/www @@ -21,7 +21,11 @@ server.on('listening', onHTTPListening); /** Connect to mongodb */ mongoose.connect('mongodb://localhost/uccportal-dev'); var db = mongoose.connection; -db.on('error', console.error.bind(console, 'db connection error:')); +db.on('error', function (err) { + console.warn(err); + console.warn("Error connecting to DB!"); + process.exit(1); +}); db.once('open', function() { console.log("Connected to db"); }); diff --git a/models/memberSchema.js b/user/models/memberSchema.js similarity index 73% rename from models/memberSchema.js rename to user/models/memberSchema.js index e00c595972894d57020c34671f02b29e6ad5c6de..e37996180812ca001e582c8924ff70e47a760a46 100644 --- a/models/memberSchema.js +++ b/user/models/memberSchema.js @@ -1,6 +1,11 @@ 'use strict'; const mongoose = require('mongoose'); +var renewalSchema = mongoose.Schema({ + renewtype: {type: String }, + date: { type: Date }, +}) + // Here we define the schema used by the model for gumby documents var memberSchema = mongoose.Schema({ firstname: String, @@ -12,9 +17,9 @@ var memberSchema = mongoose.Schema({ phone: String, birthdate: Date, username: String, - tlas: [String], + tlas: [ { type: String } ], signupdate: Date, - renewals: [{renewtype: String, date: Date}] + renewals: [ { type: renewalSchema } ] }); // And we export (return) a model based on the schema diff --git a/models/tlaSchema.js b/user/models/tlaSchema.js similarity index 78% rename from models/tlaSchema.js rename to user/models/tlaSchema.js index 8770569d4771fbf463646d04dd0f4c21c347cea4..145560a9050d487632f956fc828775af27bc238f 100644 --- a/models/tlaSchema.js +++ b/user/models/tlaSchema.js @@ -4,6 +4,7 @@ var tlaSchema = mongoose.Schema({ tla: String, // Three Letter Acronym firstname: String, // Name associated with TLA (even if a member, yes I know it's duplicated but TLAs are weird.) lastname: String, + _memberId: mongoose.Schema.Types.ObjectId, // ID of corresponding member if found }); module.exports = mongoose.model('TLA', tlaSchema); \ No newline at end of file diff --git a/package-lock.json b/user/package-lock.json similarity index 99% rename from package-lock.json rename to user/package-lock.json index 40b029c7e2bc809b0edf2158b51bf54c790129a7..025b34bc2f80f49c60f6963e548f42f3d1a6755e 100644 --- a/package-lock.json +++ b/user/package-lock.json @@ -1391,6 +1391,12 @@ } } }, + "fuse.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.2.0.tgz", + "integrity": "sha1-8ESOgGmFW/Kj5oPNwdMg5+KgfvQ=", + "dev": true + }, "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", diff --git a/package.json b/user/package.json similarity index 96% rename from package.json rename to user/package.json index 34a734671403c41fc0c5f7fabc40c38602b46e91..697af16560a57aed1e79490344e24f8a78026345 100644 --- a/package.json +++ b/user/package.json @@ -14,6 +14,7 @@ "author": "frekk", "license": "GPL-3.0-or-later", "devDependencies": { + "fuse.js": "^3.2.0", "nodemon": "^1.17.5", "pg": "^7.4.3" }, diff --git a/user/routes/index.js b/user/routes/index.js new file mode 100644 index 0000000000000000000000000000000000000000..09d3f4ed664e8653f4381534e368aa4c393dca85 --- /dev/null +++ b/user/routes/index.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.send("Welcome to UCCPortal REST API."); +}); + +module.exports = router; diff --git a/user/routes/tlas.js b/user/routes/tlas.js new file mode 100644 index 0000000000000000000000000000000000000000..13daddb86e0cb2d3006d488d0e4e11fddc7693df --- /dev/null +++ b/user/routes/tlas.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); +var TLA = require('../models/tlaSchema'); + +router.get('/:tla', function (req, res, next) { + +}); + +model.exports = router; \ No newline at end of file diff --git a/user/routes/users.js b/user/routes/users.js new file mode 100644 index 0000000000000000000000000000000000000000..3ee4031e32a7ba599bb276cf62976cd081c6b807 --- /dev/null +++ b/user/routes/users.js @@ -0,0 +1,30 @@ +var express = require('express'); +var router = express.Router(); +var Member = require('../models/memberSchema'); + +/* GET users listing. */ +router.get('/', function(req, res, next) { + Member.find({}).select('username -_id').exec(function (err, members) { + var r = []; + for (var i = 0; i < members.length; i++) { + if (members[i].username) { + r.push(members[i].username); + } + } + res.json(r); + }); +}); + +router.get('/:username', function(req, res, next) { + Member.find({username: req.params.username}).select('-_id').exec(function (err, d) { + res.json(d); + }); +}); + +router.get('/:username/tlas', function (req, res, next) { + Member.find({username: req.params.username}).select('tlas -_id').exec(function (err, d) { + res.json(d); + }) +}); + +module.exports = router;